KickJava   Java API By Example, From Geeks To Geeks.

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


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.lang.ref.Reference JavaDoc;
23 import java.lang.ref.WeakReference JavaDoc;
24 import java.util.regex.Pattern JavaDoc;
25 import org.netbeans.modules.junit.RegexpPatterns;
26
27 /**
28  * Utility class providing various parsing routines for parsing JUnit output.
29  *
30  * @author Marian Petras
31  */

32 final class RegexpUtils {
33
34     /** */
35     static final String JavaDoc TESTSUITE_PREFIX = "Testsuite: "; //NOI18N
36
/** */
37     static final String JavaDoc TESTSUITE_STATS_PREFIX = "Tests run: "; //NOI18N
38
/** */
39     static final String JavaDoc FLOAT_NUMBER_REGEX
40             = "[0-9]*(?:\\.[0-9]+)?"; //NOI18N
41
/** */
42     static final String JavaDoc TIME_SECS_REGEX
43             = '(' + FLOAT_NUMBER_REGEX + ')'
44               + " +s(?:ec(?:ond)?(?:s|\\(s\\))?)?"; //NOI18N
45
/** */
46     static final String JavaDoc TESTSUITE_STATS_REGEX
47         = "Tests run: +([0-9]+)," + //NOI18N
48
" +Failures: +([0-9]+), +Errors: +([0-9]+)," + //NOI18N
49
" +Time elapsed: +" + TIME_SECS_REGEX; //NOI18N
50
/** */
51     static final String JavaDoc OUTPUT_DELIMITER_PREFIX = "--------"; //NOI18N
52
/** */
53     static final String JavaDoc STDOUT_LABEL = "Output"; //NOI18N
54
/** */
55     static final String JavaDoc STDERR_LABEL = "Error"; //NOI18N
56
/** */
57     static final String JavaDoc OUTPUT_DELIMITER_REGEX
58             = "-{8,} (?:Standard (" //NOI18N
59
+ STDOUT_LABEL + '|' + STDERR_LABEL + ")|-{3,}) -{8,}"; //NOI18N
60
/** */
61     static final String JavaDoc TESTCASE_PREFIX = "Testcase: "; //NOI18N
62
/** */
63     static final String JavaDoc TESTCASE_ISSUE_REGEX
64             = "\\p{Blank}*(?:(FAILED) *|(?i:.*\\berror\\b.*))"; //NOI18N
65
/** */
66     static final String JavaDoc TESTCASE_HEADER_PLAIN_REGEX
67             = "\\p{Blank}*(" + RegexpPatterns.JAVA_ID_REGEX //NOI18N
68
+ ")\\p{Blank}+took\\p{Blank}+" + TIME_SECS_REGEX; //NOI18N
69
/** */
70     static final String JavaDoc TESTCASE_HEADER_BRIEF_REGEX
71             = "\\p{Blank}*(" + RegexpPatterns.JAVA_ID_REGEX //NOI18N
72
+ ") *\\( *(" + RegexpPatterns.JAVA_ID_REGEX_FULL //NOI18N
73
+ ") *\\) *:" + TESTCASE_ISSUE_REGEX; //NOI18N
74
/** */
75     static final String JavaDoc TESTCASE_EXCEPTION_REGEX
76             = "((?:" + RegexpPatterns.JAVA_ID_REGEX_FULL //NOI18N
77
+ "\\.?(?:Exception|Error|ComparisonFailure))" //NOI18N
78
+ "|java\\.lang\\.Throwable)" //NOI18N
79
+ "(?: *: *(.*))?"; //NOI18N
80
/** */
81     static final String JavaDoc CALLSTACK_LINE_PREFIX = "at "; //NOI18N
82
/** */
83     static final String JavaDoc CALLSTACK_LINE_PREFIX_CATCH = "[catch] "; //NOI18N
84
/** */
85     static final String JavaDoc CALLSTACK_LINE_REGEX
86             = "(?:\\t\\t?| +| *\\t? *\\[catch\\] )" //NOI18N
87
+ CALLSTACK_LINE_PREFIX
88               + RegexpPatterns.JAVA_ID_REGEX + "(?:\\." //NOI18N
89
+ RegexpPatterns.JAVA_ID_REGEX + ")+" //NOI18N
90
+ "(?: ?\\([^()]+\\))?"; //NOI18N
91
/** */
92     static final String JavaDoc NESTED_EXCEPTION_PREFIX = "Caused by: "; //NOI18N
93
/** */
94     static final String JavaDoc NESTED_EXCEPTION_REGEX
95             = "(" + RegexpPatterns.JAVA_ID_REGEX_FULL + ")(?:: (.*))?";//NOI18N
96
static final String JavaDoc LOCATION_IN_FILE_REGEX
97             = RegexpPatterns.JAVA_ID_REGEX_FULL + "(?:\\:[0-9]+)?"; //NOI18N
98
/** */
99     static final String JavaDoc XML_DECL_PREFIX = "<?xml"; //NOI18N
100
/** */
101     static final String JavaDoc XML_SPACE_REGEX
102             = "[ \\t\\r\\n]"; //NOI18N
103
/** */
104     static final String JavaDoc XML_EQ_REGEX
105             = XML_SPACE_REGEX + '*' + '=' + XML_SPACE_REGEX + '*';
106     /** */
107     static final String JavaDoc XML_ENC_REGEX
108             = "[A-Za-z][-A-Za-z0-9._]*"; //NOI18N
109
/** */
110     static final String JavaDoc XML_DECL_REGEX
111             = "\\Q" + XML_DECL_PREFIX + "\\E" //NOI18N
112
+ XML_SPACE_REGEX + '+' + "version" //version //NOI18N
113
+ XML_EQ_REGEX + "(?:\"1\\.0\"|'1\\.0')" //NOI18N
114
+ "(?:" //NOI18N
115
+ XML_SPACE_REGEX + '+' + "encoding" //encoding //NOI18N
116
+ XML_EQ_REGEX + "(['\"])[A-Za-z][-A-Za-z0-9._]*\\1"//NOI18N
117
+ ")?" //NOI18N
118
+ "(?:" //NOI18N
119
+ XML_SPACE_REGEX + '+' + "standalone" //standalone //NOI18N
120
+ XML_EQ_REGEX + "(['\"])(?:yes|no)\\2" //NOI18N
121
+ ")?" //NOI18N
122
+ XML_SPACE_REGEX + '*' + "\\?>"; //NOI18N
123

124     /**
125      * Regexp matching part of a Java task's invocation debug message
126      * that specificies the classpath.
127      * Hack to find the classpath an Ant task is using.
128      * Cf. Commandline.describeArguments, issue #28190.<br />
129      * Captured groups:
130      * <ol>
131      * <li>the classpath
132      * </ol>
133      * <!-- copied from JavaAntLogger -->
134      */

135     static final Pattern JavaDoc CLASSPATH_ARGS
136             = Pattern.compile("\r?\n'-classpath'\r?\n'(.*)'\r?\n"); //NOI18N
137
/**
138      * Regexp matching part of a Java task's invocation debug message
139      * that specificies java executable.
140      * Hack to find JDK used for execution.
141      * <!-- copied from JavaAntLogger -->
142      */

143     static final Pattern JavaDoc JAVA_EXECUTABLE
144             = Pattern.compile("^Executing '(.*)' with arguments:$", //NOI18N
145
Pattern.MULTILINE);
146
147     /** */
148     private static Reference JavaDoc<RegexpUtils> instRef;
149     
150     /**
151      */

152     static synchronized RegexpUtils getInstance() {
153         RegexpUtils instance = (instRef != null) ? instRef.get() : null;
154         if (instance == null) {
155             instance = new RegexpUtils();
156             instRef = new WeakReference JavaDoc<RegexpUtils>(instance);
157         }
158         return instance;
159     }
160     
161     /** Creates a new instance of RegexpUtils */
162     private RegexpUtils() { }
163     
164     private volatile Pattern JavaDoc fullJavaIdPattern, suiteStatsPattern,
165                              outputDelimPattern, testcaseIssuePattern,
166                              testcaseExceptPattern, callstackLinePattern,
167                              nestedExceptPattern,
168                              locationInFilePattern,
169                              testcaseHeaderBriefPattern,
170                              testcaseHeaderPlainPattern,
171                              xmlDeclPattern, floatNumPattern;
172     
173     //<editor-fold defaultstate="collapsed" desc=" Note about synchronization ">
174
/*
175      * If-blocks in the following methods should be synchronized to ensure that
176      * the patterns are not compiled twice if the methods are called by two or
177      * more threads concurrently.
178      *
179      * But synchronization is quite expensive so I let them unsynchronized.
180      * It may happen that a single pattern is compiled multiple times but
181      * it does not cause any functional problem. I just marked the variables
182      * as 'volatile' so that once the pattern is compiled (and the variable
183      * set), subsequent invocations from other threads will find the actual
184      * non-null value.
185      */

186     //</editor-fold>
187

188     /** */
189     Pattern JavaDoc getFullJavaIdPattern() {
190         if (fullJavaIdPattern == null) {
191             fullJavaIdPattern
192                     = Pattern.compile(RegexpPatterns.JAVA_ID_REGEX_FULL);
193         }
194         return fullJavaIdPattern;
195     }
196     
197     /** */
198     Pattern JavaDoc getSuiteStatsPattern() {
199         if (suiteStatsPattern == null) {
200             suiteStatsPattern = Pattern.compile(TESTSUITE_STATS_REGEX);
201         }
202         return suiteStatsPattern;
203     }
204     
205     /** */
206     Pattern JavaDoc getOutputDelimPattern() {
207         if (outputDelimPattern == null) {
208             outputDelimPattern = Pattern.compile(OUTPUT_DELIMITER_REGEX);
209         }
210         return outputDelimPattern;
211     }
212     
213     /** */
214     Pattern JavaDoc getTestcaseHeaderBriefPattern() {
215         if (testcaseHeaderBriefPattern == null) {
216             testcaseHeaderBriefPattern = Pattern.compile(TESTCASE_HEADER_BRIEF_REGEX);
217         }
218         return testcaseHeaderBriefPattern;
219     }
220     
221     /** */
222     Pattern JavaDoc getTestcaseHeaderPlainPattern() {
223         if (testcaseHeaderPlainPattern == null) {
224             testcaseHeaderPlainPattern = Pattern.compile(TESTCASE_HEADER_PLAIN_REGEX);
225         }
226         return testcaseHeaderPlainPattern;
227     }
228     
229     /** */
230     Pattern JavaDoc getTestcaseIssuePattern() {
231         if (testcaseIssuePattern == null) {
232             testcaseIssuePattern = Pattern.compile(TESTCASE_ISSUE_REGEX);
233         }
234         return testcaseIssuePattern;
235     }
236     
237     /** */
238     Pattern JavaDoc getTestcaseExceptionPattern() {
239         if (testcaseExceptPattern == null) {
240             testcaseExceptPattern = Pattern.compile(TESTCASE_EXCEPTION_REGEX);
241         }
242         return testcaseExceptPattern;
243     }
244     
245     /**
246      */

247     Pattern JavaDoc getNestedExceptionPattern() {
248         if (nestedExceptPattern == null) {
249             nestedExceptPattern = Pattern.compile(NESTED_EXCEPTION_REGEX);
250         }
251         return nestedExceptPattern;
252     }
253     
254     /** */
255     Pattern JavaDoc getCallstackLinePattern() {
256         if (callstackLinePattern == null) {
257             callstackLinePattern = Pattern.compile(CALLSTACK_LINE_REGEX);
258         }
259         return callstackLinePattern;
260     }
261     
262     /** */
263     Pattern JavaDoc getLocationInFilePattern() {
264         if (locationInFilePattern == null) {
265             locationInFilePattern = Pattern.compile(LOCATION_IN_FILE_REGEX);
266         }
267         return locationInFilePattern;
268     }
269     
270     /** */
271     Pattern JavaDoc getXmlDeclPattern() {
272         if (xmlDeclPattern == null) {
273             xmlDeclPattern = Pattern.compile(XML_DECL_REGEX);
274         }
275         return xmlDeclPattern;
276     }
277     
278     /** */
279     Pattern JavaDoc getFloatNumPattern() {
280         if (floatNumPattern == null) {
281             floatNumPattern = Pattern.compile(FLOAT_NUMBER_REGEX);
282         }
283         return floatNumPattern;
284     }
285     
286     /**
287      * Parses a floating-point number describing elapsed time.
288      * The returned number is a number of elapsed milliseconds.
289      *
290      * @param string represeting non-negative floating-point number of seconds
291      * @return integer representing number of milliseconds (rounded)
292      * @exception java.lang.NumberFormatException
293      * if the passed string does not match
294      * the {@link #FLOAT_NUMBER_REGEX} pattern
295      */

296     int parseTimeMillis(String JavaDoc timeString) throws NumberFormatException JavaDoc {
297         int secs, millis;
298         final int dotIndex = timeString.indexOf('.');
299         if (dotIndex == -1) {
300             secs = Integer.parseInt(timeString);
301             millis = 0;
302         } else {
303             secs = (dotIndex == 0)
304                    ? 0
305                    : Integer.parseInt(timeString.substring(0, dotIndex));
306
307             String JavaDoc fractString = timeString.substring(dotIndex + 1);
308             if (fractString.length() > 4) {
309                 fractString = fractString.substring(0, 4);
310             }
311             int fractNum = Integer.parseInt(fractString);
312             switch (fractString.length()) {
313                 case 1:
314                     millis = 100 * fractNum;
315                     break;
316                 case 2:
317                     millis = 10 * fractNum;
318                     break;
319                 case 3:
320                     millis = fractNum;
321                     break;
322                 case 4:
323                     millis = (fractNum + 5) / 10;
324                     break;
325                 default:
326                     assert false;
327                     millis = 0;
328                     break;
329             }
330         }
331         return 1000 * secs + millis;
332     }
333     
334     /**
335      * Parses a floating-point number describing elapsed time.
336      * The returned number is a number of elapsed milliseconds.
337      *
338      * @param string represeting non-negative floating-point number of seconds
339      * @return integer representing number of milliseconds (rounded),
340      * or <code>-1</code> if the passed string is <code>null</code>
341      * or if it does not match the {@link #FLOAT_NUMBER_REGEX} pattern
342      */

343     int parseTimeMillisNoNFE(String JavaDoc timeStr) {
344         if ((timeStr == null)
345                 || !getFloatNumPattern().matcher(timeStr).matches()) {
346             return -1;
347         }
348         try {
349             return parseTimeMillis(timeStr);
350         } catch (NumberFormatException JavaDoc ex) {
351             assert false;
352             return -1;
353         }
354     }
355     
356     /**
357      * Trims leading and trailing spaces and tabs from a string.
358      *
359      * @param string string to remove spaces and tabs from
360      * @return the trimmed string, or the passed string if no trimming
361      * was necessary
362      */

363     static String JavaDoc specialTrim(String JavaDoc string) {
364         
365         /* Handle the trivial case: */
366         final int len = string.length();
367         if (len == 0) {
368             return string;
369         }
370         
371         final char[] chars = string.toCharArray();
372         char c;
373
374         int lead = 0;
375         while (lead < len) {
376             c = chars[lead];
377             if ((c != ' ') && (c != '\t')) {
378                 break;
379             }
380             lead++;
381         }
382         
383         /* Handle a corner case: */
384         if (lead == len) {
385             return string.substring(len);
386         }
387         
388         int trail = len;
389         do {
390             c = chars[--trail];
391         } while ((c == ' ') || (c == '\t'));
392         
393         if ((lead == 0) && (trail == len - 1)) {
394             return string;
395         } else {
396             return string.substring(lead, trail + 1);
397         }
398     }
399     
400 }
401
Popular Tags