diff --git a/src/main/org/apache/tools/ant/XmlLogger.java b/src/main/org/apache/tools/ant/XmlLogger.java index 34580ef01..3f09d5d40 100644 --- a/src/main/org/apache/tools/ant/XmlLogger.java +++ b/src/main/org/apache/tools/ant/XmlLogger.java @@ -58,6 +58,7 @@ import java.io.*; import java.util.*; import javax.xml.parsers.*; import org.w3c.dom.*; +import org.apache.tools.ant.util.DOMElementWriter; /** * Generates a "log.xml" file in the current directory with @@ -134,7 +135,7 @@ public class XmlLogger implements BuildListener { Writer out = new FileWriter(outFilename); out.write("\n\n"); - write(buildElement, out, 0); + (new DOMElementWriter()).write(buildElement, out, 0, "\t"); out.flush(); out.close(); @@ -228,63 +229,4 @@ public class XmlLogger implements BuildListener { } } - /** - * Writes a DOM element to a file. - */ - private static void write(Element element, Writer out, int indent) throws IOException { - - // Write indent characters - for (int i = 0; i < indent; i++) { - out.write("\t"); - } - - // Write element - out.write("<"); - out.write(element.getTagName()); - - // Write attributes - NamedNodeMap attrs = element.getAttributes(); - for (int i = 0; i < attrs.getLength(); i++) { - Attr attr = (Attr) attrs.item(i); - out.write(" "); - out.write(attr.getName()); - out.write("=\""); - out.write(attr.getValue()); - out.write("\""); - } - out.write(">"); - - // Write child attributes and text - boolean hasChildren = false; - NodeList children = element.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - - if (child.getNodeType() == Node.ELEMENT_NODE) { - if (!hasChildren) { - out.write("\n"); - hasChildren = true; - } - write((Element)child, out, indent + 1); - } - - if (child.getNodeType() == Node.TEXT_NODE) { - out.write(((Text)child).getData()); - } - } - - // If we had child elements, we need to indent before we close - // the element, otherwise we're on the same line and don't need - // to indent - if (hasChildren) { - for (int i = 0; i < indent; i++) { - out.write("\t"); - } - } - - // Write element close - out.write("\n"); - } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java index 590268509..0ddad9a18 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java @@ -23,7 +23,7 @@ * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * - * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software + * 4. The names "The Jakarta Project", "Ant", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. @@ -62,6 +62,7 @@ import java.util.*; import javax.xml.parsers.*; import org.w3c.dom.*; import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.util.DOMElementWriter; import junit.framework.Test; import junit.framework.TestCase; @@ -69,7 +70,7 @@ import junit.framework.TestCase; /** * Prints XML output of the test to a specified Writer. * - * @author Stefan Bodewig + * @author Stefan Bodewig */ public class XMLJUnitResultFormatter implements JUnitResultFormatter { @@ -120,7 +121,7 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter { public void startTestSuite(JUnitTest suite) { doc = getDocumentBuilder().newDocument(); rootElement = doc.createElement("testsuite"); - rootElement.setAttribute("name", xmlEscape(suite.getName())); + rootElement.setAttribute("name", suite.getName()); } /** @@ -137,7 +138,7 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter { try { wri = new OutputStreamWriter(out); wri.write("\n"); - write(rootElement, wri, 0); + (new DOMElementWriter()).write(rootElement, wri, 0, " "); wri.flush(); } catch(IOException exc) { throw new BuildException("Unable to write log file", exc); @@ -161,7 +162,7 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter { public void startTest(Test t) { lastTestStart = System.currentTimeMillis(); currentTest = doc.createElement("testcase"); - currentTest.setAttribute("name", xmlEscape(((TestCase) t).name())); + currentTest.setAttribute("name", ((TestCase) t).name()); rootElement.appendChild(currentTest); } @@ -208,9 +209,9 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter { String message = t.getMessage(); if (message != null && message.length() > 0) { - nested.setAttribute("message", xmlEscape(t.getMessage())); + nested.setAttribute("message", t.getMessage()); } - nested.setAttribute("type", xmlEscape(t.getClass().getName())); + nested.setAttribute("type", t.getClass().getName()); StringWriter swr = new StringWriter(); t.printStackTrace(new PrintWriter(swr, true)); @@ -218,97 +219,4 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter { nested.appendChild(trace); } - - /** - * Translates <, & , " and > to corresponding entities. - */ - private String xmlEscape(String orig) { - if (orig == null) return ""; - StringBuffer temp = new StringBuffer(); - StringCharacterIterator sci = new StringCharacterIterator(orig); - for (char c = sci.first(); c != CharacterIterator.DONE; - c = sci.next()) { - - switch (c) { - case '<': - temp.append("<"); - break; - case '>': - temp.append(">"); - break; - case '\"': - temp.append("""); - break; - case '&': - temp.append("&"); - break; - default: - temp.append(c); - break; - } - } - return temp.toString(); - } - - /** - * Writes a DOM element to a stream. - */ - private static void write(Element element, Writer out, int indent) throws IOException { - // Write indent characters - for (int i = 0; i < indent; i++) { - out.write("\t"); - } - - // Write element - out.write("<"); - out.write(element.getTagName()); - - // Write attributes - NamedNodeMap attrs = element.getAttributes(); - for (int i = 0; i < attrs.getLength(); i++) { - Attr attr = (Attr) attrs.item(i); - out.write(" "); - out.write(attr.getName()); - out.write("=\""); - out.write(attr.getValue()); - out.write("\""); - } - out.write(">"); - - // Write child attributes and text - boolean hasChildren = false; - NodeList children = element.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node child = children.item(i); - - if (child.getNodeType() == Node.ELEMENT_NODE) { - if (!hasChildren) { - out.write("\n"); - hasChildren = true; - } - write((Element)child, out, indent + 1); - } - - if (child.getNodeType() == Node.TEXT_NODE) { - out.write(""); - } - } - - // If we had child elements, we need to indent before we close - // the element, otherwise we're on the same line and don't need - // to indent - if (hasChildren) { - for (int i = 0; i < indent; i++) { - out.write("\t"); - } - } - - // Write element close - out.write("\n"); - } - } // XMLJUnitResultFormatter diff --git a/src/main/org/apache/tools/ant/util/DOMElementWriter.java b/src/main/org/apache/tools/ant/util/DOMElementWriter.java new file mode 100644 index 000000000..7f8234fcf --- /dev/null +++ b/src/main/org/apache/tools/ant/util/DOMElementWriter.java @@ -0,0 +1,218 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.util; + +import java.io.*; +import org.w3c.dom.*; + +/** + * Writes a DOM tree to a given Writer. + * + *

Utility class used by {@link org.apache.tools.ant.XmlLogger + * XmlLogger} and + * org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter + * XMLJUnitResultFormatter}.

