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