View Javadoc

1   package org.apache.maven.plugin.surefire.report;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.PrintWriter;
23  import java.util.LinkedList;
24  
25  import org.apache.maven.shared.utils.xml.XMLWriter;
26  
27  public class PrettyPrintXMLWriter
28      implements XMLWriter
29  {
30      private final PrintWriter writer;
31  
32      private final LinkedList<String> elementStack = new LinkedList<String>();
33  
34      private boolean tagInProgress;
35  
36      private int depth;
37  
38      private final String lineIndenter;
39  
40      private final String encoding;
41  
42      private final String docType;
43  
44      private boolean readyForNewLine;
45  
46      private boolean tagIsEmpty;
47  
48      public PrettyPrintXMLWriter( PrintWriter writer )
49      {
50          this( writer, null, null );
51      }
52  
53      private PrettyPrintXMLWriter( PrintWriter writer, String lineIndenter, String encoding, String doctype )
54      {
55          this.writer = writer;
56  
57          this.lineIndenter = lineIndenter;
58  
59          this.encoding = encoding;
60  
61          this.docType = doctype;
62  
63          if ( docType != null || encoding != null )
64          {
65              writeDocumentHeaders();
66          }
67      }
68  
69      public void setEncoding( String encoding )
70      {
71          throw new RuntimeException( "Not Implemented" );
72      }
73  
74      public void setDocType( String docType )
75      {
76          throw new RuntimeException( "Not Implemented" );
77      }
78  
79      private PrettyPrintXMLWriter( PrintWriter writer, String encoding, String doctype )
80      {
81          this( writer, "  ", encoding, doctype );
82      }
83  
84      public void startElement( String name )
85      {
86          tagIsEmpty = false;
87  
88          finishTag();
89  
90          write( "<" );
91  
92          write( name );
93  
94          elementStack.addLast( name );
95  
96          tagInProgress = true;
97  
98          depth++;
99  
100         readyForNewLine = true;
101 
102         tagIsEmpty = true;
103     }
104 
105     public void writeText( String text )
106     {
107         writeText( text, true );
108     }
109 
110     public void writeMarkup( String text )
111     {
112         writeText( text, false );
113     }
114 
115     private void writeText( String text, boolean escapeXml )
116     {
117         readyForNewLine = false;
118 
119         tagIsEmpty = false;
120 
121         finishTag();
122 
123         if ( escapeXml )
124         {
125             text = escapeXml( text );
126         }
127 
128         write( text );
129     }
130 
131     private static String escapeXml( String text )
132     {
133         StringBuffer sb = new StringBuffer( text.length() * 2 );
134         for ( int i = 0; i < text.length(); i++ )
135         {
136             char c = text.charAt( i );
137             if ( c < 32 )
138             {
139                 if ( c == '\n' || c == '\r' || c == '\t' )
140                 {
141                     sb.append( c );
142                 }
143                 else
144                 {
145                     // uh-oh!  This character is illegal in XML 1.0!
146                     // http://www.w3.org/TR/1998/REC-xml-19980210#charsets
147                     // we're going to deliberately doubly-XML escape it...
148                     // there's nothing better we can do! :-(
149                     // SUREFIRE-456
150                     sb.append( "&amp;#" ).append( (int) c ).append( ';' );
151                 }
152             }
153             else if ( c == '<' )
154             {
155                 sb.append( "&lt;" );
156             }
157             else if ( c == '>' )
158             {
159                 sb.append( "&gt;" );
160             }
161             else if ( c == '&' )
162             {
163                 sb.append( "&amp;" );
164             }
165             else if ( c == '"' )
166             {
167                 sb.append( "&quot;" );
168             }
169             else if ( c == '\'' )
170             {
171                 sb.append( "&apos;" );
172             }
173             else
174             {
175                 sb.append( c );
176             }
177         }
178         return sb.toString();
179     }
180 
181     public void addAttribute( String key, String value )
182     {
183         write( " " );
184 
185         write( key );
186 
187         write( "=\"" );
188 
189         write( escapeXml( value ) );
190 
191         write( "\"" );
192     }
193 
194     public void endElement()
195     {
196         depth--;
197 
198         if ( tagIsEmpty )
199         {
200             write( "/" );
201 
202             readyForNewLine = false;
203 
204             finishTag();
205 
206             elementStack.removeLast();
207         }
208         else
209         {
210             finishTag();
211 
212             write( "</" + elementStack.removeLast() + ">" );
213         }
214 
215         readyForNewLine = true;
216     }
217 
218     private void write( String str )
219     {
220         writer.write( str );
221     }
222 
223     private void finishTag()
224     {
225         if ( tagInProgress )
226         {
227             write( ">" );
228         }
229 
230         tagInProgress = false;
231 
232         if ( readyForNewLine )
233         {
234             endOfLine();
235         }
236         readyForNewLine = false;
237 
238         tagIsEmpty = false;
239     }
240 
241     protected void endOfLine()
242     {
243         write( "\n" );
244 
245         for ( int i = 0; i < depth; i++ )
246         {
247             write( lineIndenter );
248         }
249     }
250 
251     private void writeDocumentHeaders()
252     {
253         write( "<?xml version=\"1.0\"" );
254 
255         if ( encoding != null )
256         {
257             write( " encoding=\"" + encoding + "\"" );
258         }
259 
260         write( "?>" );
261 
262         endOfLine();
263 
264         if ( docType != null )
265         {
266             write( "<!DOCTYPE " );
267 
268             write( docType );
269 
270             write( ">" );
271 
272             endOfLine();
273         }
274     }
275 }