1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package javancss;
23
24 import java.awt.event.WindowAdapter;
25 import java.awt.event.WindowEvent;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileOutputStream;
30 import java.io.InputStream;
31 import java.io.IOException;
32 import java.io.InputStreamReader;
33 import java.io.OutputStream;
34 import java.io.OutputStreamWriter;
35 import java.io.PrintWriter;
36 import java.io.Reader;
37 import java.io.UnsupportedEncodingException;
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.HashMap;
41 import java.util.HashSet;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Set;
46
47 import ccl.util.Exitable;
48 import ccl.util.FileUtil;
49 import ccl.util.Init;
50 import ccl.util.Util;
51
52 import javancss.parser.JavaParser;
53 import javancss.parser.JavaParserInterface;
54 import javancss.parser.JavaParserTokenManager;
55 import javancss.parser.ParseException;
56 import javancss.parser.TokenMgrError;
57 import javancss.parser.debug.JavaParserDebug;
58 import javancss.parser.java15.JavaParser15;
59 import javancss.parser.java15.debug.JavaParser15Debug;
60 import javancss.test.JavancssTest;
61
62
63
64
65
66
67
68
69
70
71
72
73 public class Javancss implements Exitable
74 {
75 private static final String S_INIT__FILE_CONTENT =
76 "[Init]\n" +
77 "Author=Chr. Clemens Lee\n" +
78 "\n" +
79 "[Help]\n"+
80 "; Please do not edit the Help section\n"+
81 "HelpUsage=@srcfiles.txt | *.java | <stdin>\n" +
82 "Options=ncss,package,object,function,all,gui,xml,out,recursive,check,encoding,parser15\n" +
83 "ncss=b,o,Counts the program NCSS (default).\n" +
84 "package=b,o,Assembles a statistic on package level.\n" +
85 "object=b,o,Counts the object NCSS.\n" +
86 "function=b,o,Counts the function NCSS.\n" +
87 "all=b,o,The same as '-function -object -package'.\n" +
88 "gui=b,o,Opens a gui to present the '-all' output in tabbed panels.\n" +
89 "xml=b,o,Output in xml format.\n" +
90 "out=s,o,Output file name. By default output goes to standard out.\n"+
91 "recursive=b,o,Recurse to subdirs.\n" +
92 "check=b,o,Triggers a javancss self test.\n" +
93 "encoding=s,o,Encoding used while reading source files (default: platform encoding).\n" +
94 "parser15=b,o,Use new experimental Java 1.5 parser.\n" +
95 "\n" +
96 "[Colors]\n" +
97 "UseSystemColors=true\n";
98
99 private boolean _bExit = false;
100
101 private List
102 private String encoding = null;
103
104 private String _sErrorMessage = null;
105 private Throwable _thrwError = null;
106
107 private JavaParserInterface _pJavaParser = null;
108 private int _ncss = 0;
109 private int _loc = 0;
110 private List
111 private List
112 private List
113 private List _vImports = null;
114 private Map
115 private Object[] _aoPackage = null;
116
117
118
119
120 private File _sJavaSourceFile = null;
121
122 private Reader createSourceReader( File sSourceFile_ )
123 {
124 try
125 {
126 return newReader( sSourceFile_ );
127 }
128 catch ( IOException pIOException )
129 {
130 if ( Util.isEmpty( _sErrorMessage ) )
131 {
132 _sErrorMessage = "";
133 }
134 else
135 {
136 _sErrorMessage += "\n";
137 }
138 _sErrorMessage += "File not found: " + sSourceFile_.getAbsolutePath();
139 _thrwError = pIOException;
140
141 return null;
142 }
143 }
144
145 private void _measureSource( File sSourceFile_ ) throws IOException, Exception, Error
146 {
147 Reader reader = null;
148
149
150 try
151 {
152 reader = newReader( sSourceFile_ );
153 }
154 catch ( IOException pIOException )
155 {
156 if ( Util.isEmpty( _sErrorMessage ) )
157 {
158 _sErrorMessage = "";
159 }
160 else
161 {
162 _sErrorMessage += "\n";
163 }
164 _sErrorMessage += "File not found: " + sSourceFile_.getAbsolutePath();
165 _thrwError = pIOException;
166
167 throw pIOException;
168 }
169
170 String sTempErrorMessage = _sErrorMessage;
171 try
172 {
173
174 _measureSource( reader );
175 }
176 catch ( Exception pParseException )
177 {
178 if ( sTempErrorMessage == null )
179 {
180 sTempErrorMessage = "";
181 }
182 sTempErrorMessage += "ParseException in " + sSourceFile_.getAbsolutePath() +
183 "\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction() + "\"\n";
184 sTempErrorMessage += pParseException.getMessage() + "\n";
185
186 _sErrorMessage = sTempErrorMessage;
187 _thrwError = pParseException;
188
189 throw pParseException;
190 }
191 catch ( Error pTokenMgrError )
192 {
193 if ( sTempErrorMessage == null )
194 {
195 sTempErrorMessage = "";
196 }
197 sTempErrorMessage += "TokenMgrError in " + sSourceFile_.getAbsolutePath() +
198 "\n" + pTokenMgrError.getMessage() + "\n";
199 _sErrorMessage = sTempErrorMessage;
200 _thrwError = pTokenMgrError;
201
202 throw pTokenMgrError;
203 }
204 }
205
206 private void _measureSource( Reader reader ) throws IOException, Exception, Error
207 {
208 Util.debug( "_measureSource(Reader).ENTER" );
209
210
211
212 Util.debug( "_measureSource(Reader).ENTER2" );
213 try
214 {
215
216 if ( Util.isDebug() == false )
217 {
218 if ( _pInit == null || _pInit.getOptions() == null || _pInit.getOptions().get( "parser15" ) == null ) {
219 Util.debug( "creating JavaParser" );
220 _pJavaParser = (JavaParserInterface)(new JavaParser( reader ));
221 } else {
222 Util.debug( "creating JavaParser15" );
223 _pJavaParser = (JavaParserInterface)(new JavaParser15( reader ));
224 }
225 } else {
226 if ( _pInit == null || _pInit.getOptions() == null || _pInit.getOptions().get( "parser15" ) == null ) {
227 Util.debug( "creating JavaParserDebug" );
228 Util.println( "creating JavaParserDebug" );
229 _pJavaParser = (JavaParserInterface)(new JavaParserDebug( reader ));
230 } else {
231 Util.debug( "creating JavaParser15Debug" );
232 _pJavaParser = (JavaParserInterface)(new JavaParser15Debug( reader ));
233 }
234 }
235
236
237 _pJavaParser.parse();
238 Util.debug( "Javancss._measureSource(DataInputStream).SUCCESSFULLY_PARSED" );
239
240 _ncss += _pJavaParser.getNcss();
241 _loc += _pJavaParser.getLOC();
242
243 _vFunctionMetrics.addAll( _pJavaParser.getFunction() );
244 _vObjectMetrics.addAll( _pJavaParser.getObject() );
245 Map htNewPackages = _pJavaParser.getPackage();
246
247
248 for ( Iterator ePackages = htNewPackages.entrySet().iterator(); ePackages.hasNext(); )
249 {
250 String sPackage = (String) ( (Map.Entry) ePackages.next() ).getKey();
251
252 PackageMetric pckmNext = (PackageMetric) htNewPackages.get( sPackage );
253 pckmNext.name = sPackage;
254
255 PackageMetric pckmPrevious = (PackageMetric) _htPackages.get( sPackage );
256 pckmNext.add( pckmPrevious );
257
258 _htPackages.put( sPackage, pckmNext );
259 }
260 }
261 catch ( Exception pParseException )
262 {
263 if ( _sErrorMessage == null )
264 {
265 _sErrorMessage = "";
266 }
267 _sErrorMessage += "ParseException in STDIN";
268 if ( _pJavaParser != null )
269 {
270 _sErrorMessage += "\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction() + "\"\n";
271 }
272 _sErrorMessage += pParseException.getMessage() + "\n";
273 _thrwError = pParseException;
274
275 throw pParseException;
276 }
277 catch ( Error pTokenMgrError )
278 {
279 if ( _sErrorMessage == null )
280 {
281 _sErrorMessage = "";
282 }
283 _sErrorMessage += "TokenMgrError in STDIN\n";
284 _sErrorMessage += pTokenMgrError.getMessage() + "\n";
285 _thrwError = pTokenMgrError;
286
287 throw pTokenMgrError;
288 }
289 }
290
291 private void _measureFiles( List
292 {
293
294 for ( Iterator e = vJavaSourceFiles_.iterator(); e.hasNext(); )
295 {
296 File file = (File) e.next();
297
298 try
299 {
300 _measureSource( file );
301 }
302 catch ( Throwable pThrowable )
303 {
304
305 }
306 }
307 }
308
309
310
311
312
313 private void _measureRoot( Reader reader ) throws IOException, Exception, Error
314 {
315 _htPackages = new HashMap();
316
317
318 if ( _vJavaSourceFiles == null )
319 {
320 _measureSource( reader );
321 }
322 else
323 {
324
325 _measureFiles( _vJavaSourceFiles );
326 }
327
328 _vPackageMetrics = new ArrayList();
329 for ( Iterator ePackages = _htPackages.keySet().iterator(); ePackages.hasNext(); )
330 {
331 String sPackage = (String) ePackages.next();
332
333 PackageMetric pckmNext = (PackageMetric) _htPackages.get( sPackage );
334 _vPackageMetrics.add( pckmNext );
335 }
336 Collections.sort( _vPackageMetrics );
337 }
338
339 public List getImports() {
340 return _vImports;
341 }
342
343
344
345
346
347
348 public Object[] getPackage() {
349 return _aoPackage;
350 }
351
352
353
354
355 public List
356 return _vFunctionMetrics;
357 }
358
359 public String printObjectNcss() {
360 return getFormatter().printObjectNcss();
361 }
362
363 public String printFunctionNcss() {
364 return getFormatter().printFunctionNcss();
365 }
366
367 public String printPackageNcss() {
368 return getFormatter().printPackageNcss();
369 }
370
371 public String printJavaNcss() {
372 return getFormatter().printJavaNcss();
373 }
374
375 public Javancss( List
376 {
377 _vJavaSourceFiles = vJavaSourceFiles_;
378 try {
379 _measureRoot(newReader(System.in));
380 } catch(Exception e) {
381 e.printStackTrace();
382 } catch(TokenMgrError pError) {
383 pError.printStackTrace();
384 }
385 }
386
387 public Javancss( File sJavaSourceFile_ )
388 {
389 Util.debug( "Javancss.<init>(String).sJavaSourceFile_: " + sJavaSourceFile_ );
390 _sErrorMessage = null;
391 _vJavaSourceFiles = new ArrayList();
392 _vJavaSourceFiles.add(sJavaSourceFile_);
393 try {
394 _measureRoot(newReader(System.in));
395 } catch(Exception e) {
396 Util.debug( "Javancss.<init>(String).e: " + e );
397 e.printStackTrace();
398 } catch(TokenMgrError pError) {
399 Util.debug( "Javancss.<init>(String).pError: " + pError );
400 pError.printStackTrace();
401 }
402 }
403
404
405
406
407
408 public Javancss() {
409 super();
410
411 _sErrorMessage = null;
412 _thrwError = null;
413 }
414
415 public boolean parseImports() {
416 if ( _sJavaSourceFile == null ) {
417 Util.debug( "Javancss.parseImports().NO_FILE" );
418
419 return true;
420 }
421 Reader reader = createSourceReader( _sJavaSourceFile );
422 if ( reader == null ) {
423 Util.debug( "Javancss.parseImports().NO_DIS" );
424
425 return true;
426 }
427
428 try {
429 Util.debug( "Javancss.parseImports().START_PARSING" );
430 if ( Util.isDebug() == false ) {
431 _pJavaParser = (JavaParserInterface)(new JavaParser(reader));
432 } else {
433 _pJavaParser = (JavaParserInterface)(new JavaParserDebug(reader));
434 }
435 _pJavaParser.parseImportUnit();
436 _vImports = _pJavaParser.getImports();
437 _aoPackage = _pJavaParser.getPackageObjects();
438 Util.debug( "Javancss.parseImports().END_PARSING" );
439 } catch(Exception pParseException) {
440 Util.debug( "Javancss.parseImports().PARSE_EXCEPTION" );
441 if (_sErrorMessage == null) {
442 _sErrorMessage = "";
443 }
444 _sErrorMessage += "ParseException in STDIN";
445 if (_pJavaParser != null) {
446 _sErrorMessage += "\nLast useful checkpoint: \"" + _pJavaParser.getLastFunction() + "\"\n";
447 }
448 _sErrorMessage += pParseException.getMessage() + "\n";
449 _thrwError = pParseException;
450
451 return true;
452 } catch(Error pTokenMgrError) {
453 Util.debug( "Javancss.parseImports().TOKEN_ERROR" );
454 if (_sErrorMessage == null) {
455 _sErrorMessage = "";
456 }
457 _sErrorMessage += "TokenMgrError in STDIN\n";
458 _sErrorMessage += pTokenMgrError.getMessage() + "\n";
459 _thrwError = pTokenMgrError;
460
461 return true;
462 }
463
464 return false;
465 }
466
467 public void setSourceFile( File javaSourceFile_ ) {
468 _sJavaSourceFile = javaSourceFile_;
469 _vJavaSourceFiles = new ArrayList();
470 _vJavaSourceFiles.add(javaSourceFile_);
471 }
472
473 public Javancss(Reader reader) {
474 try {
475 _measureRoot(reader);
476 } catch(Exception e) {
477 } catch(TokenMgrError pError) {
478 }
479 }
480
481
482
483
484
485
486 private static void _addJavaFiles( File dir, List v
487 {
488 File[] files = dir.listFiles();
489 if( files == null || files.length == 0 )
490 {
491 return;
492 }
493
494 for( int i = 0; i < files.length; i++ )
495 {
496 File newFile = files[i];
497 if( newFile.isDirectory() )
498 {
499
500 _addJavaFiles( newFile, v );
501 }
502 else
503 {
504 if( newFile.getName().endsWith( ".java" ) )
505 {
506 v.add( newFile );
507 }
508 }
509 }
510 }
511
512 private List
513 {
514 if ( Util.isDebug() )
515 {
516 Util.debug( "filenames: " + Util.toString( filenames ) );
517 }
518 if ( filenames.size() == 0 )
519 {
520 if ( recursive )
521 {
522
523 filenames.add( "." );
524 }
525 else
526 {
527 return null;
528 }
529 }
530
531 Set _processedAtFiles = new HashSet();
532 List newFiles = new ArrayList();
533 for ( Iterator iter = filenames.iterator(); iter.hasNext(); )
534 {
535 String filename = (String)iter.next();
536
537
538 if ( filename.startsWith( "@" ) )
539 {
540 filename = filename.substring( 1 );
541 if ( filename.length() > 1 )
542 {
543 filename = FileUtil.normalizeFileName( filename );
544 if ( _processedAtFiles.add( filename ) )
545 {
546 String sJavaSourceFileNames = null;
547 try
548 {
549 sJavaSourceFileNames = FileUtil.readFile( filename );
550 }
551 catch( IOException pIOException )
552 {
553 _sErrorMessage = "File Read Error: " + filename;
554 _thrwError = pIOException;
555 throw pIOException;
556 }
557 List vTheseJavaSourceFiles = Util.stringToLines( sJavaSourceFileNames );
558 for ( Iterator iterator = vTheseJavaSourceFiles.iterator(); iterator.hasNext(); )
559 {
560 newFiles.add( new File( (String)iterator.next() ) );
561 }
562 }
563 }
564 }
565 else
566 {
567 filename = FileUtil.normalizeFileName( filename );
568 File file = new File( filename );
569 if ( file.isDirectory() )
570 {
571 _addJavaFiles( file, newFiles );
572 }
573 else
574 {
575 newFiles.add( file );
576 }
577 }
578 }
579
580 if ( Util.isDebug() )
581 {
582 Util.debug( "resolved filenames: " + Util.toString( newFiles ) );
583 }
584
585 return newFiles;
586 }
587
588 private Init _pInit = null;
589
590
591
592
593 public Javancss(String[] asArgs_, String sRcsHeader_) throws IOException {
594 this(asArgs_);
595 }
596
597
598
599
600
601
602
603 public Javancss(String[] asArgs_) throws IOException {
604 _pInit = new Init(this, asArgs_, Main.S_RCS_HEADER, S_INIT__FILE_CONTENT);
605 if (_bExit) {
606 return;
607 }
608 Map htOptions = _pInit.getOptions();
609
610 setEncoding( (String) htOptions.get( "encoding" ) );
611
612 if ( htOptions.get( "check" ) != null ) {
613 new JavancssTest().main( new File( _pInit.getApplicationPath() ) );
614 return;
615 }
616
617
618 _vJavaSourceFiles = findFiles( _pInit.getArguments(), htOptions.get( "recursive" ) != null );
619
620 if ( htOptions.get( "gui" ) != null )
621 {
622 final JavancssFrame pJavancssFrame = new JavancssFrame(_pInit);
623
624 pJavancssFrame.addWindowListener(new WindowAdapter() {
625 public void windowClosing(WindowEvent e_) {
626 Util.debug("JavancssAll.run().WindowAdapter.windowClosing().1");
627 pJavancssFrame.setVisible(false);
628 pJavancssFrame.dispose();
629 }
630 });
631 pJavancssFrame.setVisible(true);
632
633 try {
634 _measureRoot(newReader(System.in));
635 } catch(Throwable pThrowable) {
636
637 }
638
639 pJavancssFrame.showJavancss(this);
640 pJavancssFrame.setSelectedTab(JavancssFrame.S_PACKAGES);
641 pJavancssFrame.run();
642
643 return;
644 }
645
646
647 try
648 {
649 _measureRoot( newReader( System.in ) );
650 }
651 catch(Throwable pThrowable)
652 {
653 }
654 if ( getLastErrorMessage() != null )
655 {
656 Util.printlnErr( getLastErrorMessage() + "\n" );
657 if ( getNcss() <= 0 )
658 {
659 return;
660 }
661 }
662
663 boolean bNoNCSS = false;
664
665 String sOutputFile = (String)htOptions.get( "out" );
666 OutputStream out = System.out;
667 if (sOutputFile != null)
668 {
669 try
670 {
671 out = new FileOutputStream( FileUtil.normalizeFileName( sOutputFile ) );
672 } catch ( Exception exception ) {
673 Util.printlnErr( "Error opening output file '"
674 + sOutputFile
675 + "': " + exception.getMessage() );
676
677 out = System.out;
678 sOutputFile = null;
679 }
680 }
681
682 PrintWriter pw = useXML() ? new PrintWriter(new OutputStreamWriter(out, "UTF-8")) : new PrintWriter(out);
683
684 if ( useXML() )
685 {
686 pw.print( XmlFormatter.printStart() );
687 }
688
689 if (htOptions.get( "package" ) != null ||
690 htOptions.get( "all" ) != null)
691 {
692 pw.print( printPackageNcss() );
693 bNoNCSS = true;
694 }
695 if (htOptions.get( "object" ) != null ||
696 htOptions.get( "all" ) != null)
697 {
698 if ( bNoNCSS )
699 {
700 pw.println();
701 }
702 pw.print( printObjectNcss() );
703 bNoNCSS = true;
704 }
705 if (htOptions.get( "function" ) != null ||
706 htOptions.get( "all" ) != null)
707 {
708 if ( bNoNCSS )
709 {
710 pw.println();
711 }
712 pw.print( printFunctionNcss() );
713 bNoNCSS = true;
714 }
715 if (!bNoNCSS) {
716 pw.print( printJavaNcss() );
717 }
718
719 if ( useXML() )
720 {
721 if ( !bNoNCSS )
722 {
723 pw.print( printJavaNcss() );
724 }
725 pw.println( "</javancss>" );
726 }
727
728 if ( sOutputFile != null )
729 {
730 pw.close();
731 } else
732 {
733
734 pw.flush();
735 }
736 }
737
738 public int getNcss() {
739 return _ncss;
740 }
741
742 public int getLOC() {
743 return _loc;
744 }
745
746
747 public int getJvdc() {
748 return _pJavaParser.getJvdc();
749 }
750
751
752
753
754
755 public int getJdcl() {
756 return JavaParserTokenManager._iFormalComments;
757 }
758
759 public int getSl() {
760 return JavaParserTokenManager._iSingleComments;
761 }
762
763 public int getMl() {
764 return JavaParserTokenManager._iMultiComments;
765 }
766
767
768 public List getFunctionMetrics() {
769 return(_vFunctionMetrics);
770 }
771
772 public List
773 return(_vObjectMetrics);
774 }
775
776
777
778
779
780 public List getPackageMetrics() {
781 return(_vPackageMetrics);
782 }
783
784 public String getLastErrorMessage() {
785 if (_sErrorMessage == null) {
786 return null;
787 }
788 return _sErrorMessage;
789 }
790
791 public Throwable getLastError() {
792 return _thrwError;
793 }
794
795 public void setExit() {
796 _bExit = true;
797 }
798
799 private boolean _bXML = false;
800
801 public void setXML( boolean bXML )
802 {
803 _bXML = bXML;
804 }
805
806 public boolean useXML()
807 {
808 return _bXML
809 || (_pInit != null && _pInit.getOptions().get( "xml" ) != null );
810 }
811
812 public Formatter getFormatter()
813 {
814 if ( useXML() )
815 {
816 return new XmlFormatter( this );
817 }
818
819 return new AsciiFormatter( this );
820 }
821
822 public String getEncoding()
823 {
824 return encoding;
825 }
826
827 public void setEncoding( String encoding )
828 {
829 this.encoding = encoding;
830 }
831
832 private Reader newReader( InputStream stream ) throws UnsupportedEncodingException
833 {
834 return ( encoding == null ) ? new InputStreamReader( stream ) : new InputStreamReader( stream, encoding );
835 }
836
837 private Reader newReader( File file ) throws FileNotFoundException, UnsupportedEncodingException
838 {
839 return newReader( new FileInputStream( file ) );
840 }
841 }