langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java
changeset 35426 374342e56a56
parent 33920 bd731341c405
child 36526 3b41f1c69604
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConfigurationImpl.java	Sat Nov 28 18:52:17 2015 -0800
@@ -0,0 +1,747 @@
+/*
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.javadoc.internal.doclets.formats.html;
+
+import java.net.*;
+import java.util.*;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.source.util.DocTreePath;
+import com.sun.tools.doclint.DocLint;
+
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlVersion;
+import jdk.javadoc.internal.doclets.toolkit.Configuration;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.MessageRetriever;
+import jdk.javadoc.internal.doclets.toolkit.util.Utils;
+
+import static javax.tools.Diagnostic.Kind.*;
+
+/**
+ * Configure the output based on the command line options.
+ * <p>
+ * Also determine the length of the command line option. For example,
+ * for a option "-header" there will be a string argument associated, then the
+ * the length of option "-header" is two. But for option "-nohelp" no argument
+ * is needed so it's length is 1.
+ * </p>
+ * <p>
+ * Also do the error checking on the options used. For example it is illegal to
+ * use "-helpfile" option when already "-nohelp" option is used.
+ * </p>
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ *
+ * @author Robert Field.
+ * @author Atul Dambalkar.
+ * @author Jamie Ho
+ * @author Bhavesh Patel (Modified)
+ */
+public class ConfigurationImpl extends Configuration {
+
+    /**
+     * The build date.  Note: For now, we will use
+     * a version number instead of a date.
+     */
+    public static final String BUILD_DATE = System.getProperty("java.version");
+
+    /**
+     * Argument for command line option "-header".
+     */
+    public String header = "";
+
+    /**
+     * Argument for command line option "-packagesheader".
+     */
+    public String packagesheader = "";
+
+    /**
+     * Argument for command line option "-footer".
+     */
+    public String footer = "";
+
+    /**
+     * Argument for command line option "-doctitle".
+     */
+    public String doctitle = "";
+
+    /**
+     * Argument for command line option "-windowtitle".
+     */
+    public String windowtitle = "";
+
+    /**
+     * Argument for command line option "-top".
+     */
+    public String top = "";
+
+    /**
+     * Argument for command line option "-bottom".
+     */
+    public String bottom = "";
+
+    /**
+     * Argument for command line option "-helpfile".
+     */
+    public String helpfile = "";
+
+    /**
+     * Argument for command line option "-stylesheetfile".
+     */
+    public String stylesheetfile = "";
+
+    /**
+     * Argument for command line option "-Xdocrootparent".
+     */
+    public String docrootparent = "";
+
+    public boolean sortedMethodDetails = false;
+
+    /**
+     * True if command line option "-nohelp" is used. Default value is false.
+     */
+    public boolean nohelp = false;
+
+    /**
+     * True if command line option "-splitindex" is used. Default value is
+     * false.
+     */
+    public boolean splitindex = false;
+
+    /**
+     * False if command line option "-noindex" is used. Default value is true.
+     */
+    public boolean createindex = true;
+
+    /**
+     * True if command line option "-use" is used. Default value is false.
+     */
+    public boolean classuse = false;
+
+    /**
+     * False if command line option "-notree" is used. Default value is true.
+     */
+    public boolean createtree = true;
+
+    /**
+     * True if command line option "-nodeprecated" is used. Default value is
+     * false.
+     */
+    public boolean nodeprecatedlist = false;
+
+    /**
+     * True if command line option "-nonavbar" is used. Default value is false.
+     */
+    public boolean nonavbar = false;
+
+    /**
+     * True if command line option "-nooverview" is used. Default value is
+     * false
+     */
+    private boolean nooverview = false;
+
+    /**
+     * The overview path specified with "-overview" flag.
+     */
+    public String overviewpath = null;
+
+    /**
+     * This is true if option "-overview" is used or option "-overview" is not
+     * used and number of packages is more than one.
+     */
+    public boolean createoverview = false;
+
+    /**
+     * This is the HTML version of the generated pages. HTML 4.01 is the default output version.
+     */
+    public HtmlVersion htmlVersion = HtmlVersion.HTML4;
+
+    /**
+     * Collected set of doclint options
+     */
+    public Map<Doclet.Option, String> doclintOpts = new LinkedHashMap<>();
+
+    /**
+     * Unique Resource Handler for this package.
+     */
+    public final MessageRetriever standardmessage;
+
+    /**
+     * First file to appear in the right-hand frame in the generated
+     * documentation.
+     */
+    public DocPath topFile = DocPath.empty;
+
+    /**
+     * The TypeElement for the class file getting generated.
+     */
+    public TypeElement currentTypeElement = null;  // Set this TypeElement in the ClassWriter.
+
+    protected List<SearchIndexItem> memberSearchIndex = new ArrayList<>();
+
+    protected List<SearchIndexItem> packageSearchIndex = new ArrayList<>();
+
+    protected List<SearchIndexItem> tagSearchIndex = new ArrayList<>();
+
+    protected List<SearchIndexItem> typeSearchIndex = new ArrayList<>();
+
+    protected Map<Character,List<SearchIndexItem>> tagSearchIndexMap = new HashMap<>();
+
+    protected Set<Character> tagSearchIndexKeys;
+
+    /**
+     * Constructor. Initializes resource for the
+     * {@link com.sun.tools.doclets.internal.toolkit.util.MessageRetriever MessageRetriever}.
+     */
+    public ConfigurationImpl() {
+        standardmessage = new MessageRetriever(this,
+            "jdk.javadoc.internal.doclets.formats.html.resources.standard");
+    }
+
+    private final String versionRBName = "jdk.javadoc.internal.tool.resources.version";
+    private ResourceBundle versionRB;
+
+    /**
+     * Return the build date for the doclet.
+     * @return the build date
+     */
+    @Override
+    public String getDocletSpecificBuildDate() {
+        if (versionRB == null) {
+            try {
+                versionRB = ResourceBundle.getBundle(versionRBName, getLocale());
+            } catch (MissingResourceException e) {
+                return BUILD_DATE;
+            }
+        }
+
+        try {
+            return versionRB.getString("release");
+        } catch (MissingResourceException e) {
+            return BUILD_DATE;
+        }
+    }
+
+    protected boolean validateOptions() {
+        // check shared options
+        if (!generalValidOptions()) {
+            return false;
+        }
+        boolean helpfileSeen = false;
+        // otherwise look at our options
+        for (Doclet.Option opt : optionsProcessed) {
+            if (opt.matches("-helpfile")) {
+                if (nohelp == true) {
+                    reporter.print(ERROR, getText("doclet.Option_conflict",
+                        "-helpfile", "-nohelp"));
+                    return false;
+                }
+                if (helpfileSeen) {
+                    reporter.print(ERROR, getText("doclet.Option_reuse",
+                        "-helpfile"));
+                    return false;
+                }
+                helpfileSeen = true;
+                DocFile help = DocFile.createFileForInput(this, helpfile);
+                if (!help.exists()) {
+                    reporter.print(ERROR, getText("doclet.File_not_found", helpfile));
+                    return false;
+                }
+            } else  if (opt.matches("-nohelp")) {
+                if (helpfileSeen) {
+                    reporter.print(ERROR, getText("doclet.Option_conflict",
+                        "-nohelp", "-helpfile"));
+                    return false;
+                }
+            } else if (opt.matches("-xdocrootparent")) {
+                try {
+                    URL ignored = new URL(docrootparent);
+                } catch (MalformedURLException e) {
+                    reporter.print(ERROR, getText("doclet.MalformedURL", docrootparent));
+                    return false;
+                }
+            } else if (opt.matches("-overview")) {
+                if (nooverview == true) {
+                    reporter.print(ERROR, getText("doclet.Option_conflict",
+                        "-overview", "-nooverview"));
+                    return false;
+                }
+            } else  if (opt.matches("-nooverview")) {
+                if (overviewpath != null) {
+                    reporter.print(ERROR, getText("doclet.Option_conflict",
+                        "-nooverview", "-overview"));
+                    return false;
+                }
+            } else if (opt.matches("-splitindex")) {
+                if (createindex == false) {
+                    reporter.print(ERROR, getText("doclet.Option_conflict",
+                        "-splitindex", "-noindex"));
+                    return false;
+                }
+            } else if (opt.matches("-noindex")) {
+                if (splitindex == true) {
+                    reporter.print(ERROR, getText("doclet.Option_conflict",
+                        "-noindex", "-splitindex"));
+                    return false;
+                }
+            } else if (opt.matches("-xdoclint:")) {
+                String dopt = doclintOpts.get(opt);
+                if (dopt == null) {
+                    continue;
+                }
+                if (dopt.contains("/")) {
+                    reporter.print(ERROR, getText("doclet.Option_doclint_no_qualifiers"));
+                    return false;
+                }
+                if (!DocLint.isValidOption(dopt)) {
+                    reporter.print(ERROR, getText("doclet.Option_doclint_invalid_arg"));
+                    return false;
+                }
+            } else if (opt.matches("-xdoclint/package:")) {
+                 String dopt = doclintOpts.get(opt);
+                    if (!DocLint.isValidOption(dopt)) {
+                        reporter.print(ERROR, getText("doclet.Option_doclint_package_invalid_arg"));
+                        return false;
+                    }
+                }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean finishOptionSettings() {
+        if (!validateOptions()) {
+            return false;
+        }
+        if (!root.getSpecifiedElements().isEmpty()) {
+            Map<String, PackageElement> map = new HashMap<>();
+            PackageElement pkg;
+            List<TypeElement> classes = new ArrayList<>(root.getIncludedClasses());
+            for (TypeElement aClass : classes) {
+                pkg = utils.containingPackage(aClass);
+                if (!map.containsKey(utils.getPackageName(pkg))) {
+                    map.put(utils.getPackageName(pkg), pkg);
+                }
+            }
+        }
+        setCreateOverview();
+        setTopFile(root);
+        workArounds.initDocLint(doclintOpts.values(), tagletManager.getCustomTagNames(),
+                Utils.toLowerCase(htmlVersion.name()));
+        return true;
+    }
+
+    /**
+     * Return true if the generated output is HTML5.
+     */
+    public boolean isOutputHtml5() {
+        return htmlVersion == HtmlVersion.HTML5;
+    }
+
+    /**
+     * Return true if the tag is allowed for this specific version of HTML.
+     */
+    public boolean allowTag(HtmlTag htmlTag) {
+        return htmlTag.allowTag(this.htmlVersion);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public MessageRetriever getDocletSpecificMsg() {
+        return standardmessage;
+    }
+
+    /**
+     * Decide the page which will appear first in the right-hand frame. It will
+     * be "overview-summary.html" if "-overview" option is used or no
+     * "-overview" but the number of packages is more than one. It will be
+     * "package-summary.html" of the respective package if there is only one
+     * package to document. It will be a class page(first in the sorted order),
+     * if only classes are provided on the command line.
+     *
+     * @param root Root of the program structure.
+     */
+    protected void setTopFile(DocletEnvironment root) {
+        if (!checkForDeprecation(root)) {
+            return;
+        }
+        if (createoverview) {
+            topFile = DocPaths.OVERVIEW_SUMMARY;
+        } else {
+            if (packages.size() == 1 && packages.first().isUnnamed()) {
+                if (!root.getIncludedClasses().isEmpty()) {
+                    List<TypeElement> classes = new ArrayList<>(root.getIncludedClasses());
+                    TypeElement te = getValidClass(classes);
+                    topFile = DocPath.forClass(utils, te);
+                }
+            } else if (!packages.isEmpty()) {
+                topFile = DocPath.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY);
+            }
+        }
+    }
+
+    protected TypeElement getValidClass(List<TypeElement> classes) {
+        if (!nodeprecated) {
+            return classes.get(0);
+        }
+        for (TypeElement te : classes) {
+            if (!utils.isDeprecated(te)) {
+                return te;
+            }
+        }
+        return null;
+    }
+
+    protected boolean checkForDeprecation(DocletEnvironment root) {
+        for (TypeElement te : root.getIncludedClasses()) {
+            if (isGeneratedDoc(te)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Generate "overview.html" page if option "-overview" is used or number of
+     * packages is more than one. Sets {@link #createoverview} field to true.
+     */
+    protected void setCreateOverview() {
+        if ((overviewpath != null || packages.size() > 1) && !nooverview) {
+            createoverview = true;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public WriterFactory getWriterFactory() {
+        return new WriterFactoryImpl(this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Locale getLocale() {
+        if (locale == null)
+            return Locale.getDefault();
+        return locale;
+    }
+
+    /**
+     * Return the path of the overview file and null if it does not exist.
+     *
+     * @return the path of the overview file and null if it does not exist.
+     */
+    public JavaFileObject getOverviewPath() {
+        if (overviewpath != null && getFileManager() instanceof StandardJavaFileManager) {
+            StandardJavaFileManager fm = (StandardJavaFileManager) getFileManager();
+            return fm.getJavaFileObjects(overviewpath).iterator().next();
+        }
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public JavaFileManager getFileManager() {
+        return root.getJavaFileManager();
+    }
+
+    @Override
+    public boolean showMessage(DocTreePath path, String key) {
+        return (path == null || workArounds.haveDocLint());
+    }
+
+    @Override
+    public boolean showMessage(Element e, String key) {
+        return (e == null || workArounds.haveDocLint());
+    }
+
+    @Override
+    public Content newContent() {
+        return new ContentBuilder();
+    }
+
+    protected void buildSearchTagIndex() {
+        for (SearchIndexItem sii : tagSearchIndex) {
+            String tagLabel = sii.getLabel();
+            Character unicode = (tagLabel.length() == 0)
+                    ? '*'
+                    : Character.toUpperCase(tagLabel.charAt(0));
+            List<SearchIndexItem> list = tagSearchIndexMap.get(unicode);
+            if (list == null) {
+                list = new ArrayList<>();
+                tagSearchIndexMap.put(unicode, list);
+            }
+            list.add(sii);
+        }
+        tagSearchIndexKeys = tagSearchIndexMap.keySet();
+    }
+
+    @Override
+    public Set<Doclet.Option> getSupportedOptions() {
+        Doclet.Option[] options = {
+            new Option(this, "bottom", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    bottom = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "charset", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    charset = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "doctitle", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    doctitle = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "footer", 1) {
+                @Override
+                public boolean process(String opt, ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    footer = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "header", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    header = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "helpfile", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    helpfile = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "html4") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    htmlVersion = HtmlVersion.HTML4;
+                    return true;
+                }
+            },
+            new Option(this, "html5") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    htmlVersion = HtmlVersion.HTML5;
+                    return true;
+                }
+            },
+            new Option(this, "nohelp") {
+                @Override
+                public boolean process(String opt, ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    nohelp = true;
+                    return true;
+                }
+            },
+            new Option(this, "nodeprecatedlist") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    nodeprecatedlist = true;
+                    return true;
+                }
+            },
+            new Option(this, "noindex") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    createindex = false;
+                    return true;
+                }
+            },
+            new Option(this, "nonavbar") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    nonavbar = true;
+                    return true;
+                }
+            },
+            new Hidden(this, "nooverview") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    nooverview = true;
+                    return true;
+                }
+            },
+            new Option(this, "notree") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    createtree = false;
+                    return true;
+                }
+            },
+            new Hidden(this, "overview", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    overviewpath = args.next();
+                    return true;
+                }
+            },
+            new Hidden(this, "packagesheader", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    packagesheader = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "splitindex") {
+                @Override
+                public boolean process(String opt, ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    splitindex = true;
+                    return true;
+                }
+            },
+            new Option(this, "stylesheetfile", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    stylesheetfile = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "top", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    top = args.next();
+                    return true;
+                }
+            },
+            new Option(this, "use") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    classuse = true;
+                    return true;
+                }
+            },
+            new Option(this, "windowtitle", 1) {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    windowtitle = args.next().replaceAll("\\<.*?>", "");
+                    return true;
+                }
+            },
+            new XOption(this, "xdoclint") {
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    doclintOpts.put(this, DocLint.XMSGS_OPTION);
+                    return true;
+                }
+            },
+            new XOption(this, "Xdocrootparent", 1) {
+                @Override
+                public boolean process(String opt, ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    docrootparent = args.next();
+                    return true;
+                }
+            },
+            new XOption(this, "doclet.xusage.xdoclint-extended.", "Xdoclint:", 0) {
+                @Override
+                public boolean matches(String option) {
+                    String opt = option.startsWith("-") ? option.substring(1) : option;
+                    return opt.toLowerCase().startsWith(getName().toLowerCase());
+                }
+
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    doclintOpts.put(this, opt.replace("-Xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX));
+                    return true;
+                }
+            },
+            new XOption(this, "doclet.xusage.xdoclint-package.", "Xdoclint/package:", 0) {
+                @Override
+                public boolean matches(String option) {
+                    String opt = option.startsWith("-") ? option.substring(1) : option;
+                    return opt.toLowerCase().startsWith(getName().toLowerCase());
+                }
+
+                @Override
+                public boolean process(String opt,  ListIterator<String> args) {
+                    optionsProcessed.add(this);
+                    doclintOpts.put(this, opt.replace("-Xdoclint/package:", DocLint.XCHECK_PACKAGE));
+                    return true;
+                }
+            }
+        };
+        Set<Doclet.Option> oset = new TreeSet<>();
+        oset.addAll(Arrays.asList(options));
+        oset.addAll(super.getSupportedOptions());
+        return oset;
+    }
+}