1 package jdiff; 2 3 import java.io.*; 4 import java.util.*; 5 import com.sun.javadoc.*; 6 import javax.tools.Diagnostic; 7 import jdk.javadoc.doclet.Doclet.Option; 8 9 /** 10 * Class to handle options for JDiff. 11 * 12 * See the file LICENSE.txt for copyright details. 13 * @author Matthew Doar, mdoar@pobox.com 14 */ 15 public class Options { 16 17 public static String authorid = ""; 18 public static String versionid = ""; 19 public static boolean classlist = false; 20 public static String title = ""; 21 public static boolean docletid = false; 22 public static String evident = ""; 23 public static List<String> skippkg = new ArrayList(); 24 public static List<String> skipclass = new ArrayList(); 25 public static int execdepth = 0; 26 27 /** 28 * The name of the file where the XML representing the old API is 29 * stored. 30 */ 31 static String oldFileName = "old_java.xml"; 32 33 /** 34 * The name of the directory where the XML representing the old API is 35 * stored. 36 */ 37 static String oldDirectory = null; 38 39 /** 40 * The name of the file where the XML representing the new API is 41 * stored. 42 */ 43 static String newFileName = "new_java.xml"; 44 45 /** 46 * The name of the directory where the XML representing the new API is 47 * stored. 48 */ 49 static String newDirectory = null; 50 51 /** If set, then generate the XML for an API and exit. */ 52 static boolean writeXML = false; 53 54 /** If set, then read in two XML files and compare their APIs. */ 55 static boolean compareAPIs = false; 56 getSupportedOptions()57 public static Set<? extends Option> getSupportedOptions() { 58 Set<Option> options = new HashSet<>(); 59 60 // Standard options 61 62 options.add( 63 new Option() { 64 private final List<String> names = List.of("-authorid"); 65 @Override public int getArgumentCount() { return 1; } 66 @Override public String getDescription() { return ""; } 67 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 68 @Override public List<String> getNames() { return names; } 69 @Override public String getParameters() { return "<author>"; } 70 @Override public boolean process(String opt, List<String> arguments) { 71 Options.authorid = arguments.get(0); 72 return true; 73 } 74 } 75 ); 76 77 options.add( 78 new Option() { 79 private final List<String> names = List.of("-versionid"); 80 @Override public int getArgumentCount() { return 1; } 81 @Override public String getDescription() { return ""; } 82 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 83 @Override public List<String> getNames() { return names; } 84 @Override public String getParameters() { return "<version>"; } 85 @Override public boolean process(String opt, List<String> arguments) { 86 Options.versionid = arguments.get(0); 87 return true; 88 } 89 } 90 ); 91 92 options.add( 93 new Option() { 94 private final List<String> names = List.of("-d"); 95 @Override public int getArgumentCount() { return 1; } 96 @Override public String getDescription() { 97 return "Destination directory for output HTML files"; 98 } 99 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 100 @Override public List<String> getNames() { return names; } 101 @Override public String getParameters() { return "<directory>"; } 102 @Override public boolean process(String opt, List<String> arguments) { 103 HTMLReportGenerator.outputDir = arguments.get(0); 104 return true; 105 } 106 } 107 ); 108 109 options.add( 110 new Option() { 111 private final List<String> names = List.of("-classlist"); 112 @Override public int getArgumentCount() { return 0; } 113 @Override public String getDescription() { return ""; } 114 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 115 @Override public List<String> getNames() { return names; } 116 @Override public String getParameters() { return ""; } 117 @Override public boolean process(String opt, List<String> arguments) { 118 Options.classlist = true; 119 return true; 120 } 121 } 122 ); 123 124 options.add( 125 new Option() { 126 private final List<String> names = List.of("-title"); 127 @Override public int getArgumentCount() { return 1; } 128 @Override public String getDescription() { return ""; } 129 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 130 @Override public List<String> getNames() { return names; } 131 @Override public String getParameters() { return "<title>"; } 132 @Override public boolean process(String opt, List<String> arguments) { 133 Options.title = arguments.get(0); 134 return true; 135 } 136 } 137 ); 138 139 options.add( 140 new Option() { 141 private final List<String> names = List.of("-docletid"); 142 @Override public int getArgumentCount() { return 0; } 143 @Override public String getDescription() { return ""; } 144 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 145 @Override public List<String> getNames() { return names; } 146 @Override public String getParameters() { return ""; } 147 @Override public boolean process(String opt, List<String> arguments) { 148 Options.docletid = true; 149 return true; 150 } 151 } 152 ); 153 154 options.add( 155 new Option() { 156 private final List<String> names = List.of("-evident"); 157 @Override public int getArgumentCount() { return 1; } 158 @Override public String getDescription() { return ""; } 159 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 160 @Override public List<String> getNames() { return names; } 161 @Override public String getParameters() { return "<evident>"; } 162 @Override public boolean process(String opt, List<String> arguments) { 163 Options.evident = arguments.get(0); 164 return true; 165 } 166 } 167 ); 168 169 options.add( 170 new Option() { 171 private final List<String> names = List.of("-skippkg"); 172 @Override public int getArgumentCount() { return 1; } 173 @Override public String getDescription() { return ""; } 174 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 175 @Override public List<String> getNames() { return names; } 176 @Override public String getParameters() { return "<package>"; } 177 @Override public boolean process(String opt, List<String> arguments) { 178 Options.skippkg.add(arguments.get(0)); 179 return true; 180 } 181 } 182 ); 183 184 options.add( 185 new Option() { 186 private final List<String> names = List.of("-skipclass"); 187 @Override public int getArgumentCount() { return 1; } 188 @Override public String getDescription() { return ""; } 189 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 190 @Override public List<String> getNames() { return names; } 191 @Override public String getParameters() { return "<class>"; } 192 @Override public boolean process(String opt, List<String> arguments) { 193 Options.skipclass.add(arguments.get(0)); 194 return true; 195 } 196 } 197 ); 198 199 options.add( 200 new Option() { 201 private final List<String> names = List.of("-execdepth"); 202 @Override public int getArgumentCount() { return 1; } 203 @Override public String getDescription() { return ""; } 204 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 205 @Override public List<String> getNames() { return names; } 206 @Override public String getParameters() { return "<depth>"; } 207 @Override public boolean process(String opt, List<String> arguments) { 208 Options.execdepth = Integer.parseInt(arguments.get(0)); 209 return true; 210 } 211 } 212 ); 213 214 options.add( 215 new Option() { 216 private final List<String> names = List.of("-version"); 217 @Override public int getArgumentCount() { return 0; } 218 @Override public String getDescription() { return ""; } 219 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 220 @Override public List<String> getNames() { return names; } 221 @Override public String getParameters() { return ""; } 222 @Override public boolean process(String opt, List<String> arguments) { 223 System.out.println("JDiff version: " + JDiff.version); 224 System.exit(0); 225 return true; 226 } 227 } 228 ); 229 230 // Options to control JDiff 231 232 options.add( 233 new Option() { 234 private final List<String> names = List.of("-apiname"); 235 @Override public int getArgumentCount() { return 1; } 236 @Override public String getDescription() { return ""; } 237 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 238 @Override public List<String> getNames() { return names; } 239 @Override public String getParameters() { return "<Name of a version>"; } 240 @Override public boolean process(String opt, List<String> arguments) { 241 Options.skipclass.add(arguments.get(0)); 242 String filename = arguments.get(0); 243 RootDocToXML.apiIdentifier = filename; 244 filename = filename.replace(' ', '_'); 245 RootDocToXML.outputFileName = filename + ".xml"; 246 Options.writeXML = true; 247 Options.compareAPIs = false; 248 return true; 249 } 250 } 251 ); 252 253 options.add( 254 new Option() { 255 private final List<String> names = List.of("-oldapi"); 256 @Override public int getArgumentCount() { return 1; } 257 @Override public String getDescription() { return ""; } 258 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 259 @Override public List<String> getNames() { return names; } 260 @Override public String getParameters() { return "<Name of a version>"; } 261 @Override public boolean process(String opt, List<String> arguments) { 262 String filename = arguments.get(0); 263 filename = filename.replace(' ', '_'); 264 Options.oldFileName = filename + ".xml"; 265 Options.writeXML = false; 266 Options.compareAPIs = true; 267 return true; 268 } 269 } 270 ); 271 272 options.add( 273 new Option() { 274 private final List<String> names = List.of("-newapi"); 275 @Override public int getArgumentCount() { return 1; } 276 @Override public String getDescription() { return ""; } 277 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 278 @Override public List<String> getNames() { return names; } 279 @Override public String getParameters() { return "<Name of a version>"; } 280 @Override public boolean process(String opt, List<String> arguments) { 281 String filename = arguments.get(0); 282 filename = filename.replace(' ', '_'); 283 Options.newFileName = filename + ".xml"; 284 Options.writeXML = false; 285 Options.compareAPIs = true; 286 return true; 287 } 288 } 289 ); 290 291 // Options to control the location of the XML files 292 293 options.add( 294 new Option() { 295 private final List<String> names = List.of("-apidir"); 296 @Override public int getArgumentCount() { return 1; } 297 @Override public String getDescription() { return ""; } 298 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 299 @Override public List<String> getNames() { return names; } 300 @Override public String getParameters() { return "<directory>"; } 301 @Override public boolean process(String opt, List<String> arguments) { 302 RootDocToXML.outputDirectory = arguments.get(0); 303 return true; 304 } 305 } 306 ); 307 308 options.add( 309 new Option() { 310 private final List<String> names = List.of("-oldapidir"); 311 @Override public int getArgumentCount() { return 1; } 312 @Override public String getDescription() { 313 return "Location of the XML file for the old API"; 314 } 315 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 316 @Override public List<String> getNames() { return names; } 317 @Override public String getParameters() { return "<directory>"; } 318 @Override public boolean process(String opt, List<String> arguments) { 319 Options.oldDirectory = arguments.get(0); 320 return true; 321 } 322 } 323 ); 324 325 options.add( 326 new Option() { 327 private final List<String> names = List.of("-newapidir"); 328 @Override public int getArgumentCount() { return 1; } 329 @Override public String getDescription() { 330 return "Location of the XML file for the new API"; 331 } 332 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 333 @Override public List<String> getNames() { return names; } 334 @Override public String getParameters() { return "<directory>"; } 335 @Override public boolean process(String opt, List<String> arguments) { 336 Options.newDirectory = arguments.get(0); 337 return true; 338 } 339 } 340 ); 341 342 options.add( 343 new Option() { 344 private final List<String> names = List.of("-usercommentsdir"); 345 @Override public int getArgumentCount() { return 1; } 346 @Override public String getDescription() { 347 return "Path to dir containing the user_comments* file(s)"; 348 } 349 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 350 @Override public List<String> getNames() { return names; } 351 @Override public String getParameters() { return "<directory>"; } 352 @Override public boolean process(String opt, List<String> arguments) { 353 HTMLReportGenerator.commentsDir = arguments.get(0); 354 return true; 355 } 356 } 357 ); 358 359 // Options for the exclusion level for classes and members 360 361 options.add( 362 new Option() { 363 private final List<String> names = List.of("-excludeclass"); 364 @Override public int getArgumentCount() { return 1; } 365 @Override public String getDescription() { 366 return "Exclude classes which are not public, protected etc"; 367 } 368 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 369 @Override public List<String> getNames() { return names; } 370 @Override public String getParameters() { 371 return "[public|protected|package|private]"; 372 } 373 @Override public boolean process(String opt, List<String> arguments) { 374 String level = arguments.get(0); 375 if (level.compareTo("public") != 0 && 376 level.compareTo("protected") != 0 && 377 level.compareTo("package") != 0 && 378 level.compareTo("private") != 0) { 379 JDiff.reporter.print(Diagnostic.Kind.ERROR, 380 "Level specified after -excludeclass option must be one of (public|protected|package|private)."); 381 return false; 382 } 383 RootDocToXML.classVisibilityLevel = level; 384 return true; 385 } 386 } 387 ); 388 389 options.add( 390 new Option() { 391 private final List<String> names = List.of("-excludemember"); 392 @Override public int getArgumentCount() { return 1; } 393 @Override public String getDescription() { 394 return "Exclude members which are not public, protected etc"; 395 } 396 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 397 @Override public List<String> getNames() { return names; } 398 @Override public String getParameters() { 399 return "[public|protected|package|private]"; 400 } 401 @Override public boolean process(String opt, List<String> arguments) { 402 String level = arguments.get(0); 403 if (level.compareTo("public") != 0 && 404 level.compareTo("protected") != 0 && 405 level.compareTo("package") != 0 && 406 level.compareTo("private") != 0) { 407 JDiff.reporter.print(Diagnostic.Kind.ERROR, 408 "Level specified after -excludemember option must be one of (public|protected|package|private)."); 409 return false; 410 } 411 RootDocToXML.memberVisibilityLevel = level; 412 return true; 413 } 414 } 415 ); 416 417 options.add( 418 new Option() { 419 private final List<String> names = List.of("-firstsentence"); 420 @Override public int getArgumentCount() { return 0; } 421 @Override public String getDescription() { 422 return "Save only the first sentence of each comment block with the API."; 423 } 424 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 425 @Override public List<String> getNames() { return names; } 426 @Override public String getParameters() { return ""; } 427 @Override public boolean process(String opt, List<String> arguments) { 428 RootDocToXML.saveAllDocs = false; 429 return true; 430 } 431 } 432 ); 433 434 options.add( 435 new Option() { 436 private final List<String> names = List.of("-docchanges"); 437 @Override public int getArgumentCount() { return 0; } 438 @Override public String getDescription() { 439 return "Report changes in Javadoc comments between the APIs"; 440 } 441 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 442 @Override public List<String> getNames() { return names; } 443 @Override public String getParameters() { return ""; } 444 @Override public boolean process(String opt, List<String> arguments) { 445 HTMLReportGenerator.reportDocChanges = true; 446 Diff.noDocDiffs = false; 447 return true; 448 } 449 } 450 ); 451 452 options.add( 453 new Option() { 454 private final List<String> names = List.of("-packagesonly"); 455 @Override public int getArgumentCount() { return 0; } 456 @Override public String getDescription() { return ""; } 457 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 458 @Override public List<String> getNames() { return names; } 459 @Override public String getParameters() { return ""; } 460 @Override public boolean process(String opt, List<String> arguments) { 461 RootDocToXML.packagesOnly = true; 462 return true; 463 } 464 } 465 ); 466 467 options.add( 468 new Option() { 469 private final List<String> names = List.of("-showallchanges"); 470 @Override public int getArgumentCount() { return 0; } 471 @Override public String getDescription() { return ""; } 472 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 473 @Override public List<String> getNames() { return names; } 474 @Override public String getParameters() { return ""; } 475 @Override public boolean process(String opt, List<String> arguments) { 476 Diff.showAllChanges = true; 477 return true; 478 } 479 } 480 ); 481 482 // Option to change the location for the existing Javadoc 483 // documentation for the new API. Default is "../" 484 485 options.add( 486 new Option() { 487 private final List<String> names = List.of("-javadocnew"); 488 @Override public int getArgumentCount() { return 1; } 489 @Override public String getDescription() { return ""; } 490 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 491 @Override public List<String> getNames() { return names; } 492 @Override public String getParameters() { 493 return "<location of existing Javadoc files for the new API>"; 494 } 495 @Override public boolean process(String opt, List<String> arguments) { 496 HTMLReportGenerator.newDocPrefix = arguments.get(0); 497 return true; 498 } 499 } 500 ); 501 502 // Option to change the location for the existing Javadoc 503 // documentation for the old API. Default is null. 504 505 options.add( 506 new Option() { 507 private final List<String> names = List.of("-javadocold"); 508 @Override public int getArgumentCount() { return 1; } 509 @Override public String getDescription() { return ""; } 510 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 511 @Override public List<String> getNames() { return names; } 512 @Override public String getParameters() { 513 return "<location of existing Javadoc files for the old API>"; 514 } 515 @Override public boolean process(String opt, List<String> arguments) { 516 HTMLReportGenerator.oldDocPrefix = arguments.get(0); 517 return true; 518 } 519 } 520 ); 521 522 options.add( 523 new Option() { 524 private final List<String> names = List.of("-baseuri"); 525 @Override public int getArgumentCount() { return 1; } 526 @Override public String getDescription() { 527 return "Use \"base\" as the base location of the various DTDs and Schemas used by JDiff"; 528 } 529 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 530 @Override public List<String> getNames() { return names; } 531 @Override public String getParameters() { return "<base>"; } 532 @Override public boolean process(String opt, List<String> arguments) { 533 RootDocToXML.baseURI = arguments.get(0); 534 return true; 535 } 536 } 537 ); 538 539 // Option not to suggest comments at all 540 541 options.add( 542 new Option() { 543 private final List<String> names = List.of("-nosuggest"); 544 @Override public int getArgumentCount() { return 1; } 545 @Override public String getDescription() { 546 return "Do not add suggested comments to all, or the removed, added or changed sections"; 547 } 548 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 549 @Override public List<String> getNames() { return names; } 550 @Override public String getParameters() { 551 return "[all|remove|add|change]"; 552 } 553 @Override public boolean process(String opt, List<String> arguments) { 554 String level = arguments.get(0); 555 if (level.compareTo("all") != 0 && 556 level.compareTo("remove") != 0 && 557 level.compareTo("add") != 0 && 558 level.compareTo("change") != 0) { 559 JDiff.reporter.print(Diagnostic.Kind.ERROR, 560 "Level specified after -nosuggest option must be one of (all|remove|add|change)."); 561 return false; 562 } 563 if (level.compareTo("removal") == 0) 564 HTMLReportGenerator.noCommentsOnRemovals = true; 565 else if (level.compareTo("add") == 0) 566 HTMLReportGenerator.noCommentsOnAdditions = true; 567 else if (level.compareTo("change") == 0) 568 HTMLReportGenerator.noCommentsOnChanges = true; 569 else if (level.compareTo("all") == 0) { 570 HTMLReportGenerator.noCommentsOnRemovals = true; 571 HTMLReportGenerator.noCommentsOnAdditions = true; 572 HTMLReportGenerator.noCommentsOnChanges = true; 573 } 574 return true; 575 } 576 } 577 ); 578 579 // Option to enable checking that the comments end with a period. 580 581 options.add( 582 new Option() { 583 private final List<String> names = List.of("-checkcomments"); 584 @Override public int getArgumentCount() { return 0; } 585 @Override public String getDescription() { 586 return "Check that comments are sentences"; 587 } 588 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 589 @Override public List<String> getNames() { return names; } 590 @Override public String getParameters() { return ""; } 591 @Override public boolean process(String opt, List<String> arguments) { 592 APIHandler.checkIsSentence = true; 593 return true; 594 } 595 } 596 ); 597 598 // Option to retain non-printing characters in comments. 599 600 options.add( 601 new Option() { 602 private final List<String> names = List.of("-retainnonprinting"); 603 @Override public int getArgumentCount() { return 0; } 604 @Override public String getDescription() { 605 return "Keep non-printable characters from comments."; 606 } 607 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 608 @Override public List<String> getNames() { return names; } 609 @Override public String getParameters() { return ""; } 610 @Override public boolean process(String opt, List<String> arguments) { 611 RootDocToXML.stripNonPrintables = false; 612 return true; 613 } 614 } 615 ); 616 617 // Option for the name of the exclude tag 618 619 options.add( 620 new Option() { 621 private final List<String> names = List.of("-excludetag"); 622 @Override public int getArgumentCount() { return 1; } 623 @Override public String getDescription() { 624 return "Define the Javadoc tag which implies exclusion"; 625 } 626 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 627 @Override public List<String> getNames() { return names; } 628 @Override public String getParameters() { return "<tag>"; } 629 @Override public boolean process(String opt, List<String> arguments) { 630 RootDocToXML.excludeTag = arguments.get(0); 631 RootDocToXML.excludeTag = RootDocToXML.excludeTag.trim(); 632 RootDocToXML.doExclude = true; 633 return true; 634 } 635 } 636 ); 637 638 // Generate statistical output 639 640 options.add( 641 new Option() { 642 private final List<String> names = List.of("-stats"); 643 @Override public int getArgumentCount() { return 0; } 644 @Override public String getDescription() { 645 return "Generate statistical output"; 646 } 647 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 648 @Override public List<String> getNames() { return names; } 649 @Override public String getParameters() { return ""; } 650 @Override public boolean process(String opt, List<String> arguments) { 651 HTMLReportGenerator.doStats = true; 652 return true; 653 } 654 } 655 ); 656 657 // Set the browser window title 658 659 options.add( 660 new Option() { 661 private final List<String> names = List.of("-windowtitle"); 662 @Override public int getArgumentCount() { return 1; } 663 @Override public String getDescription() { return ""; } 664 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 665 @Override public List<String> getNames() { return names; } 666 @Override public String getParameters() { return "<title>"; } 667 @Override public boolean process(String opt, List<String> arguments) { 668 HTMLReportGenerator.windowTitle = arguments.get(0); 669 return true; 670 } 671 } 672 ); 673 674 // Set the report title 675 676 options.add( 677 new Option() { 678 private final List<String> names = List.of("-doctitle"); 679 @Override public int getArgumentCount() { return 1; } 680 @Override public String getDescription() { return ""; } 681 @Override public Option.Kind getKind() { return Option.Kind.STANDARD; } 682 @Override public List<String> getNames() { return names; } 683 @Override public String getParameters() { return "<title>"; } 684 @Override public boolean process(String opt, List<String> arguments) { 685 HTMLReportGenerator.docTitle = arguments.get(0); 686 return true; 687 } 688 } 689 ); 690 691 return options; 692 } 693 } 694