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      * Flag to enable/disable use of module directories when generating docs for modules
 214      * Default: on (module directories are enabled).
 215      */
 216     public boolean useModuleDirectories = true;
 217 
 218     /**
 219      * Collected set of doclint options
 220      */
 221     public Map<Doclet.Option, String> doclintOpts = new LinkedHashMap<>();
 222 
 223     public final Resources resources;
 224 
 225     /**
 226      * First file to appear in the right-hand frame in the generated
 227      * documentation.
 228      */
 229     public DocPath topFile = DocPath.empty;
 230 
 231     /**
 232      * The TypeElement for the class file getting generated.
 233      */
 234     public TypeElement currentTypeElement = null;  // Set this TypeElement in the ClassWriter.
 235 
 236     protected List<SearchIndexItem> memberSearchIndex = new ArrayList<>();
 237 
 238     protected List<SearchIndexItem> moduleSearchIndex = new ArrayList<>();
 239 
 240     protected List<SearchIndexItem> packageSearchIndex = new ArrayList<>();
 241 
 242     protected SortedSet<SearchIndexItem> tagSearchIndex = new TreeSet<>(makeSearchTagComparator());
 243 
 244     protected List<SearchIndexItem> typeSearchIndex = new ArrayList<>();
 245 
 246     protected Map<Character,List<SearchIndexItem>> tagSearchIndexMap = new HashMap<>();
 247 
 248     protected Set<Character> tagSearchIndexKeys;
 249 
 250     protected final Contents contents;
 251 
 252     protected final Messages messages;
 253 
 254     protected DocPaths docPaths;
 255 
 256     /**
 257      * Creates an object to hold the configuration for a doclet.
 258      *
 259      * @param doclet the doclet
 260      */
 261     public HtmlConfiguration(Doclet doclet) {
 262         super(doclet);
 263         resources = new Resources(this,
 264                 BaseConfiguration.sharedResourceBundleName,
 265                 "jdk.javadoc.internal.doclets.formats.html.resources.standard");
 266 
 267         messages = new Messages(this);
 268         contents = new Contents(this);
 269 
 270         String v;
 271         try {
 272             ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, getLocale());
 273             try {
 274                 v = rb.getString("release");
 275             } catch (MissingResourceException e) {
 276                 v = defaultDocletVersion;
 277             }
 278         } catch (MissingResourceException e) {
 279             v = defaultDocletVersion;
 280         }
 281         docletVersion = v;
 282     }
 283 
 284     private static final String versionBundleName = "jdk.javadoc.internal.tool.resources.version";
 285     private static final String defaultDocletVersion = System.getProperty("java.version");
 286     public final String docletVersion;
 287 
 288     @Override
 289     public String getDocletVersion() {
 290         return docletVersion;
 291     }
 292 
 293     @Override
 294     public Resources getResources() {
 295         return resources;
 296     }
 297 
 298     @Override
 299     public Messages getMessages() {
 300         return messages;
 301     }
 302 
 303     protected boolean validateOptions() {
 304         // check shared options
 305         if (!generalValidOptions()) {
 306             return false;
 307         }
 308 
 309         if (htmlVersion == null) {
 310             reporter.print(WARNING, getText("doclet.HTML_version_not_specified", helpfile));
 311             htmlVersion = HtmlVersion.HTML4;
 312         }
 313 
 314         // check if helpfile exists
 315         if (!helpfile.isEmpty()) {
 316             DocFile help = DocFile.createFileForInput(this, helpfile);
 317             if (!help.exists()) {
 318                 reporter.print(ERROR, getText("doclet.File_not_found", helpfile));
 319                 return false;
 320             }
 321         }
 322         // check if stylesheetfile exists
 323         if (!stylesheetfile.isEmpty()) {
 324             DocFile stylesheet = DocFile.createFileForInput(this, stylesheetfile);
 325             if (!stylesheet.exists()) {
 326                 reporter.print(ERROR, getText("doclet.File_not_found", stylesheetfile));
 327                 return false;
 328             }
 329         }
 330         // check if additional stylesheets exists
 331         for (String ssheet : additionalStylesheets) {
 332             DocFile ssfile = DocFile.createFileForInput(this, ssheet);
 333             if (!ssfile.exists()) {
 334                 reporter.print(ERROR, getText("doclet.File_not_found", ssheet));
 335                 return false;
 336             }
 337         }
 338 
 339         // In a more object-oriented world, this would be done by methods on the Option objects.
 340         // Note that -windowtitle silently removes any and all HTML elements, and so does not need
 341         // to be handled here.
 342         utils.checkJavaScriptInOption("-header", header);
 343         utils.checkJavaScriptInOption("-footer", footer);
 344         utils.checkJavaScriptInOption("-top", top);
 345         utils.checkJavaScriptInOption("-bottom", bottom);
 346         utils.checkJavaScriptInOption("-doctitle", doctitle);
 347         utils.checkJavaScriptInOption("-packagesheader", packagesheader);
 348 
 349         return true;
 350     }
 351 
 352 
 353     @Override
 354     public boolean finishOptionSettings() {
 355         if (!validateOptions()) {
 356             return false;
 357         }
 358         if (!getSpecifiedTypeElements().isEmpty()) {
 359             Map<String, PackageElement> map = new HashMap<>();
 360             PackageElement pkg;
 361             for (TypeElement aClass : getIncludedTypeElements()) {
 362                 pkg = utils.containingPackage(aClass);
 363                 if (!map.containsKey(utils.getPackageName(pkg))) {
 364                     map.put(utils.getPackageName(pkg), pkg);
 365                 }
 366             }
 367         }
 368         docPaths = new DocPaths(utils, useModuleDirectories);
 369         setCreateOverview();
 370         setTopFile(docEnv);
 371         workArounds.initDocLint(doclintOpts.values(), tagletManager.getCustomTagNames(),
 372                 Utils.toLowerCase(htmlVersion.name()));
 373         return true;
 374     }
 375 
 376     /**
 377      * Return true if the generated output is HTML5.
 378      */
 379     public boolean isOutputHtml5() {
 380         return htmlVersion == HtmlVersion.HTML5;
 381     }
 382 
 383     /**
 384      * Return true if the tag is allowed for this specific version of HTML.
 385      */
 386     public boolean allowTag(HtmlTag htmlTag) {
 387         return htmlTag.allowTag(this.htmlVersion);
 388     }
 389 
 390     public Comparator<SearchIndexItem> makeSearchTagComparator() {
 391         return (SearchIndexItem sii1, SearchIndexItem sii2) -> {
 392             int result = (sii1.getLabel()).compareTo(sii2.getLabel());
 393             if (result == 0) {
 394                 result = (sii1.getHolder()).compareTo(sii2.getHolder());
 395             }
 396             return result;
 397         };
 398     }
 399 
 400     /**
 401      * Decide the page which will appear first in the right-hand frame. It will
 402      * be "overview-summary.html" if "-overview" option is used or no
 403      * "-overview" but the number of packages is more than one. It will be
 404      * "package-summary.html" of the respective package if there is only one
 405      * package to document. It will be a class page(first in the sorted order),
 406      * if only classes are provided on the command line.
 407      *
 408      * @param docEnv the doclet environment
 409      */
 410     protected void setTopFile(DocletEnvironment docEnv) {
 411         if (!checkForDeprecation(docEnv)) {
 412             return;
 413         }
 414         if (createoverview) {
 415             topFile = DocPaths.overviewSummary(frames);
 416         } else {
 417             if (showModules) {
 418                 topFile = DocPath.empty.resolve(docPaths.moduleSummary(modules.first()));
 419             } else if (packages.size() == 1 && packages.first().isUnnamed()) {
 420                 List<TypeElement> classes = new ArrayList<>(getIncludedTypeElements());
 421                 if (!classes.isEmpty()) {
 422                     TypeElement te = getValidClass(classes);
 423                     topFile = docPaths.forClass(te);
 424                 }
 425             } else if (!packages.isEmpty()) {
 426                 topFile = docPaths.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY);
 427             }
 428         }
 429     }
 430 
 431     protected TypeElement getValidClass(List<TypeElement> classes) {
 432         if (!nodeprecated) {
 433             return classes.get(0);
 434         }
 435         for (TypeElement te : classes) {
 436             if (!utils.isDeprecated(te)) {
 437                 return te;
 438             }
 439         }
 440         return null;
 441     }
 442 
 443     protected boolean checkForDeprecation(DocletEnvironment docEnv) {
 444         for (TypeElement te : getIncludedTypeElements()) {
 445             if (isGeneratedDoc(te)) {
 446                 return true;
 447             }
 448         }
 449         return false;
 450     }
 451 
 452     /**
 453      * Generate "overview.html" page if option "-overview" is used or number of
 454      * packages is more than one. Sets {@link #createoverview} field to true.
 455      */
 456     protected void setCreateOverview() {
 457         if ((overviewpath != null || packages.size() > 1) && !nooverview) {
 458             createoverview = true;
 459         }
 460     }
 461 
 462     /**
 463      * {@inheritDoc}
 464      */
 465     @Override
 466     public WriterFactory getWriterFactory() {
 467         return new WriterFactoryImpl(this);
 468     }
 469 
 470     /**
 471      * {@inheritDoc}
 472      */
 473     @Override
 474     public Locale getLocale() {
 475         if (locale == null)
 476             return Locale.getDefault();
 477         return locale;
 478     }
 479 
 480     /**
 481      * Return the path of the overview file or null if it does not exist.
 482      *
 483      * @return the path of the overview file or null if it does not exist.
 484      */
 485     @Override
 486     public JavaFileObject getOverviewPath() {
 487         if (overviewpath != null && getFileManager() instanceof StandardJavaFileManager) {
 488             StandardJavaFileManager fm = (StandardJavaFileManager) getFileManager();
 489             return fm.getJavaFileObjects(overviewpath).iterator().next();
 490         }
 491         return null;
 492     }
 493 
 494     public DocFile getMainStylesheet() {
 495         return stylesheetfile.isEmpty() ? null : DocFile.createFileForInput(this, stylesheetfile);
 496     }
 497 
 498     public List<DocFile> getAdditionalStylesheets() {
 499         return additionalStylesheets.stream()
 500                 .map(ssf -> DocFile.createFileForInput(this, ssf))
 501                 .collect(Collectors.toList());
 502     }
 503 
 504     /**
 505      * {@inheritDoc}
 506      */
 507     @Override
 508     public JavaFileManager getFileManager() {
 509         return docEnv.getJavaFileManager();
 510     }
 511 
 512     @Override
 513     public boolean showMessage(DocTreePath path, String key) {
 514         return (path == null || workArounds.haveDocLint());
 515     }
 516 
 517     @Override
 518     public boolean showMessage(Element e, String key) {
 519         return (e == null || workArounds.haveDocLint());
 520     }
 521 
 522     @Override
 523     public String getText(String key) {
 524         return resources.getText(key);
 525     }
 526 
 527     @Override
 528     public String getText(String key, String... args) {
 529         return resources.getText(key, (Object[]) args);
 530     }
 531 
 532    /**
 533      * {@inheritdoc}
 534      */
 535     @Override
 536     public Content getContent(String key) {
 537         return contents.getContent(key);
 538     }
 539 
 540     /**
 541      * Get the configuration string as a content.
 542      *
 543      * @param key the key to look for in the configuration file
 544      * @param o   string or content argument added to configuration text
 545      * @return a content tree for the text
 546      */
 547     @Override
 548     public Content getContent(String key, Object o) {
 549         return contents.getContent(key, o);
 550     }
 551 
 552     /**
 553      * Get the configuration string as a content.
 554      *
 555      * @param key the key to look for in the configuration file
 556      * @param o1 resource argument
 557      * @param o2 resource argument
 558      * @return a content tree for the text
 559      */
 560     @Override
 561     public Content getContent(String key, Object o1, Object o2) {
 562         return contents.getContent(key, o1, o2);
 563     }
 564 
 565     /**
 566      * Get the configuration string as a content.
 567      *
 568      * @param key the key to look for in the configuration file
 569      * @param o0  string or content argument added to configuration text
 570      * @param o1  string or content argument added to configuration text
 571      * @param o2  string or content argument added to configuration text
 572      * @return a content tree for the text
 573      */
 574     @Override
 575     public Content getContent(String key, Object o0, Object o1, Object o2) {
 576         return contents.getContent(key, o0, o1, o2);
 577     }
 578 
 579     protected void buildSearchTagIndex() {
 580         for (SearchIndexItem sii : tagSearchIndex) {
 581             String tagLabel = sii.getLabel();
 582             Character unicode = (tagLabel.length() == 0)
 583                     ? '*'
 584                     : Character.toUpperCase(tagLabel.charAt(0));
 585             List<SearchIndexItem> list = tagSearchIndexMap.get(unicode);
 586             if (list == null) {
 587                 list = new ArrayList<>();
 588                 tagSearchIndexMap.put(unicode, list);
 589             }
 590             list.add(sii);
 591         }
 592         tagSearchIndexKeys = tagSearchIndexMap.keySet();
 593     }
 594 
 595     @Override
 596     public Set<Doclet.Option> getSupportedOptions() {
 597         Resources resources = getResources();
 598         Doclet.Option[] options = {
 599             new Option(resources, "--add-stylesheet", 1) {
 600                 @Override
 601                 public boolean process(String opt, List<String> args) {
 602                     additionalStylesheets.add(args.get(0));
 603                     return true;
 604                 }
 605             },
 606             new Option(resources, "-bottom", 1) {
 607                 @Override
 608                 public boolean process(String opt,  List<String> args) {
 609                     bottom = args.get(0);
 610                     return true;
 611                 }
 612             },
 613             new Option(resources, "-charset", 1) {
 614                 @Override
 615                 public boolean process(String opt,  List<String> args) {
 616                     charset = args.get(0);
 617                     return true;
 618                 }
 619             },
 620             new Option(resources, "-doctitle", 1) {
 621                 @Override
 622                 public boolean process(String opt,  List<String> args) {
 623                     doctitle = args.get(0);
 624                     return true;
 625                 }
 626             },
 627             new Option(resources, "-footer", 1) {
 628                 @Override
 629                 public boolean process(String opt, List<String> args) {
 630                     footer = args.get(0);
 631                     return true;
 632                 }
 633             },
 634             new Option(resources, "-header", 1) {
 635                 @Override
 636                 public boolean process(String opt,  List<String> args) {
 637                     header = args.get(0);
 638                     return true;
 639                 }
 640             },
 641             new Option(resources, "-helpfile", 1) {
 642                 @Override
 643                 public boolean process(String opt,  List<String> args) {
 644                     if (nohelp == true) {
 645                         reporter.print(ERROR, getText("doclet.Option_conflict",
 646                                 "-helpfile", "-nohelp"));
 647                         return false;
 648                     }
 649                     if (!helpfile.isEmpty()) {
 650                         reporter.print(ERROR, getText("doclet.Option_reuse",
 651                                 "-helpfile"));
 652                         return false;
 653                     }
 654                     helpfile = args.get(0);
 655                     return true;
 656                 }
 657             },
 658             new Option(resources, "-html4") {
 659                 @Override
 660                 public boolean process(String opt,  List<String> args) {
 661                     htmlVersion = HtmlVersion.HTML4;
 662                     return true;
 663                 }
 664             },
 665             new Option(resources, "-html5") {
 666                 @Override
 667                 public boolean process(String opt,  List<String> args) {
 668                     htmlVersion = HtmlVersion.HTML5;
 669                     return true;
 670                 }
 671             },
 672             new Option(resources, "-nohelp") {
 673                 @Override
 674                 public boolean process(String opt, List<String> args) {
 675                     nohelp = true;
 676                     if (!helpfile.isEmpty()) {
 677                         reporter.print(ERROR, getText("doclet.Option_conflict",
 678                                 "-nohelp", "-helpfile"));
 679                         return false;
 680                     }
 681                     return true;
 682                 }
 683             },
 684             new Option(resources, "-nodeprecatedlist") {
 685                 @Override
 686                 public boolean process(String opt,  List<String> args) {
 687                     nodeprecatedlist = true;
 688                     return true;
 689                 }
 690             },
 691             new Option(resources, "-noindex") {
 692                 @Override
 693                 public boolean process(String opt,  List<String> args) {
 694                     createindex = false;
 695                     if (splitindex == true) {
 696                         reporter.print(ERROR, getText("doclet.Option_conflict",
 697                                 "-noindex", "-splitindex"));
 698                         return false;
 699                     }
 700                     return true;
 701                 }
 702             },
 703             new Option(resources, "-nonavbar") {
 704                 @Override
 705                 public boolean process(String opt,  List<String> args) {
 706                     nonavbar = true;
 707                     return true;
 708                 }
 709             },
 710             new Hidden(resources, "-nooverview") {
 711                 @Override
 712                 public boolean process(String opt,  List<String> args) {
 713                     nooverview = true;
 714                     if (overviewpath != null) {
 715                         reporter.print(ERROR, getText("doclet.Option_conflict",
 716                                 "-nooverview", "-overview"));
 717                         return false;
 718                     }
 719                     return true;
 720                 }
 721             },
 722             new Option(resources, "-notree") {
 723                 @Override
 724                 public boolean process(String opt,  List<String> args) {
 725                     createtree = false;
 726                     return true;
 727                 }
 728             },
 729             new Option(resources, "-overview", 1) {
 730                 @Override
 731                 public boolean process(String opt,  List<String> args) {
 732                     overviewpath = args.get(0);
 733                     if (nooverview == true) {
 734                         reporter.print(ERROR, getText("doclet.Option_conflict",
 735                                 "-overview", "-nooverview"));
 736                         return false;
 737                     }
 738                     return true;
 739                 }
 740             },
 741             new Option(resources, "--frames") {
 742                 @Override
 743                 public boolean process(String opt,  List<String> args) {
 744                     frames = true;
 745                     return true;
 746                 }
 747             },
 748             new Option(resources, "--no-frames") {
 749                 @Override
 750                 public boolean process(String opt,  List<String> args) {
 751                     frames = false;
 752                     return true;
 753                 }
 754             },
 755             new Hidden(resources, "-packagesheader", 1) {
 756                 @Override
 757                 public boolean process(String opt,  List<String> args) {
 758                     packagesheader = args.get(0);
 759                     return true;
 760                 }
 761             },
 762             new Option(resources, "-splitindex") {
 763                 @Override
 764                 public boolean process(String opt, List<String> args) {
 765                     splitindex = true;
 766                     if (createindex == false) {
 767                         reporter.print(ERROR, getText("doclet.Option_conflict",
 768                                 "-splitindex", "-noindex"));
 769                         return false;
 770                     }
 771                     return true;
 772                 }
 773             },
 774             new Option(resources, "--main-stylesheet -stylesheetfile", 1) {
 775                 @Override
 776                 public boolean process(String opt,  List<String> args) {
 777                     stylesheetfile = args.get(0);
 778                     return true;
 779                 }
 780             },
 781             new Option(resources, "-top", 1) {
 782                 @Override
 783                 public boolean process(String opt,  List<String> args) {
 784                     top = args.get(0);
 785                     return true;
 786                 }
 787             },
 788             new Option(resources, "-use") {
 789                 @Override
 790                 public boolean process(String opt,  List<String> args) {
 791                     classuse = true;
 792                     return true;
 793                 }
 794             },
 795             new Option(resources, "-windowtitle", 1) {
 796                 @Override
 797                 public boolean process(String opt,  List<String> args) {
 798                     windowtitle = args.get(0).replaceAll("\\<.*?>", "");
 799                     return true;
 800                 }
 801             },
 802             new XOption(resources, "-Xdoclint") {
 803                 @Override
 804                 public boolean process(String opt,  List<String> args) {
 805                     doclintOpts.put(this, DocLint.XMSGS_OPTION);
 806                     return true;
 807                 }
 808             },
 809             new XOption(resources, "-Xdocrootparent", 1) {
 810                 @Override
 811                 public boolean process(String opt, List<String> args) {
 812                     docrootparent = args.get(0);
 813                     try {
 814                         URL ignored = new URL(docrootparent);
 815                     } catch (MalformedURLException e) {
 816                         reporter.print(ERROR, getText("doclet.MalformedURL", docrootparent));
 817                         return false;
 818                     }
 819                     return true;
 820                 }
 821             },
 822             new XOption(resources, "doclet.usage.xdoclint-extended", "-Xdoclint:", 0) {
 823                 @Override
 824                 public boolean process(String opt,  List<String> args) {
 825                     String dopt = opt.replace("-Xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX);
 826                     doclintOpts.put(this, dopt);
 827                     if (dopt.contains("/")) {
 828                         reporter.print(ERROR, getText("doclet.Option_doclint_no_qualifiers"));
 829                         return false;
 830                     }
 831                     if (!DocLint.isValidOption(dopt)) {
 832                         reporter.print(ERROR, getText("doclet.Option_doclint_invalid_arg"));
 833                         return false;
 834                     }
 835                     return true;
 836                 }
 837             },
 838             new XOption(resources, "doclet.usage.xdoclint-package", "-Xdoclint/package:", 0) {
 839                 @Override
 840                 public boolean process(String opt,  List<String> args) {
 841                     String dopt = opt.replace("-Xdoclint/package:", DocLint.XCHECK_PACKAGE);
 842                     doclintOpts.put(this, dopt);
 843                     if (!DocLint.isValidOption(dopt)) {
 844                         reporter.print(ERROR, getText("doclet.Option_doclint_package_invalid_arg"));
 845                         return false;
 846                     }
 847                     return true;
 848                 }
 849             },
 850             new XOption(resources, "--no-module-directories") {
 851                 @Override
 852                 public boolean process(String option, List<String> args) {
 853                     useModuleDirectories = false;
 854                     return true;
 855                 }
 856             }
 857         };
 858         Set<Doclet.Option> oset = new TreeSet<>();
 859         oset.addAll(Arrays.asList(options));
 860         oset.addAll(super.getSupportedOptions());
 861         return oset;
 862     }
 863 
 864     @Override
 865     protected boolean finishOptionSettings0() throws DocletException {
 866         if (docencoding == null) {
 867             if (charset == null) {
 868                 docencoding = charset = (encoding == null) ? HtmlConstants.HTML_DEFAULT_CHARSET : encoding;
 869             } else {
 870                 docencoding = charset;
 871             }
 872         } else {
 873             if (charset == null) {
 874                 charset = docencoding;
 875             } else if (!charset.equals(docencoding)) {
 876                 reporter.print(ERROR, getText("doclet.Option_conflict", "-charset", "-docencoding"));
 877                 return false;
 878             }
 879         }
 880         return super.finishOptionSettings0();
 881     }
 882 }