001 /* 002 Copyright (C) 2000 Chr. Clemens Lee <clemens@kclee.com>. 003 004 This file is part of JavaNCSS 005 (http://www.kclee.com/clemens/java/javancss/). 006 007 JavaNCSS is free software; you can redistribute it and/or modify it 008 under the terms of the GNU General Public License as published by the 009 Free Software Foundation; either version 2, or (at your option) any 010 later version. 011 012 JavaNCSS is distributed in the hope that it will be useful, but WITHOUT 013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 015 for more details. 016 017 You should have received a copy of the GNU General Public License 018 along with JavaNCSS; see the file COPYING. If not, write to 019 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 020 Boston, MA 02111-1307, USA. */ 021 022 package javancss; 023 024 import java.awt.event.WindowAdapter; 025 import java.awt.event.WindowEvent; 026 import java.io.File; 027 import java.io.FileInputStream; 028 import java.io.FileNotFoundException; 029 import java.io.FileOutputStream; 030 import java.io.InputStream; 031 import java.io.IOException; 032 import java.io.InputStreamReader; 033 import java.io.OutputStream; 034 import java.io.OutputStreamWriter; 035 import java.io.PrintWriter; 036 import java.io.Reader; 037 import java.io.UnsupportedEncodingException; 038 import java.util.ArrayList; 039 import java.util.Collections; 040 import java.util.HashMap; 041 import java.util.HashSet; 042 import java.util.Iterator; 043 import java.util.List; 044 import java.util.Map; 045 import java.util.Set; 046 047 import ccl.util.Exitable; 048 import ccl.util.FileUtil; 049 import ccl.util.Init; 050 import ccl.util.Util; 051 052 import javancss.parser.JavaParser; 053 import javancss.parser.JavaParserInterface; 054 import javancss.parser.JavaParserTokenManager; 055 import javancss.parser.ParseException; 056 import javancss.parser.TokenMgrError; 057 import javancss.parser.debug.JavaParserDebug; 058 import javancss.parser.java15.JavaParser15; 059 import javancss.parser.java15.debug.JavaParser15Debug; 060 import javancss.test.JavancssTest; 061 062 /** 063 * While the Java parser class might be the heart of JavaNCSS, 064 * this class is the brain. This class controls input and output and 065 * invokes the Java parser. 066 * 067 * @author Chr. Clemens Lee <clemens@kclee.com> 068 * , recursive feature by P??k? Hannu 069 * , additional javadoc metrics by Emilio Gongora <emilio@sms.nl> 070 * , and Guillermo Rodriguez <guille@sms.nl>. 071 * @version $Id: Javancss.java 157 2009-05-24 06:59:58Z hboutemy $ 072 */ 073 public class Javancss implements Exitable 074 { 075 private static final String S_INIT__FILE_CONTENT = 076 "[Init]\n" + 077 "Author=Chr. Clemens Lee\n" + 078 "\n" + 079 "[Help]\n"+ 080 "; Please do not edit the Help section\n"+ 081 "HelpUsage=@srcfiles.txt | *.java | <stdin>\n" + 082 "Options=ncss,package,object,function,all,gui,xml,out,recursive,check,encoding,parser15\n" + 083 "ncss=b,o,Counts the program NCSS (default).\n" + 084 "package=b,o,Assembles a statistic on package level.\n" + 085 "object=b,o,Counts the object NCSS.\n" + 086 "function=b,o,Counts the function NCSS.\n" + 087 "all=b,o,The same as '-function -object -package'.\n" + 088 "gui=b,o,Opens a gui to present the '-all' output in tabbed panels.\n" + 089 "xml=b,o,Output in xml format.\n" + 090 "out=s,o,Output file name. By default output goes to standard out.\n"+ 091 "recursive=b,o,Recurse to subdirs.\n" + 092 "check=b,o,Triggers a javancss self test.\n" + 093 "encoding=s,o,Encoding used while reading source files (default: platform encoding).\n" + 094 "parser15=b,o,Use new experimental Java 1.5 parser.\n" + 095 "\n" + 096 "[Colors]\n" + 097 "UseSystemColors=true\n"; 098 099 private boolean _bExit = false; 100 101 private List/*<File>*/ _vJavaSourceFiles = null; 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/*<FunctionMetric>*/ _vFunctionMetrics = new ArrayList(); 111 private List/*<ObjectMetric>*/ _vObjectMetrics = new ArrayList(); 112 private List/*<PackageMetric>*/ _vPackageMetrics = null; 113 private List _vImports = null; 114 private Map/*<String,PackageMetric>*/ _htPackages = null; 115 private Object[] _aoPackage = null; 116 117 /** 118 * Just used for parseImports. 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 // opens the file 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 // the same method but with a Reader 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 //Util.debug( "_measureSource(Reader).parser15: -->" + (_pInit.getOptions().get( "parser15" ) + "<--" ); 210 //Util.panicIf( _pInit == null ); 211 //Util.panicIf( _pInit.getOptions() == null ); 212 Util.debug( "_measureSource(Reader).ENTER2" ); 213 try 214 { 215 // create a parser object 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 // execute the parser 237 _pJavaParser.parse(); 238 Util.debug( "Javancss._measureSource(DataInputStream).SUCCESSFULLY_PARSED" ); 239 240 _ncss += _pJavaParser.getNcss(); // increment the ncss 241 _loc += _pJavaParser.getLOC(); // and loc 242 // add new data to global vector 243 _vFunctionMetrics.addAll( _pJavaParser.getFunction() ); 244 _vObjectMetrics.addAll( _pJavaParser.getObject() ); 245 Map htNewPackages = _pJavaParser.getPackage(); 246 247 /* List vNewPackages = new Vector(); */ 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/*<File>*/ vJavaSourceFiles_ ) throws IOException, ParseException, TokenMgrError 292 { 293 // for each file 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 // hmm, do nothing? Use getLastError() or so to check for details. 305 } 306 } 307 } 308 309 /** 310 * If arguments were provided, they are used, otherwise 311 * the input stream is used. 312 */ 313 private void _measureRoot( Reader reader ) throws IOException, Exception, Error 314 { 315 _htPackages = new HashMap(); 316 317 // either there are argument files, or stdin is used 318 if ( _vJavaSourceFiles == null ) 319 { 320 _measureSource( reader ); 321 } 322 else 323 { 324 // the collection of files get measured 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 * Return info about package statement. 345 * First element has name of package, 346 * then begin of line, etc. 347 */ 348 public Object[] getPackage() { 349 return _aoPackage; 350 } 351 352 /** 353 * The same as getFunctionMetrics?! 354 */ 355 public List/*<FunctionMetric>*/ getFunctions() { 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/*<File>*/ vJavaSourceFiles_ ) 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 * Only way to create object that does not immediately 406 * start to parse. 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 * recursively adds *.java files 483 * @param dir the base directory to search 484 * @param v the list of file to add found files to 485 */ 486 private static void _addJavaFiles( File dir, List v/*<File>*/ ) 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 //Recurse!!! 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/*<File>*/ findFiles( List/*<String>*/ filenames, boolean recursive ) throws IOException 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 // If no files then add current directory! 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 // if the file specifies other files... 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 * @deprecated use Javancss(String[]) instead, since the sRcsHeader_ parameter is not useful 592 */ 593 public Javancss(String[] asArgs_, String sRcsHeader_) throws IOException { 594 this(asArgs_); 595 } 596 597 /** 598 * This is the constructor used in the main routine in 599 * javancss.Main. 600 * Other constructors might be helpful to use Javancss out 601 * of other programs. 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 // the arguments (the files) to be processed 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 // /*final Thread pThread = Thread.currentThread();*/ 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 // // shouldn't we print something here? 637 // } 638 // 639 // pJavancssFrame.showJavancss(this); 640 // pJavancssFrame.setSelectedTab(JavancssFrame.S_PACKAGES); 641 // pJavancssFrame.run(); 642 // 643 // return; 644 // } 645 646 // this initiates the measurement 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 // TODO: encoding configuration support for result output 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 // stdout is used: don't close but ensure everything is flushed 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 // added by SMS 747 public int getJvdc() { 748 return _pJavaParser.getJvdc(); 749 } 750 751 /** 752 * JDCL stands for javadoc comment lines (while jvdc stands 753 * for number of javadoc comments). 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/*<ObjectMetric>*/ getObjectMetrics() { 773 return(_vObjectMetrics); 774 } 775 776 /** 777 * Returns list of packages in the form 778 * PackageMetric objects. 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 }