View Javadoc

1   package org.apache.maven.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  import org.codehaus.plexus.util.xml.XMLWriter;
25  
26  public class PrettyPrintXMLWriter
27      implements XMLWriter
28  {
29      private final PrintWriter writer;
30  
31      private final LinkedList elementStack = new LinkedList();
32  
33      private boolean tagInProgress;
34  
35      private int depth;
36  
37      private final String lineIndenter;
38  
39      private final String encoding;
40  
41      private final String docType;
42  
43      private boolean readyForNewLine;
44  
45      private boolean tagIsEmpty;
46  
47      public PrettyPrintXMLWriter( PrintWriter writer )
48      {
49          this( writer, null, null );
50      }
51  
52      private PrettyPrintXMLWriter( PrintWriter writer, String lineIndenter, String encoding, String doctype )
53      {
54          this.writer = writer;
55  
56          this.lineIndenter = lineIndenter;
57  
58          this.encoding = encoding;
59  
60          this.docType = doctype;
61  
62          if ( docType != null || encoding != null )
63          {
64              writeDocumentHeaders();
65          }
66      }
67  
68      private PrettyPrintXMLWriter( PrintWriter writer, String encoding, String doctype )
69      {
70          this( writer, "  ", encoding, doctype );
71      }
72  
73      public void startElement( String name )
74      {
75          tagIsEmpty = false;
76  
77          finishTag();
78  
79          write( "<" );
80  
81          write( name );
82  
83          elementStack.addLast( name );
84  
85          tagInProgress = true;
86  
87          depth++;
88  
89          readyForNewLine = true;
90  
91          tagIsEmpty = true;
92      }
93  
94      public void writeText( String text )
95      {
96          writeText( text, true );
97      }
98  
99      public void writeMarkup( String text )
100     {
101         writeText( text, false );
102     }
103 
104     private void writeText( String text, boolean escapeXml )
105     {
106         readyForNewLine = false;
107 
108         tagIsEmpty = false;
109 
110         finishTag();
111 
112         if ( escapeXml )
113         {
114             text = escapeXml( text );
115         }
116 
117         write( text );
118     }
119 
120     private static String escapeXml( String text )
121     {
122         StringBuffer sb = new StringBuffer( text.length() * 2 );
123         for ( int i = 0; i < text.length(); i++ )
124         {
125             char c = text.charAt( i );
126             if ( c < 32 )
127             {
128                 if ( c == '\n' || c == '\r' || c == '\t' )
129                 {
130                     sb.append( c );
131                 }
132                 else
133                 {
134                     // uh-oh!  This character is illegal in XML 1.0!
135                     // http://www.w3.org/TR/1998/REC-xml-19980210#charsets
136                     // we're going to deliberately doubly-XML escape it...
137                     // there's nothing better we can do! :-(
138                     // SUREFIRE-456
139                     sb.append( "&amp;#" ).append( (int) c ).append( ';' );
140                 }
141             }
142             else if ( c == '<' )
143             {
144                 sb.append( "&lt;" );
145             }
146             else if ( c == '>' )
147             {
148                 sb.append( "&gt;" );
149             }
150             else if ( c == '&' )
151             {
152                 sb.append( "&amp;" );
153             }
154             else if ( c == '"' )
155             {
156                 sb.append( "&quot;" );
157             }
158             else if ( c == '\'' )
159             {
160                 sb.append( "&apos;" );
161             }
162             else
163             {
164                 sb.append( c );
165             }
166         }
167         return sb.toString();
168     }
169 
170     public void addAttribute( String key, String value )
171     {
172         write( " " );
173 
174         write( key );
175 
176         write( "=\"" );
177 
178         write( escapeXml( value ) );
179 
180         write( "\"" );
181     }
182 
183     public void endElement()
184     {
185         depth--;
186 
187         if ( tagIsEmpty )
188         {
189             write( "/" );
190 
191             readyForNewLine = false;
192 
193             finishTag();
194 
195             elementStack.removeLast();
196         }
197         else
198         {
199             finishTag();
200 
201             write( "</" + elementStack.removeLast() + ">" );
202         }
203 
204         readyForNewLine = true;
205     }
206 
207     private void write( String str )
208     {
209         writer.write( str );
210     }
211 
212     private void finishTag()
213     {
214         if ( tagInProgress )
215         {
216             write( ">" );
217         }
218 
219         tagInProgress = false;
220 
221         if ( readyForNewLine )
222         {
223             endOfLine();
224         }
225         readyForNewLine = false;
226 
227         tagIsEmpty = false;
228     }
229 
230     protected void endOfLine()
231     {
232         write( "\n" );
233 
234         for ( int i = 0; i < depth; i++ )
235         {
236             write( lineIndenter );
237         }
238     }
239 
240     private void writeDocumentHeaders()
241     {
242         write( "<?xml version=\"1.0\"" );
243 
244         if ( encoding != null )
245         {
246             write( " encoding=\"" + encoding + "\"" );
247         }
248 
249         write( "?>" );
250 
251         endOfLine();
252 
253         if ( docType != null )
254         {
255             write( "<!DOCTYPE " );
256 
257             write( docType );
258 
259             write( ">" );
260 
261             endOfLine();
262         }
263     }
264 }