< prev index next >

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java

Print this page




   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.toolkit.BaseConfiguration;
  45 import jdk.javadoc.internal.doclets.toolkit.DocletException;
  46 import jdk.javadoc.internal.doclets.toolkit.Messages;
  47 import jdk.javadoc.internal.doclets.toolkit.Resources;
  48 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
  49 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
  50 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  51 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  52 
  53 import static javax.tools.Diagnostic.Kind.*;
  54 
  55 /**
  56  * Configure the output based on the command line options.
  57  * <p>
  58  * Also determine the length of the command line option. For example,
  59  * for a option "-header" there will be a string argument associated, then the
  60  * the length of option "-header" is two. But for option "-nohelp" no argument
  61  * is needed so it's length is 1.
  62  * </p>
  63  * <p>
  64  * Also do the error checking on the options used. For example it is illegal to
  65  * use "-helpfile" option when already "-nohelp" option is used.
  66  * </p>
  67  *
  68  *  <p><b>This is NOT part of any supported API.
  69  *  If you write code that depends on this, you do so at your own risk.
  70  *  This code and its internal interfaces are subject to change or
  71  *  deletion without notice.</b>
  72  */
  73 public class HtmlConfiguration extends BaseConfiguration {
  74 
  75     /**
  76      * Default charset for HTML.
  77      */
  78     public static final String HTML_DEFAULT_CHARSET = "utf-8";
  79 
  80     /**
  81      * Argument for command line option "-header".
  82      */
  83     public String header = "";
  84 
  85     /**
  86      * Argument for command line option "-packagesheader".
  87      */
  88     public String packagesheader = "";
  89 
  90     /**
  91      * Argument for command line option "-footer".
  92      */
  93     public String footer = "";
  94 
  95     /**
  96      * Argument for command line option "-doctitle".
  97      */
  98     public String doctitle = "";
  99 
 100     /**
 101      * Argument for command line option "-windowtitle".
 102      */
 103     public String windowtitle = "";
 104 
 105     /**
 106      * Argument for command line option "-top".
 107      */
 108     public String top = "";
 109 
 110     /**
 111      * Argument for command line option "-bottom".
 112      */
 113     public String bottom = "";
 114 
 115     /**
 116      * Argument for command line option "-helpfile".
 117      */
 118     public String helpfile = "";
 119 
 120     /**
 121      * Argument for command line option "-stylesheetfile".
 122      */
 123     public String stylesheetfile = "";
 124 
 125     /**
 126      * Argument for command line option "--add-stylesheet".
 127      */
 128     public List<String> additionalStylesheets = new ArrayList<>();
 129 
 130     /**
 131      * Argument for command line option "-Xdocrootparent".
 132      */
 133     public String docrootparent = "";
 134 
 135     /**
 136      * True if command line option "-nohelp" is used. Default value is false.
 137      */
 138     public boolean nohelp = false;
 139 
 140     /**
 141      * True if command line option "-splitindex" is used. Default value is
 142      * false.
 143      */
 144     public boolean splitindex = false;
 145 
 146     /**
 147      * False if command line option "-noindex" is used. Default value is true.
 148      */
 149     public boolean createindex = true;
 150 
 151     /**
 152      * True if command line option "-use" is used. Default value is false.
 153      */
 154     public boolean classuse = false;
 155 
 156     /**
 157      * False if command line option "-notree" is used. Default value is true.
 158      */
 159     public boolean createtree = true;
 160 
 161     /**
 162      * The META charset tag used for cross-platform viewing.
 163      */
 164     public String charset = null;
 165 
 166     /**
 167      * True if command line option "-nodeprecated" is used. Default value is
 168      * false.
 169      */
 170     public boolean nodeprecatedlist = false;
 171 
 172     /**
 173      * True if command line option "-nonavbar" is used. Default value is false.
 174      */
 175     public boolean nonavbar = false;
 176 
 177     /**
 178      * True if command line option "-nooverview" is used. Default value is
 179      * false
 180      */
 181     private boolean nooverview = false;
 182 
 183     /**
 184      * The overview path specified with "-overview" flag.
 185      */
 186     public String overviewpath = null;
 187 
 188     /**
 189      * This is true if option "-overview" is used or option "-overview" is not
 190      * used and number of packages is more than one.
 191      */
 192     public boolean createoverview = false;
 193 
 194     /**
 195      * Collected set of doclint options
 196      */
 197     public Map<Doclet.Option, String> doclintOpts = new LinkedHashMap<>();
 198 
 199     public final Resources resources;
 200 
 201     /**
 202      * First file to appear in the right-hand frame in the generated
 203      * documentation.
 204      */
 205     public DocPath topFile = DocPath.empty;
 206 
 207     /**
 208      * The TypeElement for the class file getting generated.
 209      */
 210     public TypeElement currentTypeElement = null;  // Set this TypeElement in the ClassWriter.
 211 
 212     protected SortedSet<SearchIndexItem> memberSearchIndex;
 213 
 214     protected SortedSet<SearchIndexItem> moduleSearchIndex;
 215 
 216     protected SortedSet<SearchIndexItem> packageSearchIndex;
 217 
 218     protected SortedSet<SearchIndexItem> tagSearchIndex;
 219 
 220     protected SortedSet<SearchIndexItem> typeSearchIndex;
 221 
 222     protected Map<Character,List<SearchIndexItem>> tagSearchIndexMap = new HashMap<>();
 223 
 224     protected Set<Character> tagSearchIndexKeys;
 225 
 226     public final Contents contents;
 227 
 228     protected final Messages messages;
 229 
 230     public DocPaths docPaths;
 231 
 232     public Map<Element, List<DocPath>> localStylesheetMap = new HashMap<>();
 233 


 234     /**
 235      * Creates an object to hold the configuration for a doclet.
 236      *
 237      * @param doclet the doclet
 238      */
 239     public HtmlConfiguration(Doclet doclet) {
 240         super(doclet);
 241         resources = new Resources(this,
 242                 BaseConfiguration.sharedResourceBundleName,
 243                 "jdk.javadoc.internal.doclets.formats.html.resources.standard");
 244 
 245         messages = new Messages(this);
 246         contents = new Contents(this);

 247 
 248         String v;
 249         try {
 250             ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, getLocale());
 251             try {
 252                 v = rb.getString("release");
 253             } catch (MissingResourceException e) {
 254                 v = defaultDocletVersion;
 255             }
 256         } catch (MissingResourceException e) {
 257             v = defaultDocletVersion;
 258         }
 259         docletVersion = v;
 260     }
 261 
 262     private static final String versionBundleName = "jdk.javadoc.internal.tool.resources.version";
 263     private static final String defaultDocletVersion = System.getProperty("java.version");
 264     public final String docletVersion;
 265     public final Date startTime = new Date();
 266 
 267     @Override
 268     public String getDocletVersion() {
 269         return docletVersion;
 270     }
 271 
 272     @Override
 273     public Resources getResources() {
 274         return resources;
 275     }
 276 
 277     public Contents getContents() {
 278         return contents;
 279     }
 280 
 281     @Override
 282     public Messages getMessages() {
 283         return messages;
 284     }
 285 
 286     protected boolean validateOptions() {
 287         // check shared options
 288         if (!generalValidOptions()) {
 289             return false;
 290         }
 291 
 292         // check if helpfile exists
 293         if (!helpfile.isEmpty()) {
 294             DocFile help = DocFile.createFileForInput(this, helpfile);
 295             if (!help.exists()) {
 296                 reporter.print(ERROR, resources.getText("doclet.File_not_found", helpfile));
 297                 return false;
 298             }
 299         }
 300         // check if stylesheetfile exists
 301         if (!stylesheetfile.isEmpty()) {
 302             DocFile stylesheet = DocFile.createFileForInput(this, stylesheetfile);
 303             if (!stylesheet.exists()) {
 304                 reporter.print(ERROR, resources.getText("doclet.File_not_found", stylesheetfile));
 305                 return false;
 306             }
 307         }
 308         // check if additional stylesheets exists
 309         for (String ssheet : additionalStylesheets) {
 310             DocFile ssfile = DocFile.createFileForInput(this, ssheet);
 311             if (!ssfile.exists()) {
 312                 reporter.print(ERROR, resources.getText("doclet.File_not_found", ssheet));
 313                 return false;
 314             }
 315         }
 316 
 317         // In a more object-oriented world, this would be done by methods on the Option objects.
 318         // Note that -windowtitle silently removes any and all HTML elements, and so does not need
 319         // to be handled here.
 320         utils.checkJavaScriptInOption("-header", header);
 321         utils.checkJavaScriptInOption("-footer", footer);
 322         utils.checkJavaScriptInOption("-top", top);
 323         utils.checkJavaScriptInOption("-bottom", bottom);
 324         utils.checkJavaScriptInOption("-doctitle", doctitle);
 325         utils.checkJavaScriptInOption("-packagesheader", packagesheader);
 326 
 327         return true;
 328     }
 329 
 330 
 331     @Override
 332     public boolean finishOptionSettings() {
 333         if (!validateOptions()) {
 334             return false;
 335         }
 336         if (!getSpecifiedTypeElements().isEmpty()) {
 337             Map<String, PackageElement> map = new HashMap<>();
 338             PackageElement pkg;
 339             for (TypeElement aClass : getIncludedTypeElements()) {
 340                 pkg = utils.containingPackage(aClass);
 341                 if (!map.containsKey(utils.getPackageName(pkg))) {
 342                     map.put(utils.getPackageName(pkg), pkg);
 343                 }
 344             }
 345         }
 346         docPaths = new DocPaths(utils);
 347         setCreateOverview();
 348         setTopFile(docEnv);
 349         workArounds.initDocLint(doclintOpts.values(), tagletManager.getAllTagletNames());
 350         return true;
 351     }
 352 
 353     /**
 354      * Decide the page which will appear first in the right-hand frame. It will
 355      * be "overview-summary.html" if "-overview" option is used or no
 356      * "-overview" but the number of packages is more than one. It will be
 357      * "package-summary.html" of the respective package if there is only one
 358      * package to document. It will be a class page(first in the sorted order),
 359      * if only classes are provided on the command line.
 360      *
 361      * @param docEnv the doclet environment
 362      */
 363     protected void setTopFile(DocletEnvironment docEnv) {
 364         if (!checkForDeprecation(docEnv)) {
 365             return;
 366         }
 367         if (createoverview) {
 368             topFile = DocPaths.INDEX;
 369         } else {
 370             if (showModules) {
 371                 topFile = DocPath.empty.resolve(docPaths.moduleSummary(modules.first()));
 372             } else if (packages.size() == 1 && packages.first().isUnnamed()) {
 373                 List<TypeElement> classes = new ArrayList<>(getIncludedTypeElements());
 374                 if (!classes.isEmpty()) {
 375                     TypeElement te = getValidClass(classes);
 376                     topFile = docPaths.forClass(te);
 377                 }
 378             } else if (!packages.isEmpty()) {
 379                 topFile = docPaths.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY);
 380             }
 381         }
 382     }
 383 
 384     protected TypeElement getValidClass(List<TypeElement> classes) {
 385         if (!nodeprecated) {
 386             return classes.get(0);
 387         }
 388         for (TypeElement te : classes) {
 389             if (!utils.isDeprecated(te)) {
 390                 return te;
 391             }
 392         }
 393         return null;
 394     }
 395 
 396     protected boolean checkForDeprecation(DocletEnvironment docEnv) {
 397         for (TypeElement te : getIncludedTypeElements()) {
 398             if (isGeneratedDoc(te)) {
 399                 return true;
 400             }
 401         }
 402         return false;
 403     }
 404 
 405     /**
 406      * Generate "overview.html" page if option "-overview" is used or number of
 407      * packages is more than one. Sets {@link #createoverview} field to true.
 408      */
 409     protected void setCreateOverview() {
 410         if (!nooverview) {
 411             if (overviewpath != null
 412                     || modules.size() > 1
 413                     || (modules.isEmpty() && packages.size() > 1)) {
 414                 createoverview = true;
 415             }
 416         }
 417     }
 418 
 419     /**
 420      * {@inheritDoc}
 421      */
 422     @Override
 423     public WriterFactory getWriterFactory() {
 424         return new WriterFactoryImpl(this);
 425     }
 426 
 427     /**
 428      * {@inheritDoc}
 429      */
 430     @Override
 431     public Locale getLocale() {
 432         if (locale == null)
 433             return Locale.getDefault();
 434         return locale;
 435     }
 436 
 437     /**
 438      * Return the path of the overview file or null if it does not exist.
 439      *
 440      * @return the path of the overview file or null if it does not exist.
 441      */
 442     @Override
 443     public JavaFileObject getOverviewPath() {

 444         if (overviewpath != null && getFileManager() instanceof StandardJavaFileManager) {
 445             StandardJavaFileManager fm = (StandardJavaFileManager) getFileManager();
 446             return fm.getJavaFileObjects(overviewpath).iterator().next();
 447         }
 448         return null;
 449     }
 450 
 451     public DocPath getMainStylesheet() {

 452         if(!stylesheetfile.isEmpty()){
 453             DocFile docFile = DocFile.createFileForInput(this, stylesheetfile);
 454             return DocPath.create(docFile.getName());
 455         }
 456         return  null;
 457     }
 458 
 459     public List<DocPath> getAdditionalStylesheets() {
 460         return additionalStylesheets.stream()
 461                 .map(ssf -> DocFile.createFileForInput(this, ssf)).map(file -> DocPath.create(file.getName()))
 462                 .collect(Collectors.toList());
 463     }
 464 
 465     /**
 466      * {@inheritDoc}
 467      */
 468     @Override
 469     public JavaFileManager getFileManager() {
 470         return docEnv.getJavaFileManager();
 471     }
 472 
 473     @Override
 474     public boolean showMessage(DocTreePath path, String key) {
 475         return (path == null || workArounds.haveDocLint());
 476     }
 477 
 478     @Override
 479     public boolean showMessage(Element e, String key) {
 480         return (e == null || workArounds.haveDocLint());
 481     }
 482 
 483     protected void buildSearchTagIndex() {
 484         for (SearchIndexItem sii : tagSearchIndex) {
 485             String tagLabel = sii.getLabel();
 486             Character unicode = (tagLabel.length() == 0)
 487                     ? '*'
 488                     : Character.toUpperCase(tagLabel.charAt(0));
 489             List<SearchIndexItem> list = tagSearchIndexMap.get(unicode);
 490             if (list == null) {
 491                 list = new ArrayList<>();
 492                 tagSearchIndexMap.put(unicode, list);
 493             }
 494             list.add(sii);
 495         }
 496         tagSearchIndexKeys = tagSearchIndexMap.keySet();
 497     }
 498 
 499     @Override
 500     public Set<Doclet.Option> getSupportedOptions() {
 501         Resources resources = getResources();
 502         Doclet.Option[] options = {
 503             new Option(resources, "--add-stylesheet", 1) {
 504                 @Override
 505                 public boolean process(String opt, List<String> args) {
 506                     additionalStylesheets.add(args.get(0));
 507                     return true;
 508                 }
 509             },
 510             new Option(resources, "-bottom", 1) {
 511                 @Override
 512                 public boolean process(String opt,  List<String> args) {
 513                     bottom = args.get(0);
 514                     return true;
 515                 }
 516             },
 517             new Option(resources, "-charset", 1) {
 518                 @Override
 519                 public boolean process(String opt,  List<String> args) {
 520                     charset = args.get(0);
 521                     return true;
 522                 }
 523             },
 524             new Option(resources, "-doctitle", 1) {
 525                 @Override
 526                 public boolean process(String opt,  List<String> args) {
 527                     doctitle = args.get(0);
 528                     return true;
 529                 }
 530             },
 531             new Option(resources, "-footer", 1) {
 532                 @Override
 533                 public boolean process(String opt, List<String> args) {
 534                     footer = args.get(0);
 535                     return true;
 536                 }
 537             },
 538             new Option(resources, "-header", 1) {
 539                 @Override
 540                 public boolean process(String opt,  List<String> args) {
 541                     header = args.get(0);
 542                     return true;
 543                 }
 544             },
 545             new Option(resources, "-helpfile", 1) {
 546                 @Override
 547                 public boolean process(String opt,  List<String> args) {
 548                     if (nohelp == true) {
 549                         reporter.print(ERROR, resources.getText("doclet.Option_conflict",
 550                                 "-helpfile", "-nohelp"));
 551                         return false;
 552                     }
 553                     if (!helpfile.isEmpty()) {
 554                         reporter.print(ERROR, resources.getText("doclet.Option_reuse",
 555                                 "-helpfile"));
 556                         return false;
 557                     }
 558                     helpfile = args.get(0);
 559                     return true;
 560                 }
 561             },
 562             new Option(resources, "-html5") {
 563                 @Override
 564                 public boolean process(String opt,  List<String> args) {
 565                     return true;
 566                 }
 567             },
 568             new Option(resources, "-nohelp") {
 569                 @Override
 570                 public boolean process(String opt, List<String> args) {
 571                     nohelp = true;
 572                     if (!helpfile.isEmpty()) {
 573                         reporter.print(ERROR, resources.getText("doclet.Option_conflict",
 574                                 "-nohelp", "-helpfile"));
 575                         return false;
 576                     }
 577                     return true;
 578                 }
 579             },
 580             new Option(resources, "-nodeprecatedlist") {
 581                 @Override
 582                 public boolean process(String opt,  List<String> args) {
 583                     nodeprecatedlist = true;
 584                     return true;
 585                 }
 586             },
 587             new Option(resources, "-noindex") {
 588                 @Override
 589                 public boolean process(String opt,  List<String> args) {
 590                     createindex = false;
 591                     if (splitindex == true) {
 592                         reporter.print(ERROR, resources.getText("doclet.Option_conflict",
 593                                 "-noindex", "-splitindex"));
 594                         return false;
 595                     }
 596                     return true;
 597                 }
 598             },
 599             new Option(resources, "-nonavbar") {
 600                 @Override
 601                 public boolean process(String opt,  List<String> args) {
 602                     nonavbar = true;
 603                     return true;
 604                 }
 605             },
 606             new Hidden(resources, "-nooverview") {
 607                 @Override
 608                 public boolean process(String opt,  List<String> args) {
 609                     nooverview = true;
 610                     if (overviewpath != null) {
 611                         reporter.print(ERROR, resources.getText("doclet.Option_conflict",
 612                                 "-nooverview", "-overview"));
 613                         return false;
 614                     }
 615                     return true;
 616                 }
 617             },
 618             new Option(resources, "-notree") {
 619                 @Override
 620                 public boolean process(String opt,  List<String> args) {
 621                     createtree = false;
 622                     return true;
 623                 }
 624             },
 625             new Option(resources, "-overview", 1) {
 626                 @Override
 627                 public boolean process(String opt,  List<String> args) {
 628                     overviewpath = args.get(0);
 629                     if (nooverview == true) {
 630                         reporter.print(ERROR, resources.getText("doclet.Option_conflict",
 631                                 "-overview", "-nooverview"));
 632                         return false;
 633                     }
 634                     return true;
 635                 }
 636             },
 637             new Hidden(resources, "-packagesheader", 1) {
 638                 @Override
 639                 public boolean process(String opt,  List<String> args) {
 640                     packagesheader = args.get(0);
 641                     return true;
 642                 }
 643             },
 644             new Option(resources, "-splitindex") {
 645                 @Override
 646                 public boolean process(String opt, List<String> args) {
 647                     splitindex = true;
 648                     if (createindex == false) {
 649                         reporter.print(ERROR, resources.getText("doclet.Option_conflict",
 650                                 "-splitindex", "-noindex"));
 651                         return false;
 652                     }
 653                     return true;
 654                 }
 655             },
 656             new Option(resources, "--main-stylesheet -stylesheetfile", 1) {
 657                 @Override
 658                 public boolean process(String opt,  List<String> args) {
 659                     stylesheetfile = args.get(0);
 660                     return true;
 661                 }
 662             },
 663             new Option(resources, "-top", 1) {
 664                 @Override
 665                 public boolean process(String opt,  List<String> args) {
 666                     top = args.get(0);
 667                     return true;
 668                 }
 669             },
 670             new Option(resources, "-use") {
 671                 @Override
 672                 public boolean process(String opt,  List<String> args) {
 673                     classuse = true;
 674                     return true;
 675                 }
 676             },
 677             new Option(resources, "-windowtitle", 1) {
 678                 @Override
 679                 public boolean process(String opt,  List<String> args) {
 680                     windowtitle = args.get(0).replaceAll("\\<.*?>", "");
 681                     return true;
 682                 }
 683             },
 684             new XOption(resources, "-Xdoclint") {
 685                 @Override
 686                 public boolean process(String opt,  List<String> args) {
 687                     doclintOpts.put(this, DocLint.XMSGS_OPTION);
 688                     return true;
 689                 }
 690             },
 691             new XOption(resources, "-Xdocrootparent", 1) {
 692                 @Override
 693                 public boolean process(String opt, List<String> args) {
 694                     docrootparent = args.get(0);
 695                     try {
 696                         URL ignored = new URL(docrootparent);
 697                     } catch (MalformedURLException e) {
 698                         reporter.print(ERROR, resources.getText("doclet.MalformedURL", docrootparent));
 699                         return false;
 700                     }
 701                     return true;
 702                 }
 703             },
 704             new XOption(resources, "doclet.usage.xdoclint-extended", "-Xdoclint:", 0) {
 705                 @Override
 706                 public boolean process(String opt,  List<String> args) {
 707                     String dopt = opt.replace("-Xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX);
 708                     doclintOpts.put(this, dopt);
 709                     if (dopt.contains("/")) {
 710                         reporter.print(ERROR, resources.getText("doclet.Option_doclint_no_qualifiers"));
 711                         return false;
 712                     }
 713                     if (!DocLint.isValidOption(dopt)) {
 714                         reporter.print(ERROR, resources.getText("doclet.Option_doclint_invalid_arg"));
 715                         return false;
 716                     }
 717                     return true;
 718                 }
 719             },
 720             new XOption(resources, "doclet.usage.xdoclint-package", "-Xdoclint/package:", 0) {
 721                 @Override
 722                 public boolean process(String opt,  List<String> args) {
 723                     String dopt = opt.replace("-Xdoclint/package:", DocLint.XCHECK_PACKAGE);
 724                     doclintOpts.put(this, dopt);
 725                     if (!DocLint.isValidOption(dopt)) {
 726                         reporter.print(ERROR, resources.getText("doclet.Option_doclint_package_invalid_arg"));
 727                         return false;
 728                     }
 729                     return true;
 730                 }
 731             },
 732             new XOption(resources, "--no-frames") {
 733                 @Override
 734                 public boolean process(String opt, List<String> args) {
 735                     reporter.print(WARNING, resources.getText("doclet.NoFrames_specified"));
 736                     return true;
 737                 }
 738             }
 739         };
 740         Set<Doclet.Option> oset = new TreeSet<>();
 741         oset.addAll(Arrays.asList(options));
 742         oset.addAll(super.getSupportedOptions());
 743         return oset;
 744     }
 745 
 746     @Override
 747     protected boolean finishOptionSettings0() throws DocletException {
 748         if (docencoding == null) {
 749             if (charset == null) {
 750                 docencoding = charset = (encoding == null) ? HTML_DEFAULT_CHARSET : encoding;
 751             } else {
 752                 docencoding = charset;
 753             }
 754         } else {
 755             if (charset == null) {
 756                 charset = docencoding;
 757             } else if (!charset.equals(docencoding)) {
 758                 reporter.print(ERROR, resources.getText("doclet.Option_conflict", "-charset", "-docencoding"));
 759                 return false;
 760             }
 761         }
 762         return super.finishOptionSettings0();
 763     }
 764 
 765     @Override
 766     protected void initConfiguration(DocletEnvironment docEnv) {
 767         super.initConfiguration(docEnv);
 768         memberSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 769         moduleSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 770         packageSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 771         tagSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 772         typeSearchIndex = new TreeSet<>(utils.makeTypeSearchIndexComparator());
 773     }
 774 }


   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.util.*;
  29 import java.util.stream.Collectors;
  30 
  31 import javax.lang.model.element.Element;
  32 import javax.lang.model.element.PackageElement;
  33 import javax.lang.model.element.TypeElement;
  34 import javax.tools.JavaFileManager;
  35 import javax.tools.JavaFileObject;
  36 import javax.tools.StandardJavaFileManager;
  37 
  38 import com.sun.source.util.DocTreePath;

  39 
  40 import jdk.javadoc.doclet.Doclet;
  41 import jdk.javadoc.doclet.DocletEnvironment;
  42 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
  43 import jdk.javadoc.internal.doclets.toolkit.DocletException;
  44 import jdk.javadoc.internal.doclets.toolkit.Messages;
  45 import jdk.javadoc.internal.doclets.toolkit.Resources;
  46 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
  47 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
  48 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  49 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  50 
  51 import static javax.tools.Diagnostic.Kind.*;
  52 
  53 /**
  54  * Configure the output based on the command line options.
  55  * <p>
  56  * Also determine the length of the command line option. For example,
  57  * for a option "-header" there will be a string argument associated, then the
  58  * the length of option "-header" is two. But for option "-nohelp" no argument
  59  * is needed so it's length is 1.
  60  * </p>
  61  * <p>
  62  * Also do the error checking on the options used. For example it is illegal to
  63  * use "-helpfile" option when already "-nohelp" option is used.
  64  * </p>
  65  *
  66  *  <p><b>This is NOT part of any supported API.
  67  *  If you write code that depends on this, you do so at your own risk.
  68  *  This code and its internal interfaces are subject to change or
  69  *  deletion without notice.</b>
  70  */
  71 public class HtmlConfiguration extends BaseConfiguration {
  72 
  73     /**
  74      * Default charset for HTML.
  75      */
  76     public static final String HTML_DEFAULT_CHARSET = "utf-8";
  77 























































































































  78     public final Resources resources;
  79 
  80     /**
  81      * First file to appear in the right-hand frame in the generated
  82      * documentation.
  83      */
  84     public DocPath topFile = DocPath.empty;
  85 
  86     /**
  87      * The TypeElement for the class file getting generated.
  88      */
  89     public TypeElement currentTypeElement = null;  // Set this TypeElement in the ClassWriter.
  90 
  91     protected SortedSet<SearchIndexItem> memberSearchIndex;
  92 
  93     protected SortedSet<SearchIndexItem> moduleSearchIndex;
  94 
  95     protected SortedSet<SearchIndexItem> packageSearchIndex;
  96 
  97     protected SortedSet<SearchIndexItem> tagSearchIndex;
  98 
  99     protected SortedSet<SearchIndexItem> typeSearchIndex;
 100 
 101     protected Map<Character,List<SearchIndexItem>> tagSearchIndexMap = new HashMap<>();
 102 
 103     protected Set<Character> tagSearchIndexKeys;
 104 
 105     public final Contents contents;
 106 
 107     protected final Messages messages;
 108 
 109     public DocPaths docPaths;
 110 
 111     public Map<Element, List<DocPath>> localStylesheetMap = new HashMap<>();
 112 
 113     private final HtmlOptions options;
 114 
 115     /**
 116      * Creates an object to hold the configuration for a doclet.
 117      *
 118      * @param doclet the doclet
 119      */
 120     public HtmlConfiguration(Doclet doclet) {
 121         super(doclet);
 122         resources = new Resources(this,
 123                 BaseConfiguration.sharedResourceBundleName,
 124                 "jdk.javadoc.internal.doclets.formats.html.resources.standard");
 125 
 126         messages = new Messages(this);
 127         contents = new Contents(this);
 128         options = new HtmlOptions(this);
 129 
 130         String v;
 131         try {
 132             ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, getLocale());
 133             try {
 134                 v = rb.getString("release");
 135             } catch (MissingResourceException e) {
 136                 v = defaultDocletVersion;
 137             }
 138         } catch (MissingResourceException e) {
 139             v = defaultDocletVersion;
 140         }
 141         docletVersion = v;
 142     }
 143 
 144     private static final String versionBundleName = "jdk.javadoc.internal.tool.resources.version";
 145     private static final String defaultDocletVersion = System.getProperty("java.version");
 146     public final String docletVersion;
 147     public final Date startTime = new Date();
 148 
 149     @Override
 150     public String getDocletVersion() {
 151         return docletVersion;
 152     }
 153 
 154     @Override
 155     public Resources getResources() {
 156         return resources;
 157     }
 158 
 159     public Contents getContents() {
 160         return contents;
 161     }
 162 
 163     @Override
 164     public Messages getMessages() {
 165         return messages;
 166     }
 167 
 168     @Override
 169     public HtmlOptions getOptions() {
 170         if (options == null) Thread.dumpStack();
 171         return options;






































 172     }
 173 

 174     @Override
 175     public boolean finishOptionSettings() {
 176         if (!options.validateOptions()) {
 177             return false;
 178         }
 179         if (!getSpecifiedTypeElements().isEmpty()) {
 180             Map<String, PackageElement> map = new HashMap<>();
 181             PackageElement pkg;
 182             for (TypeElement aClass : getIncludedTypeElements()) {
 183                 pkg = utils.containingPackage(aClass);
 184                 if (!map.containsKey(utils.getPackageName(pkg))) {
 185                     map.put(utils.getPackageName(pkg), pkg);
 186                 }
 187             }
 188         }
 189         docPaths = new DocPaths(utils);
 190         setCreateOverview();
 191         setTopFile(docEnv);
 192         workArounds.initDocLint(options.doclintOpts.values(), tagletManager.getAllTagletNames());
 193         return true;
 194     }
 195 
 196     /**
 197      * Decide the page which will appear first in the right-hand frame. It will
 198      * be "overview-summary.html" if "-overview" option is used or no
 199      * "-overview" but the number of packages is more than one. It will be
 200      * "package-summary.html" of the respective package if there is only one
 201      * package to document. It will be a class page(first in the sorted order),
 202      * if only classes are provided on the command line.
 203      *
 204      * @param docEnv the doclet environment
 205      */
 206     protected void setTopFile(DocletEnvironment docEnv) {
 207         if (!checkForDeprecation(docEnv)) {
 208             return;
 209         }
 210         if (options.createOverview) {
 211             topFile = DocPaths.INDEX;
 212         } else {
 213             if (showModules) {
 214                 topFile = DocPath.empty.resolve(docPaths.moduleSummary(modules.first()));
 215             } else if (packages.size() == 1 && packages.first().isUnnamed()) {
 216                 List<TypeElement> classes = new ArrayList<>(getIncludedTypeElements());
 217                 if (!classes.isEmpty()) {
 218                     TypeElement te = getValidClass(classes);
 219                     topFile = docPaths.forClass(te);
 220                 }
 221             } else if (!packages.isEmpty()) {
 222                 topFile = docPaths.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY);
 223             }
 224         }
 225     }
 226 
 227     protected TypeElement getValidClass(List<TypeElement> classes) {
 228         if (!options.noDeprecated) {
 229             return classes.get(0);
 230         }
 231         for (TypeElement te : classes) {
 232             if (!utils.isDeprecated(te)) {
 233                 return te;
 234             }
 235         }
 236         return null;
 237     }
 238 
 239     protected boolean checkForDeprecation(DocletEnvironment docEnv) {
 240         for (TypeElement te : getIncludedTypeElements()) {
 241             if (isGeneratedDoc(te)) {
 242                 return true;
 243             }
 244         }
 245         return false;
 246     }
 247 
 248     /**
 249      * Generate "overview.html" page if option "-overview" is used or number of
 250      * packages is more than one. Sets {@link HtmlOptions#createOverview} field to true.
 251      */
 252     protected void setCreateOverview() {
 253         if (!options.noOverview) {
 254             if (options.overviewPath != null
 255                     || modules.size() > 1
 256                     || (modules.isEmpty() && packages.size() > 1)) {
 257                 options.createOverview = true;
 258             }
 259         }
 260     }
 261 
 262     /**
 263      * {@inheritDoc}
 264      */
 265     @Override
 266     public WriterFactory getWriterFactory() {
 267         return new WriterFactoryImpl(this);
 268     }
 269 
 270     /**
 271      * {@inheritDoc}
 272      */
 273     @Override
 274     public Locale getLocale() {
 275         if (locale == null)
 276             return Locale.getDefault();
 277         return locale;
 278     }
 279 
 280     /**
 281      * Return the path of the overview file or null if it does not exist.
 282      *
 283      * @return the path of the overview file or null if it does not exist.
 284      */
 285     @Override
 286     public JavaFileObject getOverviewPath() {
 287         String overviewpath = options.overviewPath;
 288         if (overviewpath != null && getFileManager() instanceof StandardJavaFileManager) {
 289             StandardJavaFileManager fm = (StandardJavaFileManager) getFileManager();
 290             return fm.getJavaFileObjects(overviewpath).iterator().next();
 291         }
 292         return null;
 293     }
 294 
 295     public DocPath getMainStylesheet() {
 296         String stylesheetfile = options.stylesheetFile;
 297         if(!stylesheetfile.isEmpty()){
 298             DocFile docFile = DocFile.createFileForInput(this, stylesheetfile);
 299             return DocPath.create(docFile.getName());
 300         }
 301         return  null;
 302     }
 303 
 304     public List<DocPath> getAdditionalStylesheets() {
 305         return options.additionalStylesheets.stream()
 306                 .map(ssf -> DocFile.createFileForInput(this, ssf)).map(file -> DocPath.create(file.getName()))
 307                 .collect(Collectors.toList());
 308     }
 309 
 310     /**
 311      * {@inheritDoc}
 312      */
 313     @Override
 314     public JavaFileManager getFileManager() {
 315         return docEnv.getJavaFileManager();
 316     }
 317 
 318     @Override
 319     public boolean showMessage(DocTreePath path, String key) {
 320         return (path == null || workArounds.haveDocLint());
 321     }
 322 
 323     @Override
 324     public boolean showMessage(Element e, String key) {
 325         return (e == null || workArounds.haveDocLint());
 326     }
 327 
 328     protected void buildSearchTagIndex() {
 329         for (SearchIndexItem sii : tagSearchIndex) {
 330             String tagLabel = sii.getLabel();
 331             Character unicode = (tagLabel.length() == 0)
 332                     ? '*'
 333                     : Character.toUpperCase(tagLabel.charAt(0));
 334             List<SearchIndexItem> list = tagSearchIndexMap.get(unicode);
 335             if (list == null) {
 336                 list = new ArrayList<>();
 337                 tagSearchIndexMap.put(unicode, list);
 338             }
 339             list.add(sii);
 340         }
 341         tagSearchIndexKeys = tagSearchIndexMap.keySet();
 342     }
 343 
 344     @Override























































































































































































































































 345     protected boolean finishOptionSettings0() throws DocletException {
 346         if (options.docEncoding == null) {
 347             if (options.charset == null) {
 348                 options.docEncoding = options.charset = (options.encoding == null) ? HTML_DEFAULT_CHARSET : options.encoding;
 349             } else {
 350                 options.docEncoding = options.charset;
 351             }
 352         } else {
 353             if (options.charset == null) {
 354                 options.charset = options.docEncoding;
 355             } else if (!options.charset.equals(options.docEncoding)) {
 356                 reporter.print(ERROR, resources.getText("doclet.Option_conflict", "-charset", "-docencoding"));
 357                 return false;
 358             }
 359         }
 360         return super.finishOptionSettings0();
 361     }
 362 
 363     @Override
 364     protected void initConfiguration(DocletEnvironment docEnv) {
 365         super.initConfiguration(docEnv);
 366         memberSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 367         moduleSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 368         packageSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 369         tagSearchIndex = new TreeSet<>(utils.makeGenericSearchIndexComparator());
 370         typeSearchIndex = new TreeSet<>(utils.makeTypeSearchIndexComparator());
 371     }
 372 }
< prev index next >