2
* Cobertura - http://cobertura.sourceforge.net/
4
* This file was taken from JavaNCSS
5
* http://www.kclee.com/clemens/java/javancss/
6
* Copyright (C) 2000 Chr. Clemens Lee <clemens a.t kclee d.o.t com>
8
* Cobertura is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published
10
* by the Free Software Foundation; either version 2 of the License,
11
* or (at your option) any later version.
13
* Cobertura is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with Cobertura; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
2
* Cobertura - http://cobertura.sourceforge.net/
4
* This file was taken from JavaNCSS
5
* http://www.kclee.com/clemens/java/javancss/
6
* Copyright (C) 2000 Chr. Clemens Lee <clemens a.t kclee d.o.t com>
8
* Cobertura is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published
10
* by the Free Software Foundation; either version 2 of the License,
11
* or (at your option) any later version.
13
* Cobertura is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with Cobertura; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
29
* WARNING TO COBERTURA DEVELOPERS
31
* DO NOT MODIFY THIS FILE!
33
* MODIFY THE FILES UNDER THE JAVANCSS DIRECTORY LOCATED AT THE ROOT OF THE COBERTURA PROJECT.
35
* FOLLOW THE PROCEDURE FOR MERGING THE LATEST JAVANCSS INTO COBERTURA LOCATED AT
36
* javancss/coberturaREADME.txt
38
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
24
41
package net.sourceforge.cobertura.javancss;
26
import java.io.DataInputStream;
43
import java.awt.event.WindowAdapter;
44
import java.awt.event.WindowEvent;
27
46
import java.io.FileInputStream;
47
import java.io.FileNotFoundException;
48
import java.io.FileOutputStream;
49
import java.io.InputStream;
28
50
import java.io.IOException;
29
import java.util.Enumeration;
30
import java.util.Hashtable;
31
import java.util.Vector;
51
import java.io.InputStreamReader;
52
import java.io.OutputStream;
53
import java.io.OutputStreamWriter;
54
import java.io.PrintWriter;
55
import java.io.Reader;
56
import java.io.UnsupportedEncodingException;
57
import java.util.ArrayList;
58
import java.util.Collections;
59
import java.util.HashMap;
60
import java.util.HashSet;
61
import java.util.Iterator;
62
import java.util.List;
66
import net.sourceforge.cobertura.javancss.ccl.Exitable;
67
import net.sourceforge.cobertura.javancss.ccl.FileUtil;
68
import net.sourceforge.cobertura.javancss.ccl.Init;
69
import net.sourceforge.cobertura.javancss.ccl.Util;
71
import net.sourceforge.cobertura.javancss.parser.JavaParser;
72
import net.sourceforge.cobertura.javancss.parser.JavaParserInterface;
73
import net.sourceforge.cobertura.javancss.parser.JavaParserTokenManager;
74
import net.sourceforge.cobertura.javancss.parser.ParseException;
75
import net.sourceforge.cobertura.javancss.parser.TokenMgrError;
76
import net.sourceforge.cobertura.javancss.parser.debug.JavaParserDebug;
77
import net.sourceforge.cobertura.javancss.parser.java15.JavaParser15;
78
import net.sourceforge.cobertura.javancss.parser.java15.debug.JavaParser15Debug;
79
import net.sourceforge.cobertura.javancss.test.JavancssTest;
35
* @author Chr. Clemens Lee, recursive feature by P��k� Hannu,
36
* additional javadoc metrics by Emilio Gongora, <emilio@sms.nl>,
37
* and Guillermo Rodriguez, <guille@sms.nl>.
82
* While the Java parser class might be the heart of JavaNCSS,
83
* this class is the brain. This class controls input and output and
84
* invokes the Java parser.
86
* @author Chr. Clemens Lee <clemens@kclee.com>
87
* , recursive feature by P��k� Hannu
88
* , additional javadoc metrics by Emilio Gongora <emilio@sms.nl>
89
* , and Guillermo Rodriguez <guille@sms.nl>.
90
* @version $Id: Javancss.java 676 2009-09-04 13:42:13Z lewijw $
92
public class Javancss implements Exitable
42
private JavaParser _pJavaParser = null;
43
private Vector _vJavaSourceFiles = new Vector();
44
private String _sErrorMessage = null;
45
private Vector _vMethodComplexities = new Vector();
46
private Hashtable _htProcessedAtFiles = new Hashtable();
48
public Javancss(String sJavaSourceFile_)
50
//System.out.println("Javancss.<init>(String).sJavaSourceFile_: " + sJavaSourceFile_);
51
_sErrorMessage = null;
52
_vJavaSourceFiles = new Vector();
53
_vJavaSourceFiles.addElement(sJavaSourceFile_);
56
_measureFiles(_vJavaSourceFiles);
60
System.out.println("Javancss.<init>(String).e: " + e);
62
catch (TokenMgrError pError)
64
System.out.println("Javancss.<init>(String).pError: " + pError);
68
private void _measureFiles(Vector vJavaSourceFiles_) throws IOException, ParseException,
72
for (Enumeration e = vJavaSourceFiles_.elements(); e.hasMoreElements();)
74
String sJavaFileName = (String)e.nextElement();
76
// if the file specifies other files...
77
if (sJavaFileName.charAt(0) == '@')
79
if (sJavaFileName.length() > 1)
81
String sFileName = sJavaFileName.substring(1);
82
sFileName = FileUtil.normalizeFileName(sFileName);
83
if (_htProcessedAtFiles.get(sFileName) != null)
87
_htProcessedAtFiles.put(sFileName, sFileName);
88
String sJavaSourceFileNames = null;
91
sJavaSourceFileNames = FileUtil.readFile(sFileName);
93
catch (IOException pIOException)
95
_sErrorMessage = "File Read Error: " + sFileName;
99
Vector vTheseJavaSourceFiles = Util.stringToLines(sJavaSourceFileNames);
100
_measureFiles(vTheseJavaSourceFiles);
107
_measureSource(sJavaFileName);
109
catch (Throwable pThrowable)
111
// hmm, do nothing? Use getLastError() or so to check for details.
117
private void _measureSource(String sSourceFileName_) throws IOException, ParseException,
120
// take user.dir property in account
121
sSourceFileName_ = FileUtil.normalizeFileName(sSourceFileName_);
123
DataInputStream disSource = null;
128
disSource = new DataInputStream(new FileInputStream(sSourceFileName_));
130
catch (IOException pIOException)
132
if (_sErrorMessage == null)
138
_sErrorMessage += "\n";
140
_sErrorMessage += "File not found: " + sSourceFileName_;
145
String sTempErrorMessage = _sErrorMessage;
148
// the same method but with a DataInputSream
149
_measureSource(disSource);
151
catch (ParseException pParseException)
153
if (sTempErrorMessage == null)
155
sTempErrorMessage = "";
157
sTempErrorMessage += "ParseException in " + sSourceFileName_
158
+ "\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction() + "\"\n";
159
sTempErrorMessage += pParseException.getMessage() + "\n";
161
_sErrorMessage = sTempErrorMessage;
163
throw pParseException;
165
catch (TokenMgrError pTokenMgrError)
167
if (sTempErrorMessage == null)
169
sTempErrorMessage = "";
171
sTempErrorMessage += "TokenMgrError in " + sSourceFileName_ + "\n"
172
+ pTokenMgrError.getMessage() + "\n";
173
_sErrorMessage = sTempErrorMessage;
175
throw pTokenMgrError;
179
private void _measureSource(DataInputStream disSource_) throws ParseException, TokenMgrError
183
// create a parser object
184
_pJavaParser = new JavaParser(disSource_);
185
// execute the parser
186
_pJavaParser.compilationUnit();
187
//System.out.println("Javancss._measureSource(DataInputStream).SUCCESSFULLY_PARSED");
188
// add new data to global vector
189
_vMethodComplexities.addAll(_pJavaParser.getMethodComplexities());
191
catch (ParseException pParseException)
193
if (_sErrorMessage == null)
197
_sErrorMessage += "ParseException in STDIN";
198
if (_pJavaParser != null)
200
_sErrorMessage += "\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction()
203
_sErrorMessage += pParseException.getMessage() + "\n";
205
throw pParseException;
207
catch (TokenMgrError pTokenMgrError)
209
if (_sErrorMessage == null)
213
_sErrorMessage += "TokenMgrError in STDIN\n";
214
_sErrorMessage += pTokenMgrError.getMessage() + "\n";
216
throw pTokenMgrError;
220
public Vector getMethodComplexities()
222
return (_vMethodComplexities);
94
private static final String S_INIT__FILE_CONTENT =
96
"Author=Chr. Clemens Lee\n" +
99
"; Please do not edit the Help section\n"+
100
"HelpUsage=@srcfiles.txt | *.java | <stdin>\n" +
101
"Options=ncss,package,object,function,all,gui,xml,out,recursive,check,encoding,parser15\n" +
102
"ncss=b,o,Counts the program NCSS (default).\n" +
103
"package=b,o,Assembles a statistic on package level.\n" +
104
"object=b,o,Counts the object NCSS.\n" +
105
"function=b,o,Counts the function NCSS.\n" +
106
"all=b,o,The same as '-function -object -package'.\n" +
107
"gui=b,o,Opens a gui to present the '-all' output in tabbed panels.\n" +
108
"xml=b,o,Output in xml format.\n" +
109
"out=s,o,Output file name. By default output goes to standard out.\n"+
110
"recursive=b,o,Recurse to subdirs.\n" +
111
"check=b,o,Triggers a javancss self test.\n" +
112
"encoding=s,o,Encoding used while reading source files (default: platform encoding).\n" +
113
"parser15=b,o,Use new experimental Java 1.5 parser.\n" +
116
"UseSystemColors=true\n";
118
private boolean _bExit = false;
120
private List/*<File>*/ _vJavaSourceFiles = null;
121
private String encoding = null;
123
private String _sErrorMessage = null;
124
private Throwable _thrwError = null;
126
private JavaParserInterface _pJavaParser = null;
127
private int _ncss = 0;
128
private int _loc = 0;
129
private List/*<FunctionMetric>*/ _vFunctionMetrics = new ArrayList();
130
private List/*<ObjectMetric>*/ _vObjectMetrics = new ArrayList();
131
private List/*<PackageMetric>*/ _vPackageMetrics = null;
132
private List _vImports = null;
133
private Map/*<String,PackageMetric>*/ _htPackages = null;
134
private Object[] _aoPackage = null;
137
* Just used for parseImports.
139
private File _sJavaSourceFile = null;
141
private Reader createSourceReader( File sSourceFile_ )
145
return newReader( sSourceFile_ );
147
catch ( IOException pIOException )
149
if ( Util.isEmpty( _sErrorMessage ) )
155
_sErrorMessage += "\n";
157
_sErrorMessage += "File not found: " + sSourceFile_.getAbsolutePath();
158
_thrwError = pIOException;
164
private void _measureSource( File sSourceFile_ ) throws IOException, Exception, Error
166
Reader reader = null;
171
reader = newReader( sSourceFile_ );
173
catch ( IOException pIOException )
175
if ( Util.isEmpty( _sErrorMessage ) )
181
_sErrorMessage += "\n";
183
_sErrorMessage += "File not found: " + sSourceFile_.getAbsolutePath();
184
_thrwError = pIOException;
189
String sTempErrorMessage = _sErrorMessage;
192
// the same method but with a Reader
193
_measureSource( reader );
195
catch ( Exception pParseException )
197
if ( sTempErrorMessage == null )
199
sTempErrorMessage = "";
201
sTempErrorMessage += "ParseException in " + sSourceFile_.getAbsolutePath() +
202
"\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction() + "\"\n";
203
sTempErrorMessage += pParseException.getMessage() + "\n";
205
_sErrorMessage = sTempErrorMessage;
206
_thrwError = pParseException;
208
throw pParseException;
210
catch ( Error pTokenMgrError )
212
if ( sTempErrorMessage == null )
214
sTempErrorMessage = "";
216
sTempErrorMessage += "TokenMgrError in " + sSourceFile_.getAbsolutePath() +
217
"\n" + pTokenMgrError.getMessage() + "\n";
218
_sErrorMessage = sTempErrorMessage;
219
_thrwError = pTokenMgrError;
221
throw pTokenMgrError;
225
private void _measureSource( Reader reader ) throws IOException, Exception, Error
227
Util.debug( "_measureSource(Reader).ENTER" );
228
//Util.debug( "_measureSource(Reader).parser15: -->" + (_pInit.getOptions().get( "parser15" ) + "<--" );
229
//Util.panicIf( _pInit == null );
230
//Util.panicIf( _pInit.getOptions() == null );
231
Util.debug( "_measureSource(Reader).ENTER2" );
234
// create a parser object
235
if ( Util.isDebug() == false )
237
if ( _pInit == null || _pInit.getOptions() == null || _pInit.getOptions().get( "parser15" ) == null ) {
238
Util.debug( "creating JavaParser" );
239
_pJavaParser = (JavaParserInterface)(new JavaParser( reader ));
241
Util.debug( "creating JavaParser15" );
242
_pJavaParser = (JavaParserInterface)(new JavaParser15( reader ));
245
if ( _pInit == null || _pInit.getOptions() == null || _pInit.getOptions().get( "parser15" ) == null ) {
246
Util.debug( "creating JavaParserDebug" );
247
Util.println( "creating JavaParserDebug" );
248
_pJavaParser = (JavaParserInterface)(new JavaParserDebug( reader ));
250
Util.debug( "creating JavaParser15Debug" );
251
_pJavaParser = (JavaParserInterface)(new JavaParser15Debug( reader ));
255
// execute the parser
256
_pJavaParser.parse();
257
Util.debug( "Javancss._measureSource(DataInputStream).SUCCESSFULLY_PARSED" );
259
_ncss += _pJavaParser.getNcss(); // increment the ncss
260
_loc += _pJavaParser.getLOC(); // and loc
261
// add new data to global vector
262
_vFunctionMetrics.addAll( _pJavaParser.getFunction() );
263
_vObjectMetrics.addAll( _pJavaParser.getObject() );
264
Map htNewPackages = _pJavaParser.getPackage();
266
/* List vNewPackages = new Vector(); */
267
for ( Iterator ePackages = htNewPackages.entrySet().iterator(); ePackages.hasNext(); )
269
String sPackage = (String) ( (Map.Entry) ePackages.next() ).getKey();
271
PackageMetric pckmNext = (PackageMetric) htNewPackages.get( sPackage );
272
pckmNext.name = sPackage;
274
PackageMetric pckmPrevious = (PackageMetric) _htPackages.get( sPackage );
275
pckmNext.add( pckmPrevious );
277
_htPackages.put( sPackage, pckmNext );
280
catch ( Exception pParseException )
282
if ( _sErrorMessage == null )
286
_sErrorMessage += "ParseException in STDIN";
287
if ( _pJavaParser != null )
289
_sErrorMessage += "\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction() + "\"\n";
291
_sErrorMessage += pParseException.getMessage() + "\n";
292
_thrwError = pParseException;
294
throw pParseException;
296
catch ( Error pTokenMgrError )
298
if ( _sErrorMessage == null )
302
_sErrorMessage += "TokenMgrError in STDIN\n";
303
_sErrorMessage += pTokenMgrError.getMessage() + "\n";
304
_thrwError = pTokenMgrError;
306
throw pTokenMgrError;
310
private void _measureFiles( List/*<File>*/ vJavaSourceFiles_ ) throws IOException, ParseException, TokenMgrError
313
for ( Iterator e = vJavaSourceFiles_.iterator(); e.hasNext(); )
315
File file = (File) e.next();
319
_measureSource( file );
321
catch ( Throwable pThrowable )
323
// hmm, do nothing? Use getLastError() or so to check for details.
329
* If arguments were provided, they are used, otherwise
330
* the input stream is used.
332
private void _measureRoot( Reader reader ) throws IOException, Exception, Error
334
_htPackages = new HashMap();
336
// either there are argument files, or stdin is used
337
if ( _vJavaSourceFiles == null )
339
_measureSource( reader );
343
// the collection of files get measured
344
_measureFiles( _vJavaSourceFiles );
347
_vPackageMetrics = new ArrayList();
348
for ( Iterator ePackages = _htPackages.keySet().iterator(); ePackages.hasNext(); )
350
String sPackage = (String) ePackages.next();
352
PackageMetric pckmNext = (PackageMetric) _htPackages.get( sPackage );
353
_vPackageMetrics.add( pckmNext );
357
public List getImports() {
362
* Return info about package statement.
363
* First element has name of package,
364
* then begin of line, etc.
366
public Object[] getPackage() {
371
* The same as getFunctionMetrics?!
373
public List/*<FunctionMetric>*/ getFunctions() {
374
return _vFunctionMetrics;
377
public Javancss( List/*<File>*/ vJavaSourceFiles_ )
379
_vJavaSourceFiles = vJavaSourceFiles_;
381
_measureRoot(newReader(System.in));
382
} catch(Exception e) {
384
} catch(TokenMgrError pError) {
385
pError.printStackTrace();
389
public Javancss( File sJavaSourceFile_ )
391
Util.debug( "Javancss.<init>(String).sJavaSourceFile_: " + sJavaSourceFile_ );
392
_sErrorMessage = null;
393
_vJavaSourceFiles = new ArrayList();
394
_vJavaSourceFiles.add(sJavaSourceFile_);
396
_measureRoot(newReader(System.in));
397
} catch(Exception e) {
398
Util.debug( "Javancss.<init>(String).e: " + e );
400
} catch(TokenMgrError pError) {
401
Util.debug( "Javancss.<init>(String).pError: " + pError );
402
pError.printStackTrace();
407
* cobertura: add this next constructor so any input stream can be used.
409
* It should be a copy of the Javancss(String) constructor, but just
410
* make sure _vJavaSourceFiles is null. _measureRoot will
411
* use the input stream if it is null.
413
public Javancss(InputStream isJavaSource_) {
414
Util.debug( "Javancss.<init>(InputStream).sJavaSourceFile_: " + isJavaSource_ );
415
_sErrorMessage = null;
416
_vJavaSourceFiles = null;
419
_measureRoot(newReader(isJavaSource_));
420
} catch(Exception e) {
421
Util.debug( "Javancss.<init>(InputStream).e: " + e );
423
} catch(TokenMgrError pError) {
424
Util.debug( "Javancss.<init>(InputStream).pError: " + pError );
425
pError.printStackTrace();
430
* Only way to create object that does not immediately
436
_sErrorMessage = null;
440
public boolean parseImports() {
441
if ( _sJavaSourceFile == null ) {
442
Util.debug( "Javancss.parseImports().NO_FILE" );
446
Reader reader = createSourceReader( _sJavaSourceFile );
447
if ( reader == null ) {
448
Util.debug( "Javancss.parseImports().NO_DIS" );
454
Util.debug( "Javancss.parseImports().START_PARSING" );
455
if ( Util.isDebug() == false ) {
456
_pJavaParser = (JavaParserInterface)(new JavaParser(reader));
458
_pJavaParser = (JavaParserInterface)(new JavaParserDebug(reader));
460
_pJavaParser.parseImportUnit();
461
_vImports = _pJavaParser.getImports();
462
_aoPackage = _pJavaParser.getPackageObjects();
463
Util.debug( "Javancss.parseImports().END_PARSING" );
464
} catch(Exception pParseException) {
465
Util.debug( "Javancss.parseImports().PARSE_EXCEPTION" );
466
if (_sErrorMessage == null) {
469
_sErrorMessage += "ParseException in STDIN";
470
if (_pJavaParser != null) {
471
_sErrorMessage += "\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction() + "\"\n";
473
_sErrorMessage += pParseException.getMessage() + "\n";
474
_thrwError = pParseException;
477
} catch(Error pTokenMgrError) {
478
Util.debug( "Javancss.parseImports().TOKEN_ERROR" );
479
if (_sErrorMessage == null) {
482
_sErrorMessage += "TokenMgrError in STDIN\n";
483
_sErrorMessage += pTokenMgrError.getMessage() + "\n";
484
_thrwError = pTokenMgrError;
492
public void setSourceFile( File javaSourceFile_ ) {
493
_sJavaSourceFile = javaSourceFile_;
494
_vJavaSourceFiles = new ArrayList();
495
_vJavaSourceFiles.add(javaSourceFile_);
497
private Init _pInit = null;
498
public int getNcss() {
502
public int getLOC() {
507
public int getJvdc() {
508
return _pJavaParser.getJvdc();
512
* JDCL stands for javadoc comment lines (while jvdc stands
513
* for number of javadoc comments).
515
public int getJdcl() {
516
return JavaParserTokenManager._iFormalComments;
520
return JavaParserTokenManager._iSingleComments;
524
return JavaParserTokenManager._iMultiComments;
528
public List getFunctionMetrics() {
529
return(_vFunctionMetrics);
532
public List/*<ObjectMetric>*/ getObjectMetrics() {
533
return(_vObjectMetrics);
537
* Returns list of packages in the form
538
* PackageMetric objects.
540
public List getPackageMetrics() {
541
return(_vPackageMetrics);
544
public String getLastErrorMessage() {
545
if (_sErrorMessage == null) {
548
return _sErrorMessage;
551
public Throwable getLastError() {
555
public void setExit() {
560
public String getEncoding()
565
public void setEncoding( String encoding )
567
this.encoding = encoding;
570
private Reader newReader( InputStream stream ) throws UnsupportedEncodingException
572
return ( encoding == null ) ? new InputStreamReader( stream ) : new InputStreamReader( stream, encoding );
575
private Reader newReader( File file ) throws FileNotFoundException, UnsupportedEncodingException
577
return newReader( new FileInputStream( file ) );