You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by bo...@locus.apache.org on 2000/12/07 15:52:04 UTC

cvs commit: jakarta-ant/src/testcases/org/apache/tools/ant/util DOMElementWriterTest.java

bodewig     00/12/07 06:52:03

  Modified:    src/main/org/apache/tools/ant XmlLogger.java
               src/main/org/apache/tools/ant/taskdefs/optional/junit
                        XMLJUnitResultFormatter.java
  Added:       src/main/org/apache/tools/ant/util DOMElementWriter.java
               src/testcases/org/apache/tools/ant/util
                        DOMElementWriterTest.java
  Log:
  Moved the common code from XmlLogger and XMLJUnitResultLogger into a
  new class.
  
  Wrap nested text into <![CDATA[ ]]> and replace special characters in
  attribute values correctly.
  PR: 413
  
  Revision  Changes    Path
  1.5       +2 -60     jakarta-ant/src/main/org/apache/tools/ant/XmlLogger.java
  
  Index: XmlLogger.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/XmlLogger.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XmlLogger.java	2000/09/21 07:42:47	1.4
  +++ XmlLogger.java	2000/12/07 14:52:00	1.5
  @@ -58,6 +58,7 @@
   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 @@
   
               Writer out = new FileWriter(outFilename);
               out.write("<?xml:stylesheet type=\"text/xsl\" href=\"log.xsl\"?>\n\n");
  -            write(buildElement, out, 0);
  +            (new DOMElementWriter()).write(buildElement, out, 0, "\t");
               out.flush();
               out.close();
               
  @@ -228,63 +229,4 @@
           }
       }
   
  -    /**
  -     *  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("</");
  -        out.write(element.getTagName());
  -        out.write(">\n");
  -    }
   }
  
  
  
  1.4       +8 -100    jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
  
  Index: XMLJUnitResultFormatter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XMLJUnitResultFormatter.java	2000/09/20 12:41:09	1.3
  +++ XMLJUnitResultFormatter.java	2000/12/07 14:52:01	1.4
  @@ -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 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 @@
   /**
    * Prints XML output of the test to a specified Writer.
    *
  - * @author <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a>
  + * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
    */
   
   public class XMLJUnitResultFormatter implements JUnitResultFormatter {
  @@ -120,7 +121,7 @@
       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 @@
               try {
                   wri = new OutputStreamWriter(out);
                   wri.write("<?xml version=\"1.0\"?>\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 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,107 +209,14 @@
   
           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));
           Text trace = doc.createTextNode(swr.toString());
           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("&lt;");
  -                break;
  -            case '>':
  -                temp.append("&gt;");
  -                break;
  -            case '\"':
  -                temp.append("&quot;");
  -                break;
  -            case '&':
  -                temp.append("&amp;");
  -                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("<![CDATA[");
  -                out.write(((Text)child).getData());
  -                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("</");
  -        out.write(element.getTagName());
  -        out.write(">\n");
       }
   
   } // XMLJUnitResultFormatter
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/util/DOMElementWriter.java
  
  Index: DOMElementWriter.java
  ===================================================================
  /*
   * 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
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.util;
  
  import java.io.*;
  import org.w3c.dom.*;
  
  /**
   * Writes a DOM tree to a given Writer.
   *
   * <p>Utility class used by {@link org.apache.tools.ant.XmlLogger
   * XmlLogger} and
   * org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter
   * XMLJUnitResultFormatter}.</p>
   *
   * @author The original author of XmlLogger
   * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   */
  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("<![CDATA[");
                  out.write(((Text)child).getData());
                  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(element.getTagName());
          out.write(">");
          out.write(lSep);
      }
  
      /**
       * Escape &lt;, &amp; and &quot; as their entities.
       */
      public String encode(String value) {
          sb.setLength(0);
          for (int i=0; i<value.length(); i++) {
              char c = value.charAt(i);
              switch (c) {
              case '<':
                  sb.append("&lt;");
                  break;
              case '\"':
                  sb.append("&quot;");
                  break;
              case '&':
                  int nextSemi = value.indexOf(";", i);
                  if (nextSemi < 0
                      || !isReference(value.substring(i, nextSemi+1))) {
                      sb.append("&amp;");
                  } else {
                      sb.append('&');
                  }
                  break;
              default:
                  sb.append(c);
                  break;
              }
          }
          return sb.toString();
      }
  
      /**
       * Is the given argument a character or entity reference?
       */
      public boolean isReference(String ent) {
          if (!(ent.charAt(0) == '&') || !ent.endsWith(";")) {
              return false;
          }
  
          if (ent.charAt(1) == '#') {
              if (ent.charAt(2) == 'x') {
                  try {
                      Integer.parseInt(ent.substring(3, ent.length()-1), 16);
                      return true;
                  } catch (NumberFormatException nfe) {
                      return false;
                  }
              } else {
                  try {
                      Integer.parseInt(ent.substring(2, ent.length()-1));
                      return true;
                  } catch (NumberFormatException nfe) {
                      return false;
                  }
              }
          }
  
          String name = ent.substring(1, ent.length() - 1);
          for (int i=0; i<knownEntities.length; i++) {
              if (name.equals(knownEntities[i])) {
                  return true;
              }
          }
          return false;
      }
  }
  
  
  
  1.1                  jakarta-ant/src/testcases/org/apache/tools/ant/util/DOMElementWriterTest.java
  
  Index: DOMElementWriterTest.java
  ===================================================================
  /*
   * 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", "Tomcat", 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
   * <http://www.apache.org/>.
   */
  
  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 <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> 
   */
  public class DOMElementWriterTest extends TestCase {
  
      private DOMElementWriter w = new DOMElementWriter();
  
      public DOMElementWriterTest(String name) {
          super(name);
      }
  
      public void testIsReference() {
          assert("&#20;", w.isReference("&#20;"));
          assert("&#x20;", w.isReference("&#x20;"));
          assert("&#xA0;", w.isReference("&#xA0;"));
          assert("&#A0;", !w.isReference("&#A0;"));
          assert("20;", !w.isReference("20;"));
          assert("&#20", !w.isReference("&#20"));
          assert("&quot;", w.isReference("&quot;"));
          assert("&apos;", w.isReference("&apos;"));
          assert("&gt;", w.isReference("&gt;"));
          assert("&lt;", w.isReference("&lt;"));
          assert("&amp;", w.isReference("&amp;"));
      }
  
      public void testEncode() {
          assertEquals("&#20;", w.encode("&#20;"));
          assertEquals("&#x20;", w.encode("&#x20;"));
          assertEquals("&#xA0;", w.encode("&#xA0;"));
          assertEquals("&amp;#A0;", w.encode("&#A0;"));
          assertEquals("20;", w.encode("20;"));
          assertEquals("&amp;#20", w.encode("&#20"));
          assertEquals("&quot;", w.encode("&quot;"));
          assertEquals("&apos;", w.encode("&apos;"));
          assertEquals("&gt;", w.encode("&gt;"));
          assertEquals("&lt;", w.encode("&lt;"));
          assertEquals("&amp;", w.encode("&amp;"));
          assertEquals("&quot;", w.encode("\""));
          assertEquals("&lt;", w.encode("<"));
          assertEquals("&amp;", w.encode("&"));
      }
  }