1 package org.apache.maven.surefire.report;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
135
136
137
138
139 sb.append( "&#" ).append( (int) c ).append( ';' );
140 }
141 }
142 else if ( c == '<' )
143 {
144 sb.append( "<" );
145 }
146 else if ( c == '>' )
147 {
148 sb.append( ">" );
149 }
150 else if ( c == '&' )
151 {
152 sb.append( "&" );
153 }
154 else if ( c == '"' )
155 {
156 sb.append( """ );
157 }
158 else if ( c == '\'' )
159 {
160 sb.append( "'" );
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 }