/* * 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 com.sun.tools.doclets.formats.html; import java.net.*; import java.util.*; import javax.tools.JavaFileManager; import javax.tools.JavaFileManager.Location; import javax.tools.StandardLocation; import com.sun.javadoc.*; import com.sun.tools.doclets.formats.html.markup.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclint.DocLint; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.StringUtils; import com.sun.tools.javadoc.main.RootDocImpl; /** * 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) */ @Deprecated 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 = ""; /** * 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; /** * True if command line option "-overview" is used. Default value is false. */ public boolean overview = false; /** * 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 Set<String> doclintOpts = new LinkedHashSet<>(); /** * 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 classdoc for the class file getting generated. */ public ClassDoc currentcd = null; // Set this classdoc 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, "com.sun.tools.doclets.formats.html.resources.standard"); } private final String versionRBName = "com.sun.tools.javadoc.resources.version"; private ResourceBundle versionRB; /** * Return the build date for the doclet. */ @Override public String getDocletSpecificBuildDate() { if (versionRB == null) { try { versionRB = ResourceBundle.getBundle(versionRBName); } catch (MissingResourceException e) { return BUILD_DATE; } } try { return versionRB.getString("release"); } catch (MissingResourceException e) { return BUILD_DATE; } } /** * Depending upon the command line options provided by the user, set * configure the output generation environment. * * @param options The array of option names and values. */ @Override public void setSpecificDocletOptions(String[][] options) { for (int oi = 0; oi < options.length; ++oi) { String[] os = options[oi]; String opt = StringUtils.toLowerCase(os[0]); if (opt.equals("-footer")) { footer = os[1]; } else if (opt.equals("-header")) { header = os[1]; } else if (opt.equals("-packagesheader")) { packagesheader = os[1]; } else if (opt.equals("-doctitle")) { doctitle = os[1]; } else if (opt.equals("-windowtitle")) { windowtitle = os[1].replaceAll("\\<.*?>", ""); } else if (opt.equals("-top")) { top = os[1]; } else if (opt.equals("-bottom")) { bottom = os[1]; } else if (opt.equals("-helpfile")) { helpfile = os[1]; } else if (opt.equals("-stylesheetfile")) { stylesheetfile = os[1]; } else if (opt.equals("-charset")) { charset = os[1]; } else if (opt.equals("-xdocrootparent")) { docrootparent = os[1]; } else if (opt.equals("-nohelp")) { nohelp = true; } else if (opt.equals("-splitindex")) { splitindex = true; } else if (opt.equals("-noindex")) { createindex = false; } else if (opt.equals("-use")) { classuse = true; } else if (opt.equals("-notree")) { createtree = false; } else if (opt.equals("-nodeprecatedlist")) { nodeprecatedlist = true; } else if (opt.equals("-nonavbar")) { nonavbar = true; } else if (opt.equals("-nooverview")) { nooverview = true; } else if (opt.equals("-overview")) { overview = true; } else if (opt.equals("-html4")) { htmlVersion = HtmlVersion.HTML4; } else if (opt.equals("-html5")) { htmlVersion = HtmlVersion.HTML5; } else if (opt.equals("-xdoclint")) { doclintOpts.add(DocLint.XMSGS_OPTION); } else if (opt.startsWith("-xdoclint:")) { doclintOpts.add(DocLint.XMSGS_CUSTOM_PREFIX + opt.substring(opt.indexOf(":") + 1)); } else if (opt.startsWith("-xdoclint/package:")) { doclintOpts.add(DocLint.XCHECK_PACKAGE + opt.substring(opt.indexOf(":") + 1)); } } if (root.specifiedClasses().length > 0) { Map<String,PackageDoc> map = new HashMap<>(); PackageDoc pd; ClassDoc[] classes = root.classes(); for (ClassDoc aClass : classes) { pd = aClass.containingPackage(); if (!map.containsKey(pd.name())) { map.put(pd.name(), pd); } } } setCreateOverview(); setTopFile(root); if (root instanceof RootDocImpl) { ((RootDocImpl) root).initDocLint(doclintOpts, tagletManager.getCustomTagNames(), StringUtils.toLowerCase(htmlVersion.name())); } } /** * Returns the "length" of a given option. If an option takes no * arguments, its length is one. If it takes one argument, it's * length is two, and so on. This method is called by JavaDoc to * parse the options it does not recognize. It then calls * {@link #validOptions(String[][], DocErrorReporter)} to * validate them. * <b>Note:</b><br> * The options arrive as case-sensitive strings. For options that * are not case-sensitive, use toLowerCase() on the option string * before comparing it. * * @return number of arguments + 1 for a option. Zero return means * option not known. Negative value means error occurred. */ public int optionLength(String option) { int result = -1; if ((result = super.optionLength(option)) > 0) { return result; } // otherwise look for the options we have added option = StringUtils.toLowerCase(option); if (option.equals("-nodeprecatedlist") || option.equals("-noindex") || option.equals("-notree") || option.equals("-nohelp") || option.equals("-splitindex") || option.equals("-serialwarn") || option.equals("-use") || option.equals("-nonavbar") || option.equals("-nooverview") || option.equals("-html4") || option.equals("-html5") || option.equals("-xdoclint") || option.startsWith("-xdoclint:") || option.startsWith("-xdoclint/package:")) { return 1; } else if (option.equals("-help")) { // Uugh: first, this should not be hidden inside optionLength, // and second, we should not be writing directly to stdout. // But we have no access to a DocErrorReporter, which would // allow use of reporter.printNotice System.out.println(getText("doclet.usage")); return 1; } else if (option.equals("-x")) { // Uugh: first, this should not be hidden inside optionLength, // and second, we should not be writing directly to stdout. // But we have no access to a DocErrorReporter, which would // allow use of reporter.printNotice System.out.println(getText("doclet.X.usage")); return 1; } else if (option.equals("-footer") || option.equals("-header") || option.equals("-packagesheader") || option.equals("-doctitle") || option.equals("-windowtitle") || option.equals("-top") || option.equals("-bottom") || option.equals("-helpfile") || option.equals("-stylesheetfile") || option.equals("-charset") || option.equals("-overview") || option.equals("-xdocrootparent")) { return 2; } else { return 0; } } /** * {@inheritDoc} */ @Override public boolean validOptions(String options[][], DocErrorReporter reporter) { boolean helpfile = false; boolean nohelp = false; boolean overview = false; boolean nooverview = false; boolean splitindex = false; boolean noindex = false; // check shared options if (!generalValidOptions(options, reporter)) { return false; } // otherwise look at our options for (int oi = 0; oi < options.length; ++oi) { String[] os = options[oi]; String opt = StringUtils.toLowerCase(os[0]); if (opt.equals("-helpfile")) { if (nohelp == true) { reporter.printError(getText("doclet.Option_conflict", "-helpfile", "-nohelp")); return false; } if (helpfile == true) { reporter.printError(getText("doclet.Option_reuse", "-helpfile")); return false; } DocFile help = DocFile.createFileForInput(this, os[1]); if (!help.exists()) { reporter.printError(getText("doclet.File_not_found", os[1])); return false; } helpfile = true; } else if (opt.equals("-nohelp")) { if (helpfile == true) { reporter.printError(getText("doclet.Option_conflict", "-nohelp", "-helpfile")); return false; } nohelp = true; } else if (opt.equals("-xdocrootparent")) { try { new URL(os[1]); } catch (MalformedURLException e) { reporter.printError(getText("doclet.MalformedURL", os[1])); return false; } } else if (opt.equals("-overview")) { if (nooverview == true) { reporter.printError(getText("doclet.Option_conflict", "-overview", "-nooverview")); return false; } if (overview == true) { reporter.printError(getText("doclet.Option_reuse", "-overview")); return false; } overview = true; } else if (opt.equals("-nooverview")) { if (overview == true) { reporter.printError(getText("doclet.Option_conflict", "-nooverview", "-overview")); return false; } nooverview = true; } else if (opt.equals("-splitindex")) { if (noindex == true) { reporter.printError(getText("doclet.Option_conflict", "-splitindex", "-noindex")); return false; } splitindex = true; } else if (opt.equals("-noindex")) { if (splitindex == true) { reporter.printError(getText("doclet.Option_conflict", "-noindex", "-splitindex")); return false; } noindex = true; } else if (opt.startsWith("-xdoclint:")) { if (opt.contains("/")) { reporter.printError(getText("doclet.Option_doclint_no_qualifiers")); return false; } if (!DocLint.isValidOption( opt.replace("-xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX))) { reporter.printError(getText("doclet.Option_doclint_invalid_arg")); return false; } } else if (opt.startsWith("-xdoclint/package:")) { if (!DocLint.isValidOption( opt.replace("-xdoclint/package:", DocLint.XCHECK_PACKAGE))) { reporter.printError(getText("doclet.Option_doclint_package_invalid_arg")); return false; } } } 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(RootDoc root) { if (!checkForDeprecation(root)) { return; } if (createoverview) { topFile = DocPaths.OVERVIEW_SUMMARY; } else { if (packages.size() == 1 && packages.first().name().equals("")) { if (root.classes().length > 0) { ClassDoc[] classarr = root.classes(); Arrays.sort(classarr); ClassDoc cd = getValidClass(classarr); topFile = DocPath.forClass(cd); } } else if (!packages.isEmpty()) { topFile = DocPath.forPackage(packages.first()).resolve(DocPaths.PACKAGE_SUMMARY); } } } protected ClassDoc getValidClass(ClassDoc[] classarr) { if (!nodeprecated) { return classarr[0]; } for (ClassDoc cd : classarr) { if (cd.tags("deprecated").length == 0) { return cd; } } return null; } protected boolean checkForDeprecation(RootDoc root) { for (ClassDoc cd : root.classes()) { if (isGeneratedDoc(cd)) { 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 ((overview || packages.size() > 1) && !nooverview) { createoverview = true; } } /** * {@inheritDoc} */ @Override public WriterFactory getWriterFactory() { return new WriterFactoryImpl(this); } /** * {@inheritDoc} */ @Override public Comparator<ProgramElementDoc> getMemberComparator() { return null; } /** * {@inheritDoc} */ @Override public Locale getLocale() { if (root instanceof RootDocImpl) return ((RootDocImpl)root).getLocale(); else return Locale.getDefault(); } /** * {@inheritDoc} */ @Override public JavaFileManager getFileManager() { if (fileManager == null) { if (root instanceof RootDocImpl) fileManager = ((RootDocImpl) root).getFileManager(); else fileManager = new JavacFileManager(new Context(), false, null); } return fileManager; } private JavaFileManager fileManager; @Override public boolean showMessage(SourcePosition pos, String key) { if (root instanceof RootDocImpl) { return pos == null || ((RootDocImpl) root).showTagMessages(); } return true; } @Override public Content newContent() { return new ContentBuilder(); } @Override public Location getLocationForPackage(PackageDoc pd) { JavaFileManager fm = getFileManager(); return StandardLocation.SOURCE_PATH; } protected void buildSearchTagIndex() { for (SearchIndexItem sii : tagSearchIndex) { String tagLabel = sii.getLabel(); char ch = (tagLabel.length() == 0) ? '*' : Character.toUpperCase(tagLabel.charAt(0)); Character unicode = ch; List<SearchIndexItem> list = tagSearchIndexMap.get(unicode); if (list == null) { list = new ArrayList<>(); tagSearchIndexMap.put(unicode, list); } list.add(sii); } tagSearchIndexKeys = tagSearchIndexMap.keySet(); } }