+ * + * @author The original author of XmlLogger + * @author Stefan Bodewig + */ +public class DOMElementWriter { + + private static String lSep = System.getProperty("line.separator"); + private StringBuffer sb = new StringBuffer(); + + /** + * Don't try to be too smart but at least recognize the predefined + * entities. + */ + protected String[] knownEntities = {"gt", "amp", "lt", "apos", "quot"}; + + /** + * Writes a DOM tree to a stream. + * + * @param element the Root DOM element of the tree + * @param out where to send the output + * @param indent number of + * @param indentWith strings, + * that should be used to indent the corresponding tag. + */ + public void write(Element element, Writer out, int indent, + String indentWith) + throws IOException { + + // Write indent characters + for (int i = 0; i < indent; i++) { + out.write(indentWith); + } + + // Write element + out.write("<"); + out.write(element.getTagName()); + + // Write attributes + NamedNodeMap attrs = element.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + Attr attr = (Attr) attrs.item(i); + out.write(" "); + out.write(attr.getName()); + out.write("=\""); + out.write(encode(attr.getValue())); + out.write("\""); + } + out.write(">"); + + // Write child elements and text + boolean hasChildren = false; + NodeList children = element.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (!hasChildren) { + out.write(lSep); + hasChildren = true; + } + write((Element)child, out, indent + 1, indentWith); + } + + if (child.getNodeType() == Node.TEXT_NODE) { + out.write(""); + } + } + + // If we had child elements, we need to indent before we close + // the element, otherwise we're on the same line and don't need + // to indent + if (hasChildren) { + for (int i = 0; i < indent; i++) { + out.write(" "); + } + } + + // Write element close + out.write(""); + out.write(lSep); + } + + /** + * Escape <, & and " as their entities. + */ + public String encode(String value) { + sb.setLength(0); + for (int i=0; i. + */ + +package org.apache.tools.ant.util; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Tests for org.apache.tools.ant.util.DOMElementWriter. + * + * @author Stefan Bodewig + */ +public class DOMElementWriterTest extends TestCase { + + private DOMElementWriter w = new DOMElementWriter(); + + public DOMElementWriterTest(String name) { + super(name); + } + + public void testIsReference() { + assert("", w.isReference("")); + assert(" ", w.isReference(" ")); + assert(" ", w.isReference(" ")); + assert("&#A0;", !w.isReference("&#A0;")); + assert("20;", !w.isReference("20;")); + assert("", !w.isReference("")); + assert(""", w.isReference(""")); + assert("'", w.isReference("'")); + assert(">", w.isReference(">")); + assert("<", w.isReference("<")); + assert("&", w.isReference("&")); + } + + public void testEncode() { + assertEquals("", w.encode("")); + assertEquals(" ", w.encode(" ")); + assertEquals(" ", w.encode(" ")); + assertEquals("&#A0;", w.encode("&#A0;")); + assertEquals("20;", w.encode("20;")); + assertEquals("&#20", w.encode("")); + assertEquals(""", w.encode(""")); + assertEquals("'", w.encode("'")); + assertEquals(">", w.encode(">")); + assertEquals("<", w.encode("<")); + assertEquals("&", w.encode("&")); + assertEquals(""", w.encode("\"")); + assertEquals("<", w.encode("<")); + assertEquals("&", w.encode("&")); + } +}