Author: krosenvold
Date: Sat Sep 12 21:30:18 2015
New Revision: 1702682

URL: http://svn.apache.org/r1702682
Log:
Improved performance of PrettyPrintXMLWriter by approx 45%. Reduced garbage 
production by 80%

Modified:
    
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/PrettyPrintXMLWriter.java
    
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/XMLEncode.java

Modified: 
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/PrettyPrintXMLWriter.java
URL: 
http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/PrettyPrintXMLWriter.java?rev=1702682&r1=1702681&r2=1702682&view=diff
==============================================================================
--- 
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/PrettyPrintXMLWriter.java
 (original)
+++ 
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/PrettyPrintXMLWriter.java
 Sat Sep 12 21:30:18 2015
@@ -19,11 +19,11 @@ package org.apache.maven.shared.utils.xm
  * under the License.
  */
 
+import org.apache.maven.shared.utils.Os;
+
 import java.io.PrintWriter;
 import java.io.Writer;
-import java.util.LinkedList;
-
-import org.apache.maven.shared.utils.Os;
+import java.util.ArrayList;
 
 /**
  * XMLWriter with nice indentation
@@ -31,9 +31,15 @@ import org.apache.maven.shared.utils.Os;
 public class PrettyPrintXMLWriter
     implements XMLWriter
 {
+    private static final char[] CLOSE_1 = "/>".toCharArray();
+
+    private static final char[] CLOSE_2 = "</".toCharArray();
+
+    private static final char[] DEFAULT_LINE_INDENT = new char[]{ ' ', ' ' };
+
     private PrintWriter writer;
 
-    private LinkedList<String> elementStack = new LinkedList<String>();
+    private ArrayList<String> elementStack = new ArrayList<String>();
 
     private boolean processingElement = false;
 
@@ -43,9 +49,9 @@ public class PrettyPrintXMLWriter
 
     private int depth = 0;
 
-    private String lineIndent;
+    private char[] lineIndent;
 
-    private String lineSeparator;
+    private char[] lineSeparator;
 
     private String encoding;
 
@@ -93,7 +99,7 @@ public class PrettyPrintXMLWriter
      */
     public PrettyPrintXMLWriter( PrintWriter writer, String lineIndent, String 
encoding, String doctype )
     {
-        this( writer, lineIndent, Os.LINE_SEP, encoding, doctype );
+        this( writer, lineIndent.toCharArray(), Os.LINE_SEP.toCharArray(), 
encoding, doctype );
     }
 
     /**
@@ -114,7 +120,7 @@ public class PrettyPrintXMLWriter
      */
     public PrettyPrintXMLWriter( PrintWriter writer, String encoding, String 
doctype )
     {
-        this( writer, "  ", encoding, doctype );
+        this( writer, DEFAULT_LINE_INDENT, Os.LINE_SEP.toCharArray(), 
encoding, doctype );
     }
 
     /**
@@ -137,6 +143,19 @@ public class PrettyPrintXMLWriter
     public PrettyPrintXMLWriter( PrintWriter writer, String lineIndent, String 
lineSeparator, String encoding,
                                  String doctype )
     {
+        this( writer, lineIndent.toCharArray(), lineSeparator.toCharArray(), 
encoding, doctype );
+    }
+
+    /**
+     * @param writer        not null
+     * @param lineIndent    could be null, but the normal way is some spaces.
+     * @param lineSeparator could be null, but the normal way is valid line 
separator
+     * @param encoding      could be null or the encoding to use.
+     * @param doctype       could be null.
+     */
+    private PrettyPrintXMLWriter( PrintWriter writer, char[] lineIndent, 
char[] lineSeparator, String encoding,
+                                  String doctype )
+    {
         this.writer = writer;
         this.lineIndent = lineIndent;
         this.lineSeparator = lineSeparator;
@@ -156,7 +175,7 @@ public class PrettyPrintXMLWriter
         writer.write( ' ' );
         writer.write( key );
         writer.write( '=' );
-        writer.write( XMLEncode.xmlEncodeTextForAttribute( value, '"' ) );
+        XMLEncode.xmlEncodeTextAsPCDATA( value, true, '"', writer );
     }
 
     public void setEncoding( String encoding )
@@ -186,7 +205,7 @@ public class PrettyPrintXMLWriter
             throw new IllegalStateException( "Document headers already 
written!" );
         }
 
