1 /*
   2  * Copyright (c) 1998, 2018, 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 
  26 package jdk.javadoc.internal.doclets.formats.html;
  27 
  28 import java.net.*;
  29 import java.util.*;
  30 import java.util.stream.Collectors;
  31 
  32 import javax.lang.model.element.Element;
  33 import javax.lang.model.element.PackageElement;
  34 import javax.lang.model.element.TypeElement;
  35 import javax.tools.JavaFileManager;
  36 import javax.tools.JavaFileObject;
  37 import javax.tools.StandardJavaFileManager;
  38 
  39 import com.sun.source.util.DocTreePath;
  40 import com.sun.tools.doclint.DocLint;
  41 
  42 import jdk.javadoc.doclet.Doclet;
  43 import jdk.javadoc.doclet.DocletEnvironment;
  44 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
  45 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  46 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlVersion;
  47 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
  48 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
  49 import jdk.javadoc.internal.doclets.toolkit.Content;
  50 import jdk.javadoc.internal.doclets.toolkit.DocletException;
  51 import jdk.javadoc.internal.doclets.toolkit.Messages;
  52 import jdk.javadoc.internal.doclets.toolkit.Resources;
  53 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
  54 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
  55 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  56 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  57 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
  58 
  59 import static javax.tools.Diagnostic.Kind.*;
  60 
  61 /**
  62  * Configure the output based on the command line options.
  63  * <p>
  64  * Also determine the length of the command line option. For example,
  65  * for a option "-header" there will be a string argument associated, then the
  66  * the length of option "-header" is two. But for option "-nohelp" no argument
  67  * is needed so it's length is 1.
  68  * </p>
  69  * <p>
  70  * Also do the error checking on the options used. For example it is illegal to
  71  * use "-helpfile" option when already "-nohelp" option is used.
  72  * </p>
  73  *
  74  *  <p><b>This is NOT part of any supported API.
  75  *  If you write code that depends on this, you do so at your own risk.
  76  *  This code and its internal interfaces are subject to change or
  77  *  deletion without notice.</b>
  78  *
  79  * @author Robert Field.
  80  * @author Atul Dambalkar.
  81  * @author Jamie Ho
  82  * @author Bhavesh Patel (Modified)
  83  */
  84 public class HtmlConfiguration extends BaseConfiguration {
  85 
  86     /**
  87      * Argument for command line option "-header".
  88      */
  89     public String header = "";
  90 
  91     /**
  92      * Argument for command line option "-packagesheader".
  93      */
  94     public String packagesheader = "";
  95 
  96     /**
  97      * Argument for command line option "-footer".
  98      */
  99     public String footer = "";
 100 
 101     /**
 102      * Argument for command line option "-doctitle".
 103      */
 104     public String doctitle = "";
 105 
 106     /**
 107      * Argument for command line option "-windowtitle".
 108      */
 109     public String windowtitle = "";
 110 
 111     /**
 112      * Argument for command line option "-top".
 113      */
 114     public String top = "";
 115 
 116     /**
 117      * Argument for command line option "-bottom".
 118      */
 119     public String bottom = "";
 120 
 121     /**
 122      * Argument for command line option "-helpfile".
 123      */
 124     public String helpfile = "";
 125 
 126     /**
 127      * Argument for command line option "-stylesheetfile".
 128      */
 129     public String stylesheetfile = "";
 130 
 131     /**
 132      * Argument for command line option "--add-stylesheet".
 133      */
 134     public List<String> additionalStylesheets = new ArrayList<>();
 135 
 136     /**
 137      * Argument for command line option "-Xdocrootparent".
 138      */
 139     public String docrootparent = "";
 140 
 141     /**
 142      * True if command line option "-nohelp" is used. Default value is false.
 143      */
 144     public boolean nohelp = false;
 145 
 146     /**
 147      * True if command line option "-splitindex" is used. Default value is
 148      * false.
 149      */
 150     public boolean splitindex = false;
 151 
 152     /**
 153      * False if command line option "-noindex" is used. Default value is true.
 154      */
 155     public boolean createindex = true;
 156 
 157     /**
 158      * True if command line option "-use" is used. Default value is false.
 159      */
 160     public boolean classuse = false;
 161 
 162     /**
 163      * False if command line option "-notree" is used. Default value is true.
 164      */
 165     public boolean createtree = true;
 166 
 167     /**
 168      * The META charset tag used for cross-platform viewing.
 169      */
 170     public String charset = null;
 171 
 172     /**
 173      * True if command line option "-nodeprecated" is used. Default value is
 174      * false.
 175      */
 176     public boolean nodeprecatedlist = false;
 177 
 178     /**
 179      * True if command line option "-nonavbar" is used. Default value is false.
 180      */
 181     public boolean nonavbar = false;
 182 
 183     /**
 184      * True if command line option "-nooverview" is used. Default value is
 185      * false
 186      */
 187     private boolean nooverview = false;
 188 
 189     /**
 190      * The overview path specified with "-overview" flag.
 191      */
 192     public String overviewpath = null;
 193 
 194     /**
 195      * This is true if option "-overview" is used or option "-overview" is not
 196      * used and number of packages is more than one.
 197      */
 198     public boolean createoverview = false;
 199 
 200     /**
 201      * Specifies whether or not frames should be generated.
 202      * Defaults to true; can be set by --frames; can be set to false by --no-frames; last one wins.
 203      */
 204     public boolean frames = true;
 205 
 206     /**
 207      * This is the HTML version of the generated pages.
 208      * The default value is determined later.
 209      */
 210     public HtmlVersion htmlVersion = null;
 211 
 212     /**
 213      * Collected set of doclint options
 214      */
 215     public Map<Doclet.Option, String> doclintOpts = new LinkedHashMap<>();
 216 
 217     public final Resources resources;
 218 
 219     /**
 220      * First file to appear in the right-hand frame in the generated
 221      * documentation.
 222      */
 223     public DocPath topFile = DocPath.empty;
 224 
 225     /**
 226      * The TypeElement for the class file getting generated.
 227      */
 228     public TypeElement currentTypeElement = null;  // Set this TypeElement in the ClassWriter.
 229 
 230     protected List<SearchIndexItem> memberSearchIndex = new ArrayList<>();
 231 
 232     protected List<SearchIndexItem> moduleSearchIndex = new ArrayList<>();
 233 
 234     protected List<SearchIndexItem> packageSearchIndex = new ArrayList<>();
 235 
 236     protected SortedSet<SearchIndexItem> tagSearchIndex = new TreeSet<>(makeSearchTagComparator());
 237 
 238     protected List<SearchIndexItem> typeSearchIndex = new ArrayList<>();
 239 
 240     protected Map<Character,List<SearchIndexItem>> tagSearchIndexMap = new HashMap<>();
 241 
 242     protected Set<Character> tagSearchIndexKeys;
 243 
 244     protected final Contents contents;
 245 
 246     protected final Messages messages;
 247 
 248     /**
 249      * Creates an object to hold the configuration for a doclet.
 250      *
 251      * @param doclet the doclet
 252      */
 253     public HtmlConfiguration(Doclet doclet) {
 254         super(doclet);
 255         resources = new Resources(this,
 256                 BaseConfiguration.sharedResourceBundleName,
 257                 "jdk.javadoc.internal.doclets.formats.html.resources.standard");
 258 
 259         messages = new Messages(this);
 260         contents = new Contents(this);
 261 
 262         String v;
 263         try {
 264             ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, getLocale());
 265             try {
 266                 v = rb.getString("release");
 267             } catch (MissingResourceException e) {
 268                 v = defaultDocletVersion;
 269             }
 270         } catch (MissingResourceException e) {
 271             v = defaultDocletVersion;
 272         }
 273         docletVersion = v;
 274     }
 275 
 276     private static final String versionBundleName = "jdk.javadoc.internal.tool.resources.version";
 277     private static final String defaultDocletVersion = System.getProperty("java.version");
 278     public final String docletVersion;
 279 
 280     @Override
 281     public String getDocletVersion() {
 282         return docletVersion;
 283     }
 284 
 285     @Override
 286     public Resources getResources() {
 287         return resources;
 288     }
 289 
 290     @Override
 291     public Messages getMessages() {
 292         return messages;
 293     }
 294 
 295     protected boolean validateOptions() {
 296         // check shared options
 297         if (!generalValidOptions()) {
 298             return false;
 299         }
 300 
 301         if (htmlVersion == null) {
 302             reporter.print(WARNING, getText("doclet.HTML_version_not_specified", helpfile));
 303             htmlVersion = HtmlVersion.HTML4;
 304         }
 305 
 306         // check if helpfile exists
 307         if (!helpfile.isEmpty()) {
 308             DocFile help = DocFile.createFileForInput(this, helpfile);
 309             if (!help.exists()) {
 310                 reporter.print(ERROR, getText("doclet.File_not_found", helpfile));
 311                 return false;
 312             }
 313         }
 314         // check if stylesheetfile exists
 315         if (!stylesheetfile.isEmpty()) {
 316             DocFile stylesheet = DocFile.createFileForInput(this, stylesheetfile);
 317             if (!stylesheet.exists()) {
 318                 reporter.print(ERROR, getText("doclet.File_not_found", stylesheetfile));
 319                 return false;
 320             }
 321         }
 322         // check if additional stylesheets exists
 323         for (String ssheet : additionalStylesheets) {
 324             DocFile ssfile = DocFile.createFileForInput(this, ssheet);
 325             if (!ssfile.exists()) {
 326                 reporter.print(ERROR, getText("doclet.File_not_found", ssheet));
 327                 return false;
 328             }
 329         }
 330 
 331         // In a more object-oriented world, this would be done by methods on the Option objects.
 332         // Note that -windowtitle silently removes any and all HTML elements, and so does not need
 333         // to be handled here.
 334         utils.checkJavaScriptInOption("-header", header);
 335         utils.checkJavaScriptInOption("-footer", footer);
 336         utils.checkJavaScriptInOption("-top", top);
 337         utils.checkJavaScriptInOption("-bottom", bottom);
 338         utils.checkJavaScriptInOption("-doctitle", doctitle);
 339         utils.checkJavaScriptInOption("-packagesheader", packagesheader);
 340 
 341         return true;
 342     }
 343 
 344 
 345     @Override
 346     public boolean finishOptionSettings() {
 347         if (!validateOptions()) {
 348             return false;
 349         }
 350         if (!getSpecifiedTypeElements().isEmpty()) {
 351             Map<String, PackageElement> map = new HashMap<>();
 352             PackageElement pkg;
 353             for (TypeElement aClass : getIncludedTypeElements()) {
 354                 pkg = utils.containingPackage(aClass);
 355                 if (!map.containsKey(utils.getPackageName(pkg))) {
 356                     map.put(utils.getPackageName(pkg), pkg);
 357                 }
 358             }
 359         }
 360         setCreateOverview();
 361         setTopFile(docEnv);
 362         workArounds.initDocLint(doclintOpts.values(), tagletManager.getCustomTagNames(),
 363                 Utils.toLowerCase(htmlVersion.name()));
 364         return true;
 365     }
 366 
 367     /**
 368      * Return true if the generated output is HTML5.
 369      */
 370     public boolean isOutputHtml5() {
 371         return htmlVersion == HtmlVersion.HTML5;
 372     }
 373 
 374     /**
 375      * Return true if the tag is allowed for this specific version of HTML.
 376      */
 377     public boolean allowTag(HtmlTag htmlTag) {
 378         return htmlTag.allowTag(this.htmlVersion);
 379     }
 380 
 381     public Comparator<SearchIndexItem> makeSearchTagComparator() {
 382         return (SearchIndexItem sii1, SearchIndexItem sii2) -> {
 383             int result = (sii1.getLabel()).compareTo(sii2.getLabel());
 384             if (result == 0) {
 385                 result = (sii1.getHolder()).compareTo(sii2.getHolder());
 386             }
 387             return result;
 388         };
 389     }
 390 
 391     /**
 392      * Decide the page which will appear first in the right-hand frame. It will
 393      * be "overview-summary.html" if "-overview" option is used or no
 394      * "-overview" but the number of packages is more than one. It will be
 395      * "package-summary.html" of the respective package if there is only one
 396      * package to document. It will be a class page(first in the sorted order),
 397      * if only classes are provided on the command line.
 398      *
 399      * @param docEnv the doclet environment
 400      */
 401     protected void setTopFile(DocletEnvironment docEnv) {
 402         if (!checkForDeprecation(docEnv)) {
 403             return;
 404         }
 405         if (createoverview) {
 406             topFile = DocPaths.overviewSummary(frames);
 407         } else {
 408             if (showModules) {
 409                 topFile = DocPath.empty.resolve(DocPaths.moduleSummary(modules.first()));
 410             } else if (packages.size() == 1 && packages.first().isUnnamed()) {
 411                 List<TypeElement> classes = new ArrayList<>(getIncludedTypeElements());
 412                 if (!classes.isEmpty()) {
 413                     TypeElement te = getValidClass(classes);
 414                     topFile = DocPath.forClass(utils, te);
 415                 }
 416             } else if (!packages.isEmpty()) {
 417                 topFile = DocPath.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY);
 418             }
 419         }
 420     }
 421 
 422     protected TypeElement getValidClass(List<TypeElement> classes) {
 423         if (!nodeprecated) {
 424             return classes.get(0);
 425         }
 426         for (TypeElement te : classes) {
 427             if (!utils.isDeprecated(te)) {
 428                 return te;
 429             }
 430         }
 431         return null;
 432     }
 433 
 434     protected boolean checkForDeprecation(DocletEnvironment docEnv) {
 435         for (TypeElement te : getIncludedTypeElements()) {
 436             if (isGeneratedDoc(te)) {
 437                 return true;
 438             }
 439         }
 440         return false;
 441     }
 442 
 443     /**
 444      * Generate "overview.html" page if option "-overview" is used or number of
 445      * packages is more than one. Sets {@link #createoverview} field to true.
 446      */
 447     protected void setCreateOverview() {
 448         if ((overviewpath != null || packages.size() > 1) && !nooverview) {
 449             createoverview = true;
 450         }
 451     }
 452 
 453     /**
 454      * {@inheritDoc}
 455      */
 456     @Override
 457     public WriterFactory getWriterFactory() {
 458         return new WriterFactoryImpl(this);
 459     }
 460 
 461     /**
 462      * {@inheritDoc}
 463      */
 464     @Override
 465     public Locale getLocale() {
 466         if (locale == null)
 467             return Locale.getDefault();
 468         return locale;
 469     }
 470 
 471     /**
 472      * Return the path of the overview file or null if it does not exist.
 473      *
 474      * @return the path of the overview file or null if it does not exist.
 475      */
 476     @Override
 477     public JavaFileObject getOverviewPath() {
 478         if (overviewpath != null && getFileManager() instanceof StandardJavaFileManager) {
 479             StandardJavaFileManager fm = (StandardJavaFileManager) getFileManager();
 480             return fm.getJavaFileObjects(overviewpath).iterator().next();
 481         }
 482         return null;
 483     }
 484 
 485     public DocFile getMainStylesheet() {
 486         return stylesheetfile.isEmpty() ? null : DocFile.createFileForInput(this, stylesheetfile);
 487     }
 488 
 489     public List<DocFile> getAdditionalStylesheets() {
 490         return additionalStylesheets.stream()
 491                 .map(ssf -> DocFile.createFileForInput(this, ssf))
 492                 .collect(Collectors.toList());
 493     }
 494 
 495     /**
 496      * {@inheritDoc}
 497      */
 498     @Override
 499     public JavaFileManager getFileManager() {
 500         return docEnv.getJavaFileManager();
 501     }
 502 
 503     @Override
 504     public boolean showMessage(DocTreePath path, String key) {
 505         return (path == null || workArounds.haveDocLint());
 506     }
 507 
 508     @Override
 509     public boolean showMessage(Element e, String key) {
 510         return (e == null || workArounds.haveDocLint());
 511     }
 512 
 513     @Override
 514     public String getText(String key) {
 515         return resources.getText(key);
 516     }
 517 
 518     @Override
 519     public String getText(String key, String... args) {
 520         return resources.getText(key, (Object[]) args);
 521     }
 522 
 523    /**
 524      * {@inheritdoc}
 525      */
 526     @Override
 527     public Content getContent(String key) {
 528         return contents.getContent(key);
 529     }
 530 
 531     /**
 532      * Get the configuration string as a content.
 533      *
 534      * @param key the key to look for in the configuration file
 535      * @param o   string or content argument added to configuration text
 536      * @return a content tree for the text
 537      */
 538     @Override
 539     public Content getContent(String key, Object o) {
 540         return contents.getContent(key, o);
 541     }
 542 
 543     /**
 544      * Get the configuration string as a content.
 545      *
 546      * @param key the key to look for in the configuration file
 547      * @param o1 resource argument
 548      * @param o2 resource argument
 549      * @return a content tree for the text
 550      */
 551     @Override
 552     public Content getContent(String key, Object o1, Object o2) {
 553         return contents.getContent(key, o1, o2);
 554     }
 555 
 556     /**
 557      * Get the configuration string as a content.
 558      *
 559      * @param key the key to look for in the configuration file
 560      * @param o0  string or content argument added to configuration text
 561      * @param o1  string or content argument added to configuration text
 562      * @param o2  string or content argument added to configuration text
 563      * @return a content tree for the text
 564      */
 565     @Override
 566     public Content getContent(String key, Object o0, Object o1, Object o2) {
 567         return contents.getContent(key, o0, o1, o2);
 568     }
 569 
 570     protected void buildSearchTagIndex() {
 571         for (SearchIndexItem sii : tagSearchIndex) {
 572             String tagLabel = sii.getLabel();
 573             Character unicode = (tagLabel.length() == 0)
 574                     ? '*'
 575                     : Character.toUpperCase(tagLabel.charAt(0));
 576             List<SearchIndexItem> list = tagSearchIndexMap.get(unicode);
 577             if (list == null) {
 578                 list = new ArrayList<>();
 579                 tagSearchIndexMap.put(unicode, list);
 580             }
 581             list.add(sii);
 582         }
 583         tagSearchIndexKeys = tagSearchIndexMap.keySet();
 584     }
 585 
 586     @Override
 587     public Set<Doclet.Option> getSupportedOptions() {
 588         Resources resources = getResources();
 589         Doclet.Option[] options = {
 590             new Option(resources, "--add-stylesheet", 1) {
 591                 @Override
 592                 public boolean process(String opt, List<String> args) {
 593                     additionalStylesheets.add(args.get(0));
 594                     return true;
 595                 }
 596             },
 597             new Option(resources, "-bottom", 1) {
 598                 @Override
 599                 public boolean process(String opt,  List<String> args) {
 600                     bottom = args.get(0);
 601                     return true;
 602                 }
 603             },
 604             new Option(resources, "-charset", 1) {
 605                 @Override
 606                 public boolean process(String opt,  List<String> args) {
 607                     charset = args.get(0);
 608                     return true;
 609                 }
 610             },
 611             new Option(resources, "-doctitle", 1) {
 612                 @Override
 613                 public boolean process(String opt,  List<String> args) {
 614                     doctitle = args.get(0);
 615                     return true;
 616                 }
 617             },
 618             new Option(resources, "-footer", 1) {
 619                 @Override
 620                 public boolean process(String opt, List<String> args) {
 621                     footer = args.get(0);
 622                     return true;
 623                 }
 624             },
 625             new Option(resources, "-header", 1) {
 626                 @Override
 627                 public boolean process(String opt,  List<String> args) {
 628                     header = args.get(0);
 629                     return true;
 630                 }
 631             },
 632             new Option(resources, "-helpfile", 1) {
 633                 @Override
 634                 public boolean process(String opt,  List<String> args) {
 635                     if (nohelp == true) {
 636                         reporter.print(ERROR, getText("doclet.Option_conflict",
 637                                 "-helpfile", "-nohelp"));
 638                         return false;
 639                     }
 640                     if (!helpfile.isEmpty()) {
 641                         reporter.print(ERROR, getText("doclet.Option_reuse",
 642                                 "-helpfile"));
 643                         return false;
 644                     }
 645                     helpfile = args.get(0);
 646                     return true;
 647                 }
 648             },
 649             new Option(resources, "-html4") {
 650                 @Override
 651                 public boolean process(String opt,  List<String> args) {
 652                     htmlVersion = HtmlVersion.HTML4;
 653                     return true;
 654                 }
 655             },
 656             new Option(resources, "-html5") {
 657                 @Override
 658                 public boolean process(String opt,  List<String> args) {
 659                     htmlVersion = HtmlVersion.HTML5;
 660                     return true;
 661                 }
 662             },
 663             new Option(resources, "-nohelp") {
 664                 @Override
 665                 public boolean process(String opt, List<String> args) {
 666                     nohelp = true;
 667                     if (!helpfile.isEmpty()) {
 668                         reporter.print(ERROR, getText("doclet.Option_conflict",
 669                                 "-nohelp", "-helpfile"));
 670                         return false;
 671                     }
 672                     return true;
 673                 }
 674             },
 675             new Option(resources, "-nodeprecatedlist") {
 676                 @Override
 677                 public boolean process(String opt,  List<String> args) {
 678                     nodeprecatedlist = true;
 679                     return true;
 680                 }
 681             },
 682             new Option(resources, "-noindex") {
 683                 @Override
 684                 public boolean process(String opt,  List<String> args) {
 685                     createindex = false;
 686                     if (splitindex == true) {
 687                         reporter.print(ERROR, getText("doclet.Option_conflict",
 688                                 "-noindex", "-splitindex"));
 689                         return false;
 690                     }
 691                     return true;
 692                 }
 693             },
 694             new Option(resources, "-nonavbar") {
 695                 @Override
 696                 public boolean process(String opt,  List<String> args) {
 697                     nonavbar = true;
 698                     return true;
 699                 }
 700             },
 701             new Hidden(resources, "-nooverview") {
 702                 @Override
 703                 public boolean process(String opt,  List<String> args) {
 704                     nooverview = true;
 705                     if (overviewpath != null) {
 706                         reporter.print(ERROR, getText("doclet.Option_conflict",
 707                                 "-nooverview", "-overview"));
 708                         return false;
 709                     }
 710                     return true;
 711                 }
 712             },
 713             new Option(resources, "-notree") {
 714                 @Override
 715                 public boolean process(String opt,  List<String> args) {
 716                     createtree = false;
 717                     return true;
 718                 }
 719             },
 720             new Option(resources, "-overview", 1) {
 721                 @Override
 722                 public boolean process(String opt,  List<String> args) {
 723                     overviewpath = args.get(0);
 724                     if (nooverview == true) {
 725                         reporter.print(ERROR, getText("doclet.Option_conflict",
 726                                 "-overview", "-nooverview"));
 727                         return false;
 728                     }
 729                     return true;
 730                 }
 731             },
 732             new Option(resources, "--frames") {
 733                 @Override
 734                 public boolean process(String opt,  List<String> args) {
 735                     frames = true;
 736                     return true;
 737                 }
 738             },
 739             new Option(resources, "--no-frames") {
 740                 @Override
 741                 public boolean process(String opt,  List<String> args) {
 742                     frames = false;
 743                     return true;
 744                 }
 745             },
 746             new Hidden(resources, "-packagesheader", 1) {
 747                 @Override
 748                 public boolean process(String opt,  List<String> args) {
 749                     packagesheader = args.get(0);
 750                     return true;
 751                 }
 752             },
 753             new Option(resources, "-splitindex") {
 754                 @Override
 755                 public boolean process(String opt, List<String> args) {
 756                     splitindex = true;
 757                     if (createindex == false) {
 758                         reporter.print(ERROR, getText("doclet.Option_conflict",
 759                                 "-splitindex", "-noindex"));
 760                         return false;
 761                     }
 762                     return true;
 763                 }
 764             },
 765             new Option(resources, "--main-stylesheet -stylesheetfile", 1) {
 766                 @Override
 767                 public boolean process(String opt,  List<String> args) {
 768                     stylesheetfile = args.get(0);
 769                     return true;
 770                 }
 771             },
 772             new Option(resources, "-top", 1) {
 773                 @Override
 774                 public boolean process(String opt,  List<String> args) {
 775                     top = args.get(0);
 776                     return true;
 777                 }
 778             },
 779             new Option(resources, "-use") {
 780                 @Override
 781                 public boolean process(String opt,  List<String> args) {
 782                     classuse = true;
 783                     return true;
 784                 }
 785             },
 786             new Option(resources, "-windowtitle", 1) {
 787                 @Override
 788                 public boolean process(String opt,  List<String> args) {
 789                     windowtitle = args.get(0).replaceAll("\\<.*?>", "");
 790                     return true;
 791                 }
 792             },
 793             new XOption(resources, "-Xdoclint") {
 794                 @Override
 795                 public boolean process(String opt,  List<String> args) {
 796                     doclintOpts.put(this, DocLint.XMSGS_OPTION);
 797                     return true;
 798                 }
 799             },
 800             new XOption(resources, "-Xdocrootparent", 1) {
 801                 @Override
 802                 public boolean process(String opt, List<String> args) {
 803                     docrootparent = args.get(0);
 804                     try {
 805                         URL ignored = new URL(docrootparent);
 806                     } catch (MalformedURLException e) {
 807                         reporter.print(ERROR, getText("doclet.MalformedURL", docrootparent));
 808                         return false;
 809                     }
 810                     return true;
 811                 }
 812             },
 813             new XOption(resources, "doclet.usage.xdoclint-extended", "-Xdoclint:", 0) {
 814                 @Override
 815                 public boolean process(String opt,  List<String> args) {
 816                     String dopt = opt.replace("-Xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX);
 817                     doclintOpts.put(this, dopt);
 818                     if (dopt.contains("/")) {
 819                         reporter.print(ERROR, getText("doclet.Option_doclint_no_qualifiers"));
 820                         return false;
 821                     }
 822                     if (!DocLint.isValidOption(dopt)) {
 823                         reporter.print(ERROR, getText("doclet.Option_doclint_invalid_arg"));
 824                         return false;
 825                     }
 826                     return true;
 827                 }
 828             },
 829             new XOption(resources, "doclet.usage.xdoclint-package", "-Xdoclint/package:", 0) {
 830                 @Override
 831                 public boolean process(String opt,  List<String> args) {
 832                     String dopt = opt.replace("-Xdoclint/package:", DocLint.XCHECK_PACKAGE);
 833                     doclintOpts.put(this, dopt);
 834                     if (!DocLint.isValidOption(dopt)) {
 835                         reporter.print(ERROR, getText("doclet.Option_doclint_package_invalid_arg"));
 836                         return false;
 837                     }
 838                     return true;
 839                 }
 840             }
 841         };
 842         Set<Doclet.Option> oset = new TreeSet<>();
 843         oset.addAll(Arrays.asList(options));
 844         oset.addAll(super.getSupportedOptions());
 845         return oset;
 846     }
 847 
 848     @Override
 849     protected boolean finishOptionSettings0() throws DocletException {
 850         if (docencoding == null) {
 851             if (charset == null) {
 852                 docencoding = charset = (encoding == null) ? HtmlConstants.HTML_DEFAULT_CHARSET : encoding;
 853             } else {
 854                 docencoding = charset;
 855             }
 856         } else {
 857             if (charset == null) {
 858                 charset = docencoding;
 859             } else if (!charset.equals(docencoding)) {
 860                 reporter.print(ERROR, getText("doclet.Option_conflict", "-charset", "-docencoding"));
 861                 return false;
 862             }
 863         }
 864         return super.finishOptionSettings0();
 865     }
 866 }