KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > junit > output > XmlOutputParser


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.junit.output;
21
22 import java.io.IOException JavaDoc;
23 import java.io.Reader JavaDoc;
24 import org.openide.ErrorManager;
25 import org.openide.util.NbBundle;
26 import org.openide.xml.XMLUtil;
27 import org.xml.sax.Attributes JavaDoc;
28 import org.xml.sax.InputSource JavaDoc;
29 import org.xml.sax.SAXException JavaDoc;
30 import org.xml.sax.XMLReader JavaDoc;
31 import org.xml.sax.helpers.DefaultHandler JavaDoc;
32
33 /**
34  * Parser of XML-output generated by the JUnit XML formatter.
35  *
36  * @author Marian Petras
37  */

38 final class XmlOutputParser extends DefaultHandler JavaDoc {
39
40     /** */
41     private static final int STATE_OUT_OF_SCOPE = 1;
42     /** */
43     private static final int STATE_TESTSUITE = 2;
44     /** */
45     private static final int STATE_PROPERTIES = 3;
46     /** */
47     private static final int STATE_PROPERTY = 4;
48     /** */
49     private static final int STATE_TESTCASE = 8;
50     /** */
51     private static final int STATE_FAILURE = 12;
52     /** */
53     private static final int STATE_ERROR = 13;
54     /** */
55     private static final int STATE_OUTPUT_STD = 16;
56     /** */
57     private static final int STATE_OUTPUT_ERR = 17;
58     
59     /** */
60     private int state = STATE_OUT_OF_SCOPE;
61     /** */
62     int unknownElemNestLevel = 0;
63     
64     /** */
65     private final XMLReader JavaDoc xmlReader;
66     /** */
67     private Report report;
68     /** */
69     private Report.Testcase testcase;
70     /** */
71     private Report.Trouble trouble;
72     /** */
73     private StringBuffer JavaDoc charactersBuf;
74     
75     /** */
76     private final RegexpUtils regexp;
77     
78     /**
79      *
80      * @exception org.xml.sax.SAXException
81      * if initialization of the parser failed
82      */

83     static Report parseXmlOutput(Reader JavaDoc reader) throws SAXException JavaDoc,
84                                                        IOException JavaDoc {
85         XmlOutputParser parser = new XmlOutputParser();
86         try {
87            parser.xmlReader.parse(new InputSource JavaDoc(reader));
88         } catch (SAXException JavaDoc ex) {
89             String JavaDoc message = ex.getMessage();
90             int severity = ErrorManager.INFORMATIONAL;
91             if ((message != null)
92                     && ErrorManager.getDefault().isLoggable(severity)) {
93                 ErrorManager.getDefault().log(
94                        severity,
95                        "Exception while parsing XML output from JUnit: "//NOI18N
96
+ message);
97             }
98             throw ex;
99         } catch (IOException JavaDoc ex) {
100             assert false; /* should never happen */
101         } finally {
102             reader.close(); //throws IOException
103
}
104         return parser.report;
105     }
106     
107     /** Creates a new instance of XMLOutputParser */
108     private XmlOutputParser() throws SAXException JavaDoc {
109         xmlReader = XMLUtil.createXMLReader();
110         xmlReader.setContentHandler(this);
111         
112         regexp = RegexpUtils.getInstance();
113     }
114     
115     /**
116      */

117     public void startElement(String JavaDoc uri,
118                              String JavaDoc localName,
119                              String JavaDoc qName,
120                              Attributes JavaDoc attrs) throws SAXException JavaDoc {
121         switch (state) {
122             //<editor-fold defaultstate="collapsed" desc="STATE_PROPERTIES">
123
case STATE_PROPERTIES:
124                 if (qName.equals("property")) {
125                     state = STATE_PROPERTY;
126                 } else {
127                     startUnknownElem();
128                 }
129                 break; //</editor-fold>
130
//<editor-fold defaultstate="collapsed" desc="STATE_TESTSUITE">
131
case STATE_TESTSUITE:
132                 if (qName.equals("testcase")) {
133                     testcase = createTestcaseReport(
134                             attrs.getValue("classname"),
135                             attrs.getValue("name"),
136                             attrs.getValue("time"));
137                     state = STATE_TESTCASE;
138                 } else if (qName.equals("system-out")) {
139                     state = STATE_OUTPUT_STD;
140                 } else if (qName.equals("system-err")) {
141                     state = STATE_OUTPUT_ERR;
142                 } else if (qName.equals("properties")) {
143                     state = STATE_PROPERTIES;
144                 } else {
145                     startUnknownElem();
146                 }
147                 break; //</editor-fold>
148
//<editor-fold defaultstate="collapsed" desc="STATE_TESTCASE">
149
case STATE_TESTCASE:
150                 if (qName.equals("failure")) {
151                     state = STATE_FAILURE;
152                 } else if (qName.equals("error")) {
153                     state = STATE_ERROR;
154                 } else {
155                     startUnknownElem();
156                 }
157                 if (state >= 0) { //i.e. the element is "failure" or "error"
158
assert testcase != null;
159                     trouble = new Report.Trouble(state == STATE_ERROR);
160                 }
161                 break; //</editor-fold>
162
//<editor-fold defaultstate="collapsed" desc="STATE_OUT_OF_SCOPE">
163
case STATE_OUT_OF_SCOPE:
164                 if (qName.equals("testsuite")) {
165                     report = createReport(attrs.getValue("name"),
166                                           attrs.getValue("tests"),
167                                           attrs.getValue("failures"),
168                                           attrs.getValue("errors"),
169                                           attrs.getValue("time"));
170                     state = STATE_TESTSUITE;
171                 } else {
172                     startUnknownElem();
173                 }
174                 break; //</editor-fold>
175
//<editor-fold defaultstate="collapsed" desc="STATE_xxx (other)">
176
case STATE_PROPERTY:
177             case STATE_FAILURE:
178             case STATE_ERROR:
179             case STATE_OUTPUT_STD:
180             case STATE_OUTPUT_ERR:
181                 startUnknownElem();
182                 break; //</editor-fold>
183
//<editor-fold defaultstate="collapsed" desc="default">
184
default:
185                 assert state < 0;
186                 unknownElemNestLevel++;
187                 break; //</editor-fold>
188
}
189     }
190     
191     /**
192      */

193     public void endElement(String JavaDoc uri,
194                            String JavaDoc localName,
195                            String JavaDoc qName) throws SAXException JavaDoc {
196         switch (state) {
197             //<editor-fold defaultstate="collapsed" desc="STATE_PROPERTIES">
198
case STATE_PROPERTIES:
199                 assert qName.equals("properties");
200                 state = STATE_TESTSUITE;
201                 break; //</editor-fold>
202
//<editor-fold defaultstate="collapsed" desc="STATE_TESTSUITE">
203
case STATE_TESTSUITE:
204                 assert qName.equals("testsuite");
205                 state = STATE_OUT_OF_SCOPE;
206                 break; //</editor-fold>
207
//<editor-fold defaultstate="collapsed" desc="STATE_TESTCASE">
208
case STATE_TESTCASE:
209                 assert qName.equals("testcase");
210                 
211                 assert testcase != null;
212                 report.reportTest(testcase);
213                 testcase = null;
214                 state = STATE_TESTSUITE;
215                 break; //</editor-fold>
216
//<editor-fold defaultstate="collapsed" desc="STATE_OUT_OF_SCOPE">
217
case STATE_OUT_OF_SCOPE:
218                 assert false;
219                 break; //</editor-fold>
220
//<editor-fold defaultstate="collapsed" desc="STATE_PROPERTY">
221
case STATE_PROPERTY:
222                 assert qName.equals("property");
223                 state = STATE_PROPERTIES;
224                 break; //</editor-fold>
225
//<editor-fold defaultstate="collapsed" desc="STATE_FAILURE or STATE_ERROR">
226
case STATE_FAILURE:
227             case STATE_ERROR:
228                 assert (state == STATE_FAILURE && qName.equals("failure"))
229                        || (state == STATE_ERROR && qName.equals("error"));
230                 
231                 assert testcase != null;
232                 assert trouble != null;
233                 if (charactersBuf != null) {
234                     parseTroubleReport(charactersBuf.toString(), trouble);
235                     charactersBuf = null;
236                 }
237                 testcase.trouble = trouble;
238                 trouble = null;
239                 state = STATE_TESTCASE;
240                 break; //</editor-fold>
241
//<editor-fold defaultstate="collapsed" desc="STATE_OUTPUT_STD or STATE_OUTPUT_ERR">
242
case STATE_OUTPUT_STD:
243             case STATE_OUTPUT_ERR:
244                 assert (state == STATE_OUTPUT_STD && qName.equals("system-out"))
245                    || (state == STATE_OUTPUT_ERR && qName.equals("system-err"));
246                 if (charactersBuf != null) {
247                     String JavaDoc[] output = getOutput(charactersBuf.toString());
248                     if (state == STATE_OUTPUT_STD) {
249                         report.outputStd = output;
250                     } else {
251                         report.outputErr = output;
252                     }
253                     charactersBuf = null;
254                 }
255                 state = STATE_TESTSUITE;
256                 break; //</editor-fold>
257
//<editor-fold defaultstate="collapsed" desc="default">
258
default:
259                 assert state < 0;
260                 if (--unknownElemNestLevel == 0) {
261                     state = -state;
262                 }
263                 break; //</editor-fold>
264
}
265     }
266     
267     /**
268      */

269     private void startUnknownElem() {
270         state = -state;
271         unknownElemNestLevel++;
272     }
273     
274     /**
275      */

276     private Report createReport(String JavaDoc suiteName,
277                                 String JavaDoc testsCountStr,
278                                 String JavaDoc failuresStr,
279                                 String JavaDoc errorsStr,
280                                 String JavaDoc timeStr) {
281         /* Parse the testsuite name: */
282         if (suiteName == null) {
283             suiteName = NbBundle.getMessage(XmlOutputParser.class,
284                                             "UNNKOWN_NAME"); //NOI18N
285
}
286         
287         /* Parse the test counts: */
288         final String JavaDoc[] numberStrings = new String JavaDoc[] { testsCountStr,
289                                                       failuresStr,
290                                                       errorsStr };
291         final int[] numbers = new int[numberStrings.length];
292         for (int i = 0; i < numberStrings.length; i++) {
293             boolean ok;
294             String JavaDoc numberStr = numberStrings[i];
295             if (numberStr == null) {
296                 ok = false;
297             } else {
298                 try {
299                     numbers[i] = Integer.parseInt(numberStrings[i]);
300                     ok = (numbers[i] >= 0);
301                 } catch (NumberFormatException JavaDoc ex) {
302                     ok = false;
303                 }
304             }
305             if (!ok) {
306                 numbers[i] = -1;
307             }
308         }
309         
310         /* Parse the elapsed time: */
311         int timeMillis = regexp.parseTimeMillisNoNFE(timeStr);
312         
313         /* Create a report: */
314         Report report = new Report(suiteName);
315         report.totalTests = numbers[0];
316         report.failures = numbers[1];
317         report.errors = numbers[2];
318         report.elapsedTimeMillis = timeMillis;
319         
320         return report;
321     }
322     
323     /**
324      */

325     private Report.Testcase createTestcaseReport(String JavaDoc className,
326                                                  String JavaDoc name,
327                                                  String JavaDoc timeStr) {
328         Report.Testcase testcase = new Report.Testcase();
329         testcase.className = className;
330         testcase.name = name;
331         testcase.timeMillis = regexp.parseTimeMillisNoNFE(timeStr);
332         
333         return testcase;
334     }
335     
336     /**
337      */

338     public void characters(char[] ch,
339                            int start,
340                            int length) throws SAXException JavaDoc {
341         switch (state) {
342             case STATE_FAILURE:
343             case STATE_ERROR:
344             case STATE_OUTPUT_STD:
345             case STATE_OUTPUT_ERR:
346                 if (charactersBuf == null) {
347                     charactersBuf = new StringBuffer JavaDoc(512);
348                 }
349                 charactersBuf.append(ch, start, length);
350                 break;
351         }
352     }
353     
354     /**
355      */

356     private void parseTroubleReport(String JavaDoc report, Report.Trouble trouble) {
357         final String JavaDoc[] lines = report.split("[\\r\\n]+"); //NOI18N
358

359         TroubleParser troubleParser = new TroubleParser(trouble, regexp);
360         for (String JavaDoc line : lines) {
361             if (troubleParser.processMessage(line)) {
362                 return;
363             }
364         }
365         troubleParser.finishProcessing();
366     }
367     
368     /**
369      */

370     private String JavaDoc[] getOutput(String JavaDoc string) {
371         String JavaDoc[] lines = string.split("(?:\\r|\\r\\n|\\n)"); //NOI18N
372

373         /*
374          * The XML output produces an extra empty line at the end of the output:
375          */

376         if ((lines.length >= 1) && (lines[lines.length - 1].length() == 0)) {
377             String JavaDoc[] temp = lines;
378             lines = new String JavaDoc[lines.length - 1];
379             if (lines.length > 0) {
380                 System.arraycopy(temp, 0, lines, 0, lines.length);
381             }
382         }
383         return lines;
384     }
385     
386 }
387
Popular Tags