-        this.lineSeparator = lineSeparator;
+        this.lineSeparator = lineSeparator.toCharArray();
     }
 
     public void setLineIndenter( String lineIndent )
@@ -196,7 +215,7 @@ public class PrettyPrintXMLWriter
             throw new IllegalStateException( "Document headers already 
written!" );
         }
 
-        this.lineIndent = lineIndent;
+        this.lineIndent = lineIndent.toCharArray();
     }
 
     public void startElement( String elementName )
@@ -214,9 +233,8 @@ public class PrettyPrintXMLWriter
         writer.write( elementName );
 
         processingElement = true;
-        depth++;
 
-        elementStack.addLast( elementName );
+        elementStack.add( depth++, elementName );
     }
 
     public void writeText( String text )
@@ -225,7 +243,7 @@ public class PrettyPrintXMLWriter
 
         completePreviouslyOpenedElement();
 
-        writer.write( XMLEncode.xmlEncodeText( text ) );
+        XMLEncode.xmlEncodeText( text, writer );
 
         endOnSameLine = true;
     }
@@ -241,14 +259,12 @@ public class PrettyPrintXMLWriter
 
     public void endElement()
     {
-        depth--;
-
+        String chars = elementStack.get( --depth );
         if ( processingElement )
         {
             // this means we don't have any content yet so we just add a />
-            writer.write( "/>" );
+            writer.write( CLOSE_1 );
 
-            elementStack.removeLast();
             processingElement = false;
         }
         else
@@ -259,7 +275,9 @@ public class PrettyPrintXMLWriter
             }
 
             // otherwise we need a full closing tag for that element
-            writer.write( "</" + elementStack.removeLast() + ">" );
+            writer.write( CLOSE_2 );
+            writer.write( chars );
+            writer.write( '>' );
         }
 
         endOnSameLine = false;
@@ -267,7 +285,7 @@ public class PrettyPrintXMLWriter
 
     /**
      * Write the documents if not already done.
-     * 
+     *
      * @return <code>true</code> if the document headers have freshly been 
written.
      */
     private boolean ensureDocumentStarted()
@@ -293,7 +311,9 @@ public class PrettyPrintXMLWriter
 
         if ( encoding != null )
         {
-            writer.write( " encoding=\"" + encoding + "\"" );
+            writer.write( " encoding=\"" );
+            writer.write( encoding );
+            writer.write( '\"' );
         }
 
         writer.write( "?>" );
@@ -303,7 +323,9 @@ public class PrettyPrintXMLWriter
         if ( docType != null )
         {
             newLine();
-            writer.write( "<!DOCTYPE " + docType + ">" );
+            writer.write( "<!DOCTYPE " );
+            writer.write( docType );
+            writer.write( '>' );
         }
     }
 

Modified: 
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/XMLEncode.java
URL: 
http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/XMLEncode.java?rev=1702682&r1=1702681&r2=1702682&view=diff
==============================================================================
--- 
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/XMLEncode.java
 (original)
+++ 
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/xml/XMLEncode.java
 Sat Sep 12 21:30:18 2015
