1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.tdk.jcov; 26 27 import com.sun.tdk.jcov.instrument.DataMethod; 28 import com.sun.tdk.jcov.instrument.DataField; 29 import com.sun.tdk.jcov.instrument.DataClass; 30 import com.sun.tdk.jcov.processing.DataProcessorSPI; 31 import com.sun.tdk.jcov.report.AncFilter; 32 import com.sun.tdk.jcov.report.ancfilters.DefaultAncFilter; 33 import com.sun.tdk.jcov.util.Utils; 34 import com.sun.tdk.jcov.data.FileFormatException; 35 import com.sun.tdk.jcov.data.Result; 36 import com.sun.tdk.jcov.instrument.DataRoot; 37 import com.sun.tdk.jcov.processing.ProcessingException; 38 39 import com.sun.tdk.jcov.tools.EnvHandler; 40 import com.sun.tdk.jcov.tools.OptionDescr; 41 import com.sun.tdk.jcov.io.Reader; 42 import com.sun.tdk.jcov.filter.ConveyerFilter; 43 import com.sun.tdk.jcov.filter.MemberFilter; 44 import com.sun.tdk.jcov.filter.FilterFactory; 45 import com.sun.tdk.jcov.instrument.InstrumentationOptions; 46 import com.sun.tdk.jcov.io.ClassSignatureFilter; 47 import com.sun.tdk.jcov.processing.DefaultDataProcessorSPI; 48 import com.sun.tdk.jcov.processing.StubSpi; 49 import com.sun.tdk.jcov.report.DefaultReportGeneratorSPI; 50 import com.sun.tdk.jcov.report.ProductCoverage; 51 import com.sun.tdk.jcov.report.ReportGenerator; 52 import com.sun.tdk.jcov.report.ReportGeneratorSPI; 53 import com.sun.tdk.jcov.report.SmartTestService; 54 import com.sun.tdk.jcov.report.javap.JavapClass; 55 import com.sun.tdk.jcov.report.javap.JavapRepGen; 56 import com.sun.tdk.jcov.tools.JCovCMDTool; 57 import com.sun.tdk.jcov.tools.SPIDescr; 58 import java.io.IOException; 59 import java.util.ArrayList; 60 import java.util.logging.Level; 61 import java.util.logging.Logger; 62 63 import static com.sun.tdk.jcov.tools.OptionDescr.*; 64 import java.io.File; 65 import java.util.Arrays; 66 import java.util.ServiceLoader; 67 import java.util.List; 68 import org.objectweb.asm.Opcodes; 69 70 /** 71 * <p> Report generation. </p> 72 * 73 * @author Andrey Titov 74 * @author Dmitry Fazunenko 75 * @author Alexey Fedorchenko 76 */ 77 public class RepGen extends JCovCMDTool { 78 79 final static String CUSTOM_REPORT_GENERATOR_SPI = "customreport.spi"; 80 final static String DATA_PROCESSOR_SPI = "dataprocessor.spi"; 81 82 // logger initialization 83 static { 84 Utils.initLogger(); 85 logger = Logger.getLogger(RepGen.class.getName()); 86 } 87 private final static Logger logger; 88 /** 89 * Consider or not enums. true - means ignore enum classes. 90 */ 91 private boolean noEnums = false; 92 /** 93 * Whether show or not field coverage in the report (false by default). 94 */ 95 private boolean showFields = false; 96 private ReportGeneratorSPI reportGeneratorSPIs[]; 97 private DataProcessorSPI dataProcessorSPIs[]; 98 private String[] include = new String[]{".*"}; 99 private String[] exclude = new String[]{""}; 100 private String[] m_include = new String[]{".*"}; 101 private String[] m_exclude = new String[]{""}; 102 private String[] fms = null; 103 private String filter = null; 104 private String[] ancfilters = null; 105 private String[] ancdeffilters = null; 106 private boolean noAbstract = false; 107 private boolean syntheticOn = false; 108 private boolean isPublicAPI = false; 109 private String[] filenames; 110 private String name; 111 private String outputDir; 112 private String testlist; 113 private String srcRootPath; 114 private boolean anonym = false; 115 private boolean withTestsInfo = false; 116 //path to the jar, dir or .class for javap repgen 117 private String classesPath; 118 private AncFilter[] ancfiltersClasses = null; 119 private String mainReportTitle = null; 120 private String overviewListTitle = null; 121 private String entitiesTitle = null; 122 123 public RepGen() { 124 readPlugins = true; 125 } 126 127 /** 128 * Generate report using default (html) report generator 129 * 130 * @param output 131 * @param jcovResult 132 * @throws ProcessingException 133 * @throws FileFormatException 134 * @throws Exception 135 */ 136 public void generateReport(String output, Result jcovResult) throws ProcessingException, FileFormatException, Exception { 137 generateReport(getDefaultReportGenerator(), output, jcovResult, null); 138 } 139 140 /** 141 * Generate report using specified format 142 * 143 * @param format 144 * @param output 145 * @param jcovResult 146 * @throws ProcessingException 147 * @throws FileFormatException 148 * @throws Exception 149 */ 150 public void generateReport(String format, String output, Result jcovResult) throws ProcessingException, FileFormatException, Exception { 151 generateReport(format, output, jcovResult, null); 152 } 153 154 /** 155 * Generate report using specified format 156 * 157 * @param format 158 * @param output 159 * @param jcovResult 160 * @param srcRootPath 161 * @throws ProcessingException 162 * @throws FileFormatException 163 * @throws Exception 164 */ 165 public void generateReport(String format, String output, Result jcovResult, String srcRootPath) throws ProcessingException, FileFormatException, Exception { 166 ReportGenerator rg = null; 167 if (format != null) { 168 rg = findReportGenerator(format); 169 } else { 170 rg = getDefaultReportGenerator(); 171 } 172 if (rg == null) { 173 throw new Exception("Specified ReportGenerator name (" + format + ") was not found"); 174 } 175 176 generateReport(rg, output, jcovResult, srcRootPath); 177 } 178 179 /** 180 * Generate report using specified report generator 181 * 182 * @param rg 183 * @param output 184 * @param jcovResult 185 * @param srcRootPath 186 * @throws ProcessingException 187 * @throws FileFormatException 188 * @throws Exception 189 */ 190 public void generateReport(ReportGenerator rg, String output, Result jcovResult, String srcRootPath) throws ProcessingException, FileFormatException, Exception { 191 generateReport(rg, output, jcovResult, srcRootPath, null); 192 } 193 194 /** 195 * Generate report using specified report generator 196 * 197 * @param rg 198 * @param output 199 * @param jcovResult 200 * @param srcRootPath 201 * @param classes parsed javap classes 202 * @throws ProcessingException 203 * @throws FileFormatException 204 * @throws Exception 205 */ 206 public void generateReport(ReportGenerator rg, String output, Result jcovResult, String srcRootPath, List<JavapClass> classes) throws ProcessingException, FileFormatException, Exception { 207 try { 208 logger.log(Level.INFO, "-- Writing report to {0}", output); 209 rg.init(output); 210 logger.fine("OK"); 211 } catch (Throwable ex) { 212 logger.log(Level.SEVERE, "Error while reading output file by ReportGenerator " + rg.getClass().getName(), ex); 213 return; 214 } 215 216 logger.log(Level.INFO, "-- Reading data from {0}", jcovResult.getResultPath()); 217 DataRoot file_image = readDataRootFile(jcovResult.getResultPath(), jcovResult.isTestListSet(), include, exclude, fms); 218 219 if (!syntheticOn) { 220 file_image.applyFilter(new ANC_FILTER()); 221 } 222 223 MemberFilter customFilter = null; 224 if (filter != null) { 225 logger.fine("-- Initializing custom filter"); 226 customFilter = initCustomFilter(filter, null); 227 logger.fine("OK"); 228 } 229 if (customFilter != null) { 230 logger.log(Level.INFO, "-- Applying filter {0}", customFilter.getClass().getName()); 231 file_image.applyFilter(customFilter); 232 logger.fine("OK"); 233 } 234 235 if (ancfilters != null){ 236 ancfiltersClasses = new AncFilter[ancfilters.length]; 237 for (int i = 0; i < ancfilters.length; i++) { 238 try { 239 String ancfilter = ancfilters[i]; 240 Class ancFilteClass = Class.forName(ancfilter); 241 ancfiltersClasses[i] = (AncFilter) ancFilteClass.newInstance(); 242 } catch (Exception e) { 243 throw new Error("Cannot create an instance of " 244 + "AncFilter: ", e); 245 } 246 } 247 } 248 249 if (ancdeffilters != null) { 250 ServiceLoader<DefaultAncFilter> loader = ServiceLoader.load(DefaultAncFilter.class); 251 List<AncFilter> defaultANCFiltersList = new ArrayList<AncFilter>(); 252 if (ancfiltersClasses != null && ancfiltersClasses.length > 0){ 253 defaultANCFiltersList.addAll(Arrays.asList(ancfiltersClasses)); 254 } 255 if (ancdeffilters.length == 1 && ancdeffilters[0].equals("all")){ 256 for (DefaultAncFilter filter : loader) { 257 defaultANCFiltersList.add(filter); 258 } 259 } 260 else { 261 for (String defaulAncFilter : ancdeffilters) { 262 boolean found = false; 263 for (DefaultAncFilter filter : loader) { 264 if (defaulAncFilter.equals(filter.getFilterName())) { 265 defaultANCFiltersList.add(filter); 266 found = true; 267 break; 268 } 269 } 270 if (!found) { 271 logger.log(Level.SEVERE, "There is no default ANC filter for \"{0}\" value", defaulAncFilter); 272 } 273 } 274 } 275 ancfiltersClasses = defaultANCFiltersList.toArray(new AncFilter[defaultANCFiltersList.size()]); 276 } 277 278 if (dataProcessorSPIs != null) { 279 for (DataProcessorSPI spi : dataProcessorSPIs) { 280 logger.log(Level.INFO, "-- Applying data processor {0}", spi.getClass()); 281 file_image = spi.getDataProcessor().process(file_image); 282 } 283 } 284 logger.fine("OK"); 285 286 SmartTestService sts = null; 287 if (jcovResult.isTestListSet()) { 288 logger.fine("-- Initializing test list"); 289 sts = new SmartTestService(jcovResult.getTestList()); 290 if (file_image.getScaleOpts().getScaleSize() != sts.getTestCount()) { 291 logger.log(Level.SEVERE, "The sizes of tests in JCov file and in test list differ.\n" 292 + "Datafile {0} contains {1} item(s).\nThe test list contains {2} item(s).", 293 new Object[]{jcovResult.getResultPath(), file_image.getScaleOpts().getScaleSize(), sts.getTestCount()}); 294 throw new Exception("The sizes of tests in JCov file and in test list differ"); 295 } 296 logger.fine("OK"); 297 } 298 ReportGenerator.Options options = new ReportGenerator.Options(srcRootPath, sts, classes, withTestsInfo, false, 299 mainReportTitle, overviewListTitle, entitiesTitle); 300 options.setInstrMode(file_image.getParams().getMode()); 301 options.setAnonymOn(anonym); 302 303 try { 304 ProductCoverage coverage = new ProductCoverage(file_image, options.getSrcRootPaths(), options.getJavapClasses(), isPublicAPI, noAbstract, anonym, ancfiltersClasses); 305 306 logger.log(Level.INFO, "- Starting ReportGenerator {0}", rg.getClass().getName()); 307 rg.generateReport(coverage, options); 308 } catch (Throwable ex) { 309 if (ex.getMessage() != null) { 310 throw new Exception("ReportGenerator produced exception " + ex.getMessage(), ex); 311 } else { 312 throw new Exception("ReportGenerator produced exception " + ex, ex); 313 } 314 } 315 316 logger.log(Level.INFO, "- Report generation done"); 317 return; 318 } 319 320 /** 321 * Get default (html) report generator 322 * 323 * @return default (html) report generator 324 */ 325 public ReportGenerator getDefaultReportGenerator() { 326 return findReportGenerator("html"); 327 } 328 329 private ReportGenerator findReportGenerator(String name) { 330 ReportGenerator rg = null; 331 if (reportGeneratorSPIs != null) { 332 for (ReportGeneratorSPI reportGeneratorSPI : reportGeneratorSPIs) { 333 rg = reportGeneratorSPI.getReportGenerator(name); 334 if (rg != null) { 335 return rg; 336 } 337 } 338 } 339 return new DefaultReportGeneratorSPI().getReportGenerator(name); // can be null 340 } 341 342 protected DataRoot readDataRootFile(String filename, boolean readScales, String[] include, String[] exclude, String[] modif) throws FileFormatException { 343 DataRoot file_image = null; 344 ClassSignatureFilter acceptor = new ClassSignatureFilter(include, exclude, m_include, m_exclude, modif); 345 file_image = Reader.readXML(filename, readScales, acceptor); 346 return file_image; 347 } 348 349 /** 350 * Legacy CMD line entry poiny (use 'java -jar jcov.jar Merger' from cmd 351 * instead of 'java -cp jcov.jar com.sun.tdk.jcov.Merger') 352 * 353 * @param args 354 */ 355 public static void main(String args[]) { 356 RepGen tool = new RepGen(); 357 try { 358 int res = tool.run(args); 359 System.exit(res); 360 } catch (Exception ex) { 361 System.exit(1); 362 } 363 } 364 365 protected String usageString() { 366 return "java com.sun.tdk.jcov.RepGen [options] filename"; 367 } 368 369 protected String exampleString() { 370 return "java -cp jcov.jar com.sun.tdk.jcov.RepGen -include java.lang.* -format html -output out result.xml"; 371 } 372 373 protected String getDescr() { 374 return "generates text or HTML (or custom) reports"; 375 } 376 377 private MemberFilter createCustomFilter(String spiName) { 378 return FilterFactory. 379 getInstance(spiName).getMemberFilter(); 380 381 } 382 383 private MemberFilter initCustomFilter(String filter, String sig) { 384 MemberFilter customPlugin = null; 385 MemberFilter sigFilter = null; 386 387 if (filter != null) { 388 customPlugin = createCustomFilter(filter); 389 } 390 if (customPlugin == null && sigFilter == null) { 391 return null; 392 } else if (customPlugin != null && sigFilter != null) { 393 ConveyerFilter f = new ConveyerFilter(); 394 f.add(sigFilter); 395 f.add(customPlugin); 396 return f; 397 } else { 398 return sigFilter != null ? sigFilter : customPlugin; 399 } 400 401 } 402 403 public void setReportGeneratorSPIs(ReportGeneratorSPI reportGeneratorSPI[]) { 404 this.reportGeneratorSPIs = reportGeneratorSPI; 405 } 406 407 public ReportGeneratorSPI[] getReportGeneratorSPIs() { 408 return reportGeneratorSPIs; 409 } 410 411 public String getFilter() { 412 return filter; 413 } 414 415 public void setFilter(String filter) { 416 this.filter = filter; 417 } 418 419 public String[] getFms() { 420 return fms; 421 } 422 423 public void setFms(String[] fms) { 424 this.fms = fms; 425 } 426 427 public String[] getInclude() { 428 return include; 429 } 430 431 public void setInclude(String[] include) { 432 this.include = include; 433 } 434 435 public boolean isIsPublicAPI() { 436 return isPublicAPI; 437 } 438 439 public void setIsPublicAPI(boolean isPublicAPI) { 440 this.isPublicAPI = isPublicAPI; 441 } 442 443 public boolean isNoAbstract() { 444 return noAbstract; 445 } 446 447 public void setNoAbstract(boolean noAbstract) { 448 this.noAbstract = noAbstract; 449 } 450 451 public boolean isSyntheticOn() { 452 return syntheticOn; 453 } 454 455 public void setNoANC(boolean syntheticOn) { 456 this.syntheticOn = syntheticOn; 457 } 458 459 public boolean isWithTestsInfo() { 460 return withTestsInfo; 461 } 462 463 public void setWithTestsInfo(boolean withTestsInfo) { 464 this.withTestsInfo = withTestsInfo; 465 } 466 467 public boolean isNoEnums() { 468 return noEnums; 469 } 470 471 public void setNoEnums(boolean noEnums) { 472 this.noEnums = noEnums; 473 } 474 475 public boolean isShowFields() { 476 return showFields; 477 } 478 479 public void setShowFields(boolean showFields) { 480 // this.showFields = showFields; 481 } 482 483 public String[] getExclude() { 484 return exclude; 485 } 486 487 public void setExclude(String[] exclude) { 488 this.exclude = exclude; 489 } 490 491 public String getSrcRootPath() { 492 return srcRootPath; 493 } 494 495 /** 496 * Reset all properties to defaults. reportGeneratorSPI = null; include = 497 * new String[] {".*"}; exclude = new String[] {""}; fms = null; filter = 498 * null; generateShortFormat = false; noAbstract = false; isPublicAPI = 499 * false; showMethods = true; showBlocks = true; showBranches = true; 500 * showLines = true; 501 */ 502 public void resetDefaults() { 503 try { 504 handleEnv_(defineHandler()); 505 reportGeneratorSPIs = null; 506 //setFilters(new String[]{".*"}, new String[]{""}, null); 507 setNoAbstract(false); 508 setIsPublicAPI(false); 509 } catch (EnvHandlingException ex) { 510 // should not happen 511 } 512 } 513 514 /** 515 * Set all properties (except custorm report service provider) 516 * 517 * @param include patterns for including data. Set null for default value - 518 * {".*"} (include all) 519 * @param exclude patterns for excluding data. Set null for default value - 520 * {""} (exclude nothing) 521 * @param classModifiers modifiers that should have a class to be included 522 * @param filter custom filter classname 523 * @param generateShortFormat should generate short format 524 * @param publicAPI should generate only public API (public and protected) 525 * @param hideAbstract should hide abstract data 526 * @param hideMethods should hide methods 527 * @param hideBlocks should hide blocks 528 * @param hideBranches should hide branches 529 * @param hideLines should hide lines 530 */ 531 public void configure(String[] include, String[] exclude, String[] classModifiers, 532 String filter, boolean generateShortFormat, boolean publicAPI, boolean hideAbstract, 533 boolean hideMethods, boolean hideBlocks, boolean hideBranches, boolean hideLines, 534 boolean hideFields) { 535 setFilters(include, exclude, classModifiers); 536 setFilter(filter); 537 this.isPublicAPI = publicAPI; 538 // this.showFields = !hideFields; 539 } 540 541 /** 542 * Set filtering properties for the report 543 * 544 * @param include patterns for including data. Set null for default value - 545 * {".*"} (include all) 546 * @param exclude patterns for excluding data. Set null for default value - 547 * {""} (exclude nothing) 548 * @param classModifiers modifiers that should have a class to be included 549 */ 550 public void setFilters(String[] include, String[] exclude, String[] classModifiers) { 551 if (include == null) { 552 include = new String[]{".*"}; 553 } 554 this.include = include; 555 if (exclude == null) { 556 exclude = new String[]{""}; 557 } 558 this.exclude = exclude; 559 this.fms = classModifiers; 560 } 561 562 @Override 563 protected int run() throws Exception { 564 Result r; 565 boolean srcZipped = false; 566 if (srcRootPath != null) { 567 File srcRootPathFile = new File(srcRootPath); 568 569 if (srcRootPathFile.exists() && srcRootPathFile.isFile() && (srcRootPath.endsWith(".zip") || srcRootPath.endsWith(".jar"))) { 570 srcZipped = true; 571 srcRootPath = outputDir + File.separator + srcRootPathFile.getName().replace(".zip", "").replace(".jar", ""); 572 Utils.unzipFolder(srcRootPathFile, srcRootPath); 573 } 574 } 575 576 try { 577 578 logger.log(Level.INFO, "-- Reading test list"); 579 if (filenames.length == 1) { 580 r = new Result(filenames[0], testlist); 581 } else { 582 Merger merger = new Merger(); 583 Result[] results = Merger.initResults(filenames, true); 584 Merger.Merge merge = new Merger.Merge(results, null); 585 merger.setAddMissing(true); 586 merger.setRead_scales(true); 587 merger.setDefaultReadingFilter(include, exclude, m_include, m_exclude, fms); 588 merger.merge(merge, outputDir, true); 589 590 ReportGenerator rg; 591 if (name != null) { 592 rg = findReportGenerator(name); 593 } else { 594 rg = getDefaultReportGenerator(); 595 } 596 if (rg == null) { 597 throw new Exception("Specified ReportGenerator name (" + name + ") was not found"); 598 } 599 rg.init(outputDir); 600 String[] tl = testlist != null ? Utils.readLines(testlist) : merge.getResultTestList(); 601 SmartTestService sts = new SmartTestService(tl); 602 ReportGenerator.Options options = new ReportGenerator.Options(srcRootPath, sts, null, true, true, 603 mainReportTitle, overviewListTitle, entitiesTitle); 604 try { 605 DataRoot mergedResult = merge.getResult(); 606 if (!syntheticOn) { 607 mergedResult.applyFilter(new ANC_FILTER()); 608 } 609 610 if (dataProcessorSPIs != null) { 611 for (DataProcessorSPI spi : dataProcessorSPIs) { 612 logger.log(Level.INFO, "-- Applying data processor {0}", spi.getClass()); 613 mergedResult = spi.getDataProcessor().process(mergedResult); 614 } 615 } 616 617 ProductCoverage coverage = new ProductCoverage(mergedResult, options.getSrcRootPaths(), null, isPublicAPI, noAbstract, ancfiltersClasses); 618 rg.generateReport(coverage, options); 619 620 if (srcZipped) { 621 Utils.deleteDirectory(new File(srcRootPath)); 622 } 623 624 } catch (Throwable ex) { 625 if (ex.getMessage() != null) { 626 throw new Exception("ReportGenerator produced exception " + ex.getMessage(), ex); 627 } else { 628 throw new Exception("ReportGenerator produced exception " + ex, ex); 629 } 630 } 631 632 return 0; 633 } 634 } catch (IOException ex) { 635 logger.log(Level.SEVERE, "Error while reading testlist", ex); 636 return 1; 637 } 638 639 if (classesPath != null) { 640 try { 641 logger.log(Level.INFO, "-- Creating javap report"); 642 new JavapRepGen(include, exclude).run(filenames[0], classesPath, outputDir); 643 return 0; 644 } catch (Exception ex) { 645 logger.log(Level.SEVERE, "Error while creating javap report", ex); 646 return 1; 647 } 648 } 649 650 try { 651 generateReport(name, outputDir, r, srcRootPath); 652 653 if (srcZipped) { 654 Utils.deleteDirectory(new File(srcRootPath)); 655 } 656 657 return 0; 658 } catch (FileFormatException e) { 659 // logger.log(Level.SEVERE, "malformed jcov file \"{0}", filename); 660 logger.log(Level.SEVERE, e.getMessage(), Arrays.toString(filenames)); 661 } catch (ProcessingException ex) { 662 } catch (Exception ex) { 663 logger.log(Level.SEVERE, ex.getMessage(), ex); 664 } 665 return SUCCESS_EXIT_CODE; 666 } 667 668 @Override 669 protected EnvHandler defineHandler() { 670 EnvHandler envHandler = new EnvHandler(new OptionDescr[]{ 671 DSC_FMT, 672 DSC_OUTPUT, 673 // DSC_STDOUT, 674 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE, 675 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE, 676 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_INCLUDE_LIST, 677 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_EXCLUDE_LIST, 678 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE_LIST, 679 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE_LIST, 680 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MINCLUDE, 681 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_MEXCLUDE, 682 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FM, 683 com.sun.tdk.jcov.instrument.InstrumentationOptions.DSC_FM_LIST, 684 DSC_NO_ABSTRACT, 685 DSC_SYNTHETIC_ON, 686 DSC_PUBLIC_API, 687 DSC_SRC_ROOT, 688 DSC_VERBOSE, 689 DSC_FILTER_PLUGIN, 690 DSC_ANC_FILTER_PLUGINS, 691 DSC_ANC_DEFAULT_FILTERS, 692 DSC_TEST_LIST, 693 DSC_ANONYM, 694 DSC_JAVAP, 695 DSC_TESTS_INFO, 696 DSC_REPORT_TITLE_MAIN, 697 DSC_REPORT_TITLE_OVERVIEW, 698 DSC_REPORT_TITLE_ENTITIES,}, this); 699 SPIDescr spiDescr = new SPIDescr(CUSTOM_REPORT_GENERATOR_SPI, ReportGeneratorSPI.class); 700 spiDescr.setDefaultSPI(new DefaultReportGeneratorSPI()); 701 envHandler.registerSPI(spiDescr); 702 703 spiDescr = new SPIDescr(DATA_PROCESSOR_SPI, DataProcessorSPI.class); 704 spiDescr.addPreset("none", new StubSpi()); 705 spiDescr.setDefaultSPI(new DefaultDataProcessorSPI()); 706 envHandler.registerSPI(spiDescr); 707 708 return envHandler; 709 } 710 711 private int handleEnv_(EnvHandler opts) throws EnvHandlingException { 712 if (opts.isSet(DSC_VERBOSE)) { 713 // LoggingFormatter.printStackTrace = true; // by default logger doesn't print stacktrace 714 logger.setLevel(Level.INFO); 715 } else { 716 logger.setLevel(Level.SEVERE); 717 } 718 719 name = opts.getValue(DSC_FMT); 720 outputDir = opts.getValue(DSC_OUTPUT); 721 // no check for output 722 723 filter = opts.getValue(DSC_FILTER_PLUGIN); 724 ancfilters = opts.getValues(DSC_ANC_FILTER_PLUGINS); 725 ancdeffilters = opts.getValues(DSC_ANC_DEFAULT_FILTERS); 726 noAbstract = opts.isSet(DSC_NO_ABSTRACT); 727 isPublicAPI = opts.isSet(DSC_PUBLIC_API); 728 anonym = opts.isSet(DSC_ANONYM); 729 syntheticOn = opts.isSet(DSC_SYNTHETIC_ON); 730 731 include = InstrumentationOptions.handleInclude(opts); 732 exclude = InstrumentationOptions.handleExclude(opts); 733 fms = InstrumentationOptions.handleFM(opts); 734 735 m_include = InstrumentationOptions.handleMInclude(opts); 736 m_exclude = InstrumentationOptions.handleMExclude(opts); 737 738 testlist = opts.getValue(DSC_TEST_LIST); 739 Utils.checkFileCanBeNull(testlist, "testlist filename", Utils.CheckOptions.FILE_EXISTS, Utils.CheckOptions.FILE_CANREAD, Utils.CheckOptions.FILE_ISFILE); 740 741 withTestsInfo = opts.isSet(DSC_TESTS_INFO); 742 743 srcRootPath = null; 744 if (opts.isSet(DSC_SRC_ROOT)) { 745 srcRootPath = opts.getValue(DSC_SRC_ROOT); 746 } 747 748 if (opts.isSet(DSC_REPORT_TITLE_MAIN)){ 749 mainReportTitle = opts.getValue(DSC_REPORT_TITLE_MAIN); 750 } 751 if (opts.isSet(DSC_REPORT_TITLE_OVERVIEW)){ 752 overviewListTitle = opts.getValue(DSC_REPORT_TITLE_OVERVIEW); 753 } 754 if (opts.isSet(DSC_REPORT_TITLE_ENTITIES)){ 755 entitiesTitle = opts.getValue(DSC_REPORT_TITLE_ENTITIES); 756 } 757 758 ArrayList<ReportGeneratorSPI> reportGenerators = opts.getSPIs(ReportGeneratorSPI.class); 759 if (reportGenerators != null) { 760 reportGeneratorSPIs = reportGenerators.toArray(new ReportGeneratorSPI[reportGenerators.size()]); 761 } 762 ArrayList<DataProcessorSPI> dataProcessors = opts.getSPIs(DataProcessorSPI.class); 763 if (dataProcessors != null) { 764 dataProcessorSPIs = dataProcessors.toArray(new DataProcessorSPI[dataProcessors.size()]); 765 } 766 767 classesPath = opts.getValue(DSC_JAVAP); 768 769 return SUCCESS_EXIT_CODE; 770 } 771 772 @Override 773 protected int handleEnv(EnvHandler opts) throws EnvHandlingException { 774 String[] srcs = opts.getTail(); 775 if (srcs == null) { 776 throw new EnvHandlingException("no input files specified"); 777 } 778 779 filenames = srcs; 780 Utils.checkFileNotNull(filenames[0], "JCov datafile", Utils.CheckOptions.FILE_EXISTS, Utils.CheckOptions.FILE_CANREAD, Utils.CheckOptions.FILE_ISFILE); 781 /*if (srcs.length > 1) { 782 logger.log(Level.WARNING,"only \"{0}\" will be processed, the rest of the files will be ignored\n" + 783 "\tto generate report for all files, merge them into one using the merger utility", filename); 784 }*/ 785 786 return handleEnv_(opts); 787 } 788 789 public static class ANC_FILTER implements MemberFilter { 790 791 @Override 792 public boolean accept(DataClass clz) { 793 return true; 794 } 795 796 @Override 797 public boolean accept(DataClass clz, DataMethod m) { 798 799 boolean ancMethod; 800 801 //Synthetic method (and Bridge method) 802 ancMethod = ((m.getAccess() & Opcodes.ACC_SYNTHETIC) != 0); 803 804 //Enum method 805 ancMethod = ancMethod 806 || (clz.getSuperName().equals("java/lang/Enum") && (m.getName().equals("valueOf") || m.getName().equals("values"))); 807 808 return !ancMethod || m.getName().startsWith("lambda$"); 809 810 } 811 812 @Override 813 public boolean accept(DataClass clz, DataField f) { 814 return true; 815 } 816 } 817 final static OptionDescr DSC_FMT = 818 new OptionDescr("format", new String[]{"fmt"}, 819 "Report generation output.", VAL_SINGLE, 820 "Specifies the format of the report.\n" 821 + "Use \"text\" for generate text report and \"html\" for generate HTML report\n" 822 + "Text report in one file which contains method/block/branch coverage information.\n" 823 + "HTML report contains coverage information with marked-up sources.\n\n" 824 + "Custom reports can be specified with ReportGeneratorSPI interface.", "html"); 825 /** 826 * 827 */ 828 public final static OptionDescr DSC_OUTPUT = 829 new OptionDescr("repgen.output", new String[]{"output", "o"}, "", OptionDescr.VAL_SINGLE, 830 "Output directory for generating text and HTML reports.", "report"); 831 /** 832 * 833 */ 834 public final static OptionDescr DSC_TEST_LIST = 835 new OptionDescr("tests", "Test list", OptionDescr.VAL_SINGLE, 836 "Specify the path to the file containing test list. File should contain a list of tests\n" 837 + "with one name per line."); 838 final static OptionDescr DSC_FILTER_PLUGIN = 839 new OptionDescr("filter", "", OptionDescr.VAL_SINGLE, 840 "Custom filtering plugin class"); 841 842 final static OptionDescr DSC_ANC_FILTER_PLUGINS = 843 new OptionDescr("ancfilter", new String[]{"ancf"}, "Custom anc filtering plugin classes", OptionDescr.VAL_MULTI, 844 ""); 845 846 final static OptionDescr DSC_ANC_DEFAULT_FILTERS = 847 new OptionDescr("ancdeffilters", new String[]{"ancdf"}, "Default ANC filters names to use in report", OptionDescr.VAL_MULTI, 848 ""); 849 850 /** 851 * 852 */ 853 public final static OptionDescr DSC_SRC_ROOT = 854 new OptionDescr("sourcepath", new String[]{"source", "src"}, "The source files.", OptionDescr.VAL_SINGLE, ""); 855 final static OptionDescr DSC_VERBOSE = 856 new OptionDescr("verbose", "Verbosity.", "Enable verbose mode."); 857 /** 858 * 859 */ 860 public final static OptionDescr DSC_NO_ABSTRACT = 861 new OptionDescr("noabstract", "Additional filtering", "Do not count abstract methods"); 862 public final static OptionDescr DSC_SYNTHETIC_ON = 863 new OptionDescr("syntheticon", "Additional filtering", "Count coverage for synthetic methods"); 864 /** 865 * 866 */ 867 public final static OptionDescr DSC_PUBLIC_API = 868 new OptionDescr("publicapi", "", "Count only public and protected members"); 869 public final static OptionDescr DSC_ANONYM = 870 new OptionDescr("anonym", "", "include methods from anonymous classes into the report"); 871 public final static OptionDescr DSC_JAVAP = 872 new OptionDescr("javap", new String[]{"javap"}, "Path to the class files of the product to use javap", OptionDescr.VAL_SINGLE, ""); 873 public final static OptionDescr DSC_TESTS_INFO = 874 new OptionDescr("testsinfo", "Additional information about for specified tests' list", "Show covererage for all tests in test list"); 875 876 public final static OptionDescr DSC_REPORT_TITLE_MAIN = 877 new OptionDescr("mainReportTitle", new String[]{"mainReportTitle", "mrtitle"}, "The main report title", OptionDescr.VAL_SINGLE, ""); 878 public final static OptionDescr DSC_REPORT_TITLE_OVERVIEW = 879 new OptionDescr("overviewReportTitle", new String[]{"overviewReportTitle", "ortitle"}, "The overview list report title", OptionDescr.VAL_SINGLE, ""); 880 public final static OptionDescr DSC_REPORT_TITLE_ENTITIES = 881 new OptionDescr("entitiesReportTitle", new String[]{"entitiesReportTitle", "ertitle"}, "Entities report title (for modules, packages, subpackages)", OptionDescr.VAL_SINGLE, ""); 882 }