001/* 002 * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package org.jdrupes.mdoclet.internal.doclets.formats.html; 027 028import java.net.MalformedURLException; 029import java.net.URL; 030import java.util.ArrayList; 031import java.util.List; 032import java.util.Set; 033import java.util.TreeSet; 034 035import org.jdrupes.mdoclet.internal.doclets.toolkit.BaseOptions; 036import org.jdrupes.mdoclet.internal.doclets.toolkit.Messages; 037import org.jdrupes.mdoclet.internal.doclets.toolkit.Resources; 038import org.jdrupes.mdoclet.internal.doclets.toolkit.util.DocFile; 039import org.jdrupes.mdoclet.internal.doclets.toolkit.util.Utils; 040import org.jdrupes.mdoclet.internal.doclint.DocLint; 041 042/** 043 * Storage for all options supported by the 044 * {@link jdk.javadoc.doclet.StandardDoclet standard doclet}, 045 * including the format-independent options handled 046 * by {@link BaseOptions}. 047 * 048 * <p>Some of the methods used to access the values of options 049 * have names that begin with a verb, such as {@link #createOverview} 050 * or {@link #splitIndex}. Unless otherwise stated, 051 * these methods should all be taken as just accessing the value 052 * of the associated option. 053 * 054 */ 055public class HtmlOptions extends BaseOptions { 056 // <editor-fold desc="Option values"> 057 /** 058 * Argument for command-line option {@code --add-stylesheet}. 059 */ 060 private List<String> additionalStylesheets = new ArrayList<>(); 061 062 /** 063 * Argument for command-line option {@code --add-script}. 064 */ 065 private List<String> additionalScripts = new ArrayList<>(); 066 067 /** 068 * Argument for command-line option {@code -bottom}. 069 */ 070 private String bottom = ""; 071 072 /** 073 * Argument for command-line option {@code -charset}. 074 * The META charset tag used for cross-platform viewing. 075 */ 076 private String charset = null; 077 078 /** 079 * Argument for command-line option {@code -use}. 080 * True if command-line option "-use" is used. Default value is false. 081 */ 082 private boolean classUse = false; 083 084 /** 085 * Argument for command-line option {@code -noindex}. 086 * False if command-line option "-noindex" is used. Default value is true. 087 */ 088 private boolean createIndex = true; 089 090 /** 091 * Argument for command-line option {@code -overview}. 092 * This is true if option "-overview" is used or option "-overview" is not 093 * used and number of packages is more than one. 094 */ 095 private boolean createOverview = false; 096 097 /** 098 * Argument for command-line option {@code -notree}. 099 * False if command-line option "-notree" is used. Default value is true. 100 */ 101 private boolean createTree = true; 102 103 /** 104 * Arguments for command-line option {@code -Xdoclint} and friends. 105 * Collected set of doclint options. 106 */ 107 private List<String> doclintOpts = new ArrayList<>(); 108 109 /** 110 * Argument for command-line option {@code -Xdocrootparent}. 111 */ 112 private String docrootParent = ""; 113 114 /** 115 * Argument for command-line option {@code -doctitle}. 116 */ 117 private String docTitle = ""; 118 119 /** 120 * Argument for command-line option {@code -header}. 121 */ 122 private String header = ""; 123 124 /** 125 * Argument for command-line option {@code -helpfile}. 126 */ 127 private String helpFile = ""; 128 129 /** 130 * Argument for command-line option {@code --legal-notices}. 131 */ 132 private String legalNotices = ""; 133 134 /** 135 * Argument for command-line option {@code -nodeprecatedlist}. 136 * True if command-line option "-nodeprecatedlist" is used. Default value is 137 * false. 138 */ 139 private boolean noDeprecatedList = false; 140 141 /** 142 * Argument for command-line option {@code --no-external-spec-page}. 143 * True if command-line option "--no-external-spec-page" is used. Default value is 144 * false. 145 */ 146 private boolean noExternalSpecsPage = false; 147 148 /** 149 * Argument for command-line option {@code -nohelp}. 150 * True if command-line option "-nohelp" is used. Default value is false. 151 */ 152 private boolean noHelp = false; 153 154 /** 155 * Argument for command-line option {@code -nonavbar}. 156 * True if command-line option "-nonavbar" is used. Default value is false. 157 */ 158 private boolean noNavbar = false; 159 160 /** 161 * Argument for command-line option {@code -nooverview}. 162 * True if command-line option "-nooverview" is used. Default value is 163 * false 164 */ 165 private boolean noOverview = false; 166 167 /** 168 * Argument for command-line option {@code -overview}. 169 * The overview path specified with "-overview" flag. 170 */ 171 private String overviewPath = null; 172 173 /** 174 * Argument for command-line option {@code -packagesheader}. 175 */ 176 private String packagesHeader = ""; 177 178 /** 179 * Argument for command-line option {@code -splitindex}. 180 * True if command-line option "-splitindex" is used. Default value is 181 * false. 182 */ 183 private boolean splitIndex = false; 184 185 /** 186 * Argument for command-line option {@code -stylesheetfile}. 187 */ 188 private String stylesheetFile = ""; 189 190 /** 191 * Argument for command-line option {@code -top}. 192 */ 193 private String top = ""; 194 195 /** 196 * Argument for command-line option {@code -windowtitle}. 197 */ 198 private String windowTitle = ""; 199 // </editor-fold> 200 201 private HtmlConfiguration config; 202 203 HtmlOptions(HtmlConfiguration config) { 204 super(config); 205 this.config = config; 206 } 207 208 @Override 209 public Set<? extends Option> getSupportedOptions() { 210 Messages messages = config.getMessages(); 211 Resources resources = messages.getResources(); 212 213 List<Option> options = List.of( 214 new Option(resources, "--add-script", 1) { 215 @Override 216 public boolean process(String opt, List<String> args) { 217 additionalScripts.add(args.get(0)); 218 return true; 219 } 220 }, 221 222 new Option(resources, "--add-stylesheet", 1) { 223 @Override 224 public boolean process(String opt, List<String> args) { 225 additionalStylesheets.add(args.get(0)); 226 return true; 227 } 228 }, 229 230 new Option(resources, "-bottom", 1) { 231 @Override 232 public boolean process(String opt, List<String> args) { 233 bottom = args.get(0); 234 return true; 235 } 236 }, 237 238 new Option(resources, "-charset", 1) { 239 @Override 240 public boolean process(String opt, List<String> args) { 241 charset = args.get(0); 242 return true; 243 } 244 }, 245 246 new Option(resources, "-doctitle", 1) { 247 @Override 248 public boolean process(String opt, List<String> args) { 249 docTitle = args.get(0); 250 return true; 251 } 252 }, 253 254 new Option(resources, "-footer", 1) { 255 @Override 256 public boolean process(String opt, List<String> args) { 257 messages.warning("doclet.footer_specified"); 258 return true; 259 } 260 }, 261 262 new Option(resources, "-header", 1) { 263 @Override 264 public boolean process(String opt, List<String> args) { 265 header = args.get(0); 266 return true; 267 } 268 }, 269 270 new Option(resources, "-helpfile", 1) { 271 @Override 272 public boolean process(String opt, List<String> args) { 273 if (noHelp) { 274 messages.error("doclet.Option_conflict", "-helpfile", 275 "-nohelp"); 276 return false; 277 } 278 if (!helpFile.isEmpty()) { 279 messages.error("doclet.Option_reuse", "-helpfile"); 280 return false; 281 } 282 helpFile = args.get(0); 283 return true; 284 } 285 }, 286 287 new Option(resources, "-html5") { 288 @Override 289 public boolean process(String opt, List<String> args) { 290 return true; 291 } 292 }, 293 294 new XOption(resources, "--legal-notices", 1) { 295 @Override 296 public boolean process(String opt, List<String> args) { 297 legalNotices = args.get(0); 298 return true; 299 } 300 }, 301 302 new Option(resources, "-nohelp") { 303 @Override 304 public boolean process(String opt, List<String> args) { 305 noHelp = true; 306 if (!helpFile.isEmpty()) { 307 messages.error("doclet.Option_conflict", "-nohelp", 308 "-helpfile"); 309 return false; 310 } 311 return true; 312 } 313 }, 314 315 new Option(resources, "-nodeprecatedlist") { 316 @Override 317 public boolean process(String opt, List<String> args) { 318 noDeprecatedList = true; 319 return true; 320 } 321 }, 322 323 new Option(resources, "-noindex") { 324 @Override 325 public boolean process(String opt, List<String> args) { 326 createIndex = false; 327 if (splitIndex) { 328 messages.error("doclet.Option_conflict", "-noindex", 329 "-splitindex"); 330 return false; 331 } 332 return true; 333 } 334 }, 335 336 new Option(resources, "-nonavbar") { 337 @Override 338 public boolean process(String opt, List<String> args) { 339 noNavbar = true; 340 return true; 341 } 342 }, 343 344 new Hidden(resources, "-nooverview") { 345 @Override 346 public boolean process(String opt, List<String> args) { 347 noOverview = true; 348 if (overviewPath != null) { 349 messages.error("doclet.Option_conflict", "-nooverview", 350 "-overview"); 351 return false; 352 } 353 return true; 354 } 355 }, 356 357 new Hidden(resources, "--no-external-specs-page") { 358 @Override 359 public boolean process(String opt, List<String> args) { 360 noExternalSpecsPage = true; 361 return true; 362 } 363 }, 364 365 new Option(resources, "-notree") { 366 @Override 367 public boolean process(String opt, List<String> args) { 368 createTree = false; 369 return true; 370 } 371 }, 372 373 new Option(resources, "-overview", 1) { 374 @Override 375 public boolean process(String opt, List<String> args) { 376 overviewPath = args.get(0); 377 if (noOverview) { 378 messages.error("doclet.Option_conflict", "-overview", 379 "-nooverview"); 380 return false; 381 } 382 return true; 383 } 384 }, 385 386 new Hidden(resources, "-packagesheader", 1) { 387 @Override 388 public boolean process(String opt, List<String> args) { 389 packagesHeader = args.get(0); 390 return true; 391 } 392 }, 393 394 new Option(resources, "-splitindex") { 395 @Override 396 public boolean process(String opt, List<String> args) { 397 splitIndex = true; 398 if (!createIndex) { 399 messages.error("doclet.Option_conflict", "-splitindex", 400 "-noindex"); 401 return false; 402 } 403 return true; 404 } 405 }, 406 407 new Option(resources, "--main-stylesheet -stylesheetfile", 1) { 408 @Override 409 public boolean process(String opt, List<String> args) { 410 stylesheetFile = args.get(0); 411 return true; 412 } 413 }, 414 415 new Option(resources, "-top", 1) { 416 @Override 417 public boolean process(String opt, List<String> args) { 418 top = args.get(0); 419 return true; 420 } 421 }, 422 423 new Option(resources, "-use") { 424 @Override 425 public boolean process(String opt, List<String> args) { 426 classUse = true; 427 return true; 428 } 429 }, 430 431 new Option(resources, "-windowtitle", 1) { 432 @Override 433 public boolean process(String opt, List<String> args) { 434 windowTitle = args.get(0).replaceAll("<.*?>", ""); 435 return true; 436 } 437 }, 438 439 new XOption(resources, "-Xdoclint") { 440 @Override 441 public boolean process(String opt, List<String> args) { 442 doclintOpts.add(DocLint.XMSGS_OPTION); 443 return true; 444 } 445 }, 446 447 new XOption(resources, "doclet.usage.xdoclint-extended", 448 "-Xdoclint:", 0) { 449 @Override 450 public boolean process(String opt, List<String> args) { 451 String dopt = opt.replace("-Xdoclint:", 452 DocLint.XMSGS_CUSTOM_PREFIX); 453 if (dopt.contains("/")) { 454 messages.error("doclet.Option_doclint_no_qualifiers"); 455 return false; 456 } 457 if (!(new DocLint()).isValidOption(dopt)) { 458 messages.error("doclet.Option_doclint_invalid_arg"); 459 return false; 460 } 461 doclintOpts.add(dopt); 462 return true; 463 } 464 }, 465 466 new XOption(resources, "doclet.usage.xdoclint-package", 467 "-Xdoclint/package:", 0) { 468 @Override 469 public boolean process(String opt, List<String> args) { 470 String dopt = opt.replace("-Xdoclint/package:", 471 DocLint.XCHECK_PACKAGE); 472 if (!(new DocLint()).isValidOption(dopt)) { 473 messages 474 .error("doclet.Option_doclint_package_invalid_arg"); 475 return false; 476 } 477 doclintOpts.add(dopt); 478 return true; 479 } 480 }, 481 482 new XOption(resources, "-Xdocrootparent", 1) { 483 @Override 484 public boolean process(String opt, List<String> args) { 485 docrootParent = args.get(0); 486 try { 487 @SuppressWarnings("deprecation") 488 var _unused = new URL(docrootParent); 489 } catch (MalformedURLException e) { 490 messages.error("doclet.MalformedURL", docrootParent); 491 return false; 492 } 493 return true; 494 } 495 }, 496 497 new XOption(resources, "--no-frames") { 498 @Override 499 public boolean process(String opt, List<String> args) { 500 messages.warning("doclet.NoFrames_specified"); 501 return true; 502 } 503 }); 504 Set<BaseOptions.Option> allOptions = new TreeSet<>(); 505 allOptions.addAll(options); 506 allOptions.addAll(super.getSupportedOptions()); 507 return allOptions; 508 } 509 510 protected boolean validateOptions() { 511 // check shared options 512 if (!generalValidOptions()) { 513 return false; 514 } 515 516 Messages messages = config.getMessages(); 517 518 // check if helpfile exists 519 if (!helpFile.isEmpty()) { 520 DocFile help = DocFile.createFileForInput(config, helpFile); 521 if (!help.exists()) { 522 messages.error("doclet.File_not_found", helpFile); 523 return false; 524 } 525 } 526 // check if stylesheetFile exists 527 if (!stylesheetFile.isEmpty()) { 528 DocFile stylesheet 529 = DocFile.createFileForInput(config, stylesheetFile); 530 if (!stylesheet.exists()) { 531 messages.error("doclet.File_not_found", stylesheetFile); 532 return false; 533 } 534 } 535 // check if additional stylesheets exists 536 for (String ssheet : additionalStylesheets) { 537 DocFile ssfile = DocFile.createFileForInput(config, ssheet); 538 if (!ssfile.exists()) { 539 messages.error("doclet.File_not_found", ssheet); 540 return false; 541 } 542 } 543 // check if additional scripts exists 544 for (String script : additionalScripts) { 545 DocFile sfile = DocFile.createFileForInput(config, script); 546 if (!sfile.exists()) { 547 messages.error("doclet.File_not_found", script); 548 return false; 549 } 550 } 551 // In a more object-oriented world, this would be done by methods on the 552 // Option objects. 553 // Note that -windowtitle silently removes any and all HTML elements, 554 // and so does not need 555 // to be handled here. 556 Utils utils = config.utils; 557 utils.checkJavaScriptInOption("-header", header); 558 utils.checkJavaScriptInOption("-top", top); 559 utils.checkJavaScriptInOption("-bottom", bottom); 560 utils.checkJavaScriptInOption("-doctitle", docTitle); 561 utils.checkJavaScriptInOption("-packagesheader", packagesHeader); 562 563 return true; 564 } 565 566 /** 567 * Argument for command-line option {@code --add-script}. 568 */ 569 List<String> additionalScripts() { 570 return additionalScripts; 571 } 572 573 /** 574 * Argument for command-line option {@code --add-stylesheet}. 575 */ 576 List<String> additionalStylesheets() { 577 return additionalStylesheets; 578 } 579 580 /** 581 * Argument for command-line option {@code -bottom}. 582 */ 583 String bottom() { 584 return bottom; 585 } 586 587 /** 588 * Argument for command-line option {@code -charset}. 589 * The META charset tag used for cross-platform viewing. 590 */ 591 String charset() { 592 return charset; 593 } 594 595 void setCharset(String charset) { 596 this.charset = charset; 597 } 598 599 /** 600 * Argument for command-line option {@code -use}. 601 * True if command-line option "-use" is used. Default value is false. 602 */ 603 public boolean classUse() { 604 return classUse; 605 } 606 607 /** 608 * Argument for command-line option {@code -noindex}. 609 * False if command-line option "-noindex" is used. Default value is true. 610 */ 611 public boolean createIndex() { 612 return createIndex; 613 } 614 615 /** 616 * Argument for command-line option {@code -overview}. 617 * This is true if option "-overview" is used or option "-overview" is not 618 * used and number of packages is more than one. 619 */ 620 public boolean createOverview() { 621 return createOverview; 622 } 623 624 public void setCreateOverview(boolean createOverview) { 625 this.createOverview = createOverview; 626 } 627 628 /** 629 * Argument for command-line option {@code -notree}. 630 * False if command-line option "-notree" is used. Default value is true. 631 */ 632 public boolean createTree() { 633 return createTree; 634 } 635 636 /** 637 * Arguments for command-line option {@code -Xdoclint} and friends. 638 * Collected set of doclint options. 639 */ 640 List<String> doclintOpts() { 641 return doclintOpts; 642 } 643 644 /** 645 * Argument for command-line option {@code -Xdocrootparent}. 646 */ 647 String docrootParent() { 648 return docrootParent; 649 } 650 651 /** 652 * Argument for command-line option {@code -doctitle}. 653 */ 654 String docTitle() { 655 return docTitle; 656 } 657 658 /** 659 * Argument for command-line option {@code -header}. 660 */ 661 String header() { 662 return header; 663 } 664 665 /** 666 * Argument for command-line option {@code -helpfile}. 667 */ 668 public String helpFile() { 669 return helpFile; 670 } 671 672 /** 673 * Argument for command-line option {@code --legal-notices}. 674 */ 675 public String legalNotices() { 676 return legalNotices; 677 } 678 679 /** 680 * Argument for command-line option {@code -nodeprecated}. 681 * True if command-line option "-nodeprecated" is used. Default value is 682 * false. 683 */ 684 public boolean noDeprecatedList() { 685 return noDeprecatedList; 686 } 687 688 /** 689 * Argument for command-line option {@code --no-external-specs-page}. 690 * True if command-line option "--no-external-specs-page" is used. Default value is 691 * false. 692 */ 693 public boolean noExternalSpecsPage() { 694 return noExternalSpecsPage; 695 } 696 697 /** 698 * Argument for command-line option {@code -nohelp}. 699 * True if command-line option "-nohelp" is used. Default value is false. 700 */ 701 public boolean noHelp() { 702 return noHelp; 703 } 704 705 /** 706 * Argument for command-line option {@code -nonavbar}. 707 * True if command-line option "-nonavbar" is used. Default value is false. 708 */ 709 public boolean noNavbar() { 710 return noNavbar; 711 } 712 713 /** 714 * Argument for command-line option {@code -nooverview}. 715 * True if command-line option "-nooverview" is used. Default value is 716 * false 717 */ 718 boolean noOverview() { 719 return noOverview; 720 } 721 722 /** 723 * Argument for command-line option {@code -overview}. 724 * The overview path specified with "-overview" flag. 725 */ 726 String overviewPath() { 727 return overviewPath; 728 } 729 730 /** 731 * Argument for command-line option {@code -packagesheader}. 732 */ 733 String packagesHeader() { 734 return packagesHeader; 735 } 736 737 /** 738 * Argument for command-line option {@code -splitindex}. 739 * True if command-line option "-splitindex" is used. Default value is 740 * false. 741 */ 742 public boolean splitIndex() { 743 return splitIndex; 744 } 745 746 /** 747 * Argument for command-line option {@code -stylesheetfile}. 748 */ 749 String stylesheetFile() { 750 return stylesheetFile; 751 } 752 753 /** 754 * Argument for command-line option {@code -top}. 755 */ 756 String top() { 757 return top; 758 } 759 760 /** 761 * Argument for command-line option {@code -windowtitle}. 762 */ 763 String windowTitle() { 764 return windowTitle; 765 } 766}