@@ -19,6 +19,10 @@ package org.apache.maven.shared.utils.xm
  * under the License.
  */
 
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
 /**
  * Collection of XML encoding/decoding helpers. <br>
  * This is all about the special characters &amp; and &lt;, and for attributes
@@ -28,6 +32,7 @@ final class XMLEncode
 {
 
     private static final int CDATA_BLOCK_THRESHOLD_LENGTH = 12;
+
     private static final char DEFAULT_QUOTE_CHAR = '"';
 
     /**
@@ -68,24 +73,44 @@ final class XMLEncode
         {
             return null;
         }
-        if ( !needsEncoding( text ) )
+        StringWriter writer = new StringWriter( text.length() * 2 );
+        xmlEncodeText( text, writer );
+        return writer.toString();
+    }
+
+    public static void xmlEncodeText( String text, Writer writer )
+    {
+        if ( text == null )
         {
-            return text;
+            return;
         }
-        else
+        try
         {
-            // only encode as cdata if is is longer than CDATA block overhead:
-            if ( text.length() > CDATA_BLOCK_THRESHOLD_LENGTH )
+            if ( !needsEncoding( text ) )
+            {
+                writer.write( text );
+                return;
+            }
+            else
             {
-                String cdata = xmlEncodeTextAsCDATABlock( text );
-                if ( cdata != null )
+                // only encode as cdata if is is longer than CDATA block 
overhead:
+                if ( text.length() > CDATA_BLOCK_THRESHOLD_LENGTH )
                 {
-                    return cdata;
+                    String cdata = xmlEncodeTextAsCDATABlock( text );
+                    if ( cdata != null )
+                    {
+                        writer.write( cdata );
+                        return;
+                    }
                 }
             }
         }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
         // if every thing else fails, do it the save way...
-        return xmlEncodeTextAsPCDATA( text );
+        xmlEncodeTextAsPCDATA( text, false, DEFAULT_QUOTE_CHAR, writer );
     }
 
     /**
@@ -124,83 +149,98 @@ final class XMLEncode
         {
             return null;
         }
-        char c;
-        int length = text.length();
-        StringBuilder n = new StringBuilder( length * 2 );
-        if ( forAttribute )
-        {
-            n.append( quoteChar );
-        }
-
-        for ( int i = 0; i < length; i++ )
-        {
-            c = text.charAt( i );
-            switch ( c )
-            {
-                case '&':
-                    n.append( "&amp;" );
-                    break;
-                case '<':
-                    n.append( "&lt;" );
-                    break;
-                case '>': // FIX for sourceforge bug #802520 ("]]>" needs 
encoding)
-                    n.append( "&gt;" );
-                    break;
-                case '"':
-                    if ( forAttribute )
-                    {
-                        n.append( "&quot;" );
-                    }
-                    else
-                    {
-                        n.append( c );
-                    }
-                    break;
-                case '\'':
-                    if ( forAttribute )
-                    {
-                        n.append( "&apos;" );
-                    }
-                    else
-                    {
-                        n.append( c );
-                    }
-                    break;
-                case '\r':
-                    if ( forAttribute )
-                    {
-                        if ( i == ( length - 1 ) || text.charAt( i + 1 ) != 
'\n' )
+        StringWriter writer = new StringWriter( text.length() * 2 );
+        xmlEncodeTextAsPCDATA( text, forAttribute, quoteChar, writer );
+        return writer.toString();
+    }
+
+    public static void xmlEncodeTextAsPCDATA( String text, boolean 
forAttribute, char quoteChar, Writer n )
+    {
+        if ( text == null )
+        {
+            return;
+        }
+        try
+        {
+            char c;
+            int length = text.length();
+            if ( forAttribute )
+            {
+                n.append( quoteChar );
+            }
+
+            for ( int i = 0; i < length; i++ )
+            {
+                c = text.charAt( i );
+                switch ( c )
+                {
+                    case '&':
+                        n.append( "&amp;" );
+                        break;
+                    case '<':
+                        n.append( "&lt;" );
+                        break;
+                    case '>': // FIX for sourceforge bug #802520 ("]]>" needs 
encoding)
+                        n.append( "&gt;" );
+                        break;
+                    case '"':
+                        if ( forAttribute )
                         {
-                            n.append( "&#13;" );
+                            n.append( "&quot;" );
                         }
-                    }
-                    else
-                    {
-                        n.append( c );
-                    }
-                    // but skip the \r in \r\n
+                        else
+                        {
+                            n.append( c );
+                        }
+                        break;
+                    case '\'':
+                        if ( forAttribute )
+                        {
+                            n.append( "&apos;" );
+                        }
+                        else
+                        {
+                            n.append( c );
+                        }
+                        break;
+                    case '\r':
+                        if ( forAttribute )
+                        {
+                            if ( i == ( length - 1 ) || text.charAt( i + 1 ) 
!= '\n' )
+                            {
+                                n.append( "&#13;" );
+                            }
+                        }
+                        else
+                        {
+                            n.append( c );
+                        }
+                        // but skip the \r in \r\n
 
+                        break;
+                    case '\n':
+                        if ( forAttribute )
+                        {
+                            n.append( "&#10;" );
+                        }
+                        break;
 
-                    break;
-                case '\n':
-                    if ( forAttribute )
-                    {
-                        n.append( "&#10;" );
-                    }
-                    break;
+                    default:
+                        n.append( c );
+                        break;
+                }
+            }
 
-                default:
-                    n.append( c );
-                    break;
+            if ( forAttribute )
+            {
+                n.append( quoteChar );
             }
         }
-
-        if ( forAttribute )
+        catch ( IOException e )
         {
-            n.append( quoteChar );
+            throw new RuntimeException( e );
         }
 
-        return n.toString();
     }
 
     /**


Reply via email to