Path: blob/master/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseOptions.java
44719 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package jdk.javadoc.internal.doclets.toolkit;2627import java.io.ByteArrayOutputStream;28import java.io.IOException;29import java.io.OutputStream;30import java.io.OutputStreamWriter;31import java.io.UnsupportedEncodingException;32import java.util.ArrayList;33import java.util.Arrays;34import java.util.HashSet;35import java.util.LinkedHashSet;36import java.util.List;37import java.util.MissingResourceException;38import java.util.Set;39import java.util.StringTokenizer;40import java.util.TreeSet;4142import jdk.javadoc.doclet.Doclet;43import jdk.javadoc.doclet.Reporter;44import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;45import jdk.javadoc.internal.doclets.toolkit.util.Utils;4647import static javax.tools.Diagnostic.Kind.ERROR;4849/**50* Storage for the format-independent options supported by the toolkit.51* The objects to handle command-line options, and to initialize this52* object, are all subtypes of {@link BaseOptions.Option},53* returned by {@link BaseOptions#getSupportedOptions()}.54*55* <p>Some of the methods used to access the values of options56* have names that begin with a verb, such as {@link #copyDocfileSubdirs}57* or {@link #showVersion}. Unless otherwise stated,58* these methods should all be taken as just accessing the value59* of the associated option.60*/61public abstract class BaseOptions {6263//<editor-fold desc="Option values">6465/**66* Argument for command-line option {@code --allow-script-in-comments}.67* Allow JavaScript in doc comments.68*/69private boolean allowScriptInComments = false;7071/**72* Argument for command-line option {@code -docfilessubdirs}.73* True if we should recursively copy the doc-file subdirectories74*/75private boolean copyDocfileSubdirs = false;7677/**78* Arguments for command-line option {@code -tag} and {@code -taglet}.79*/80private final LinkedHashSet<List<String>> customTagStrs = new LinkedHashSet<>();8182/**83* Argument for command-line option {@code -d}.84* Destination directory name, in which doclet will generate the entire85* documentation. Default is current directory.86*/87private String destDirName = "";8889/**90* Argument for command-line option {@code --disable-javafx-strict-checks}.91* Primarily used to disable strict checks in the regression92* tests allowing those tests to be executed successfully, for93* instance, with OpenJDK builds which may not contain FX libraries.94*/95private boolean disableJavaFxStrictChecks = false;9697/**98* Argument for command-line option {@code -docencoding}.99* Encoding for this document. Default is default encoding for this100* platform.101*/102private String docEncoding = null;103104/**105* Argument for command-line option {@code ???}.106* Destination directory name, in which doclet will copy the doc-files to.107*/108private String docFileDestDirName = "";109110/**111* Argument for hidden command-line option {@code --dump-on-error}.112*/113private boolean dumpOnError = false;114115/**116* Argument for command-line option {@code -encoding}.117* Encoding for this document. Default is default encoding for this118* platform.119*/120private String encoding = null;121122/**123* Argument for command-line option {@code -excludedocfilessubdir}.124* The set of doc-file subdirectories to exclude.125*/126private Set<String> excludedDocFileDirs;127128/**129* Argument for command-line option {@code -noqualifier}.130* The set of qualifiers to exclude.131*/132private Set<String> excludedQualifiers;133134/**135* Arguments for command-line option {@code -group}136*/137private List<Utils.Pair<String, String>> groupPairs;138139/**140* Argument for command-line option {@code --javafx} or {@code -javafx}.141* Generate documentation for JavaFX getters and setters automatically142* by copying it from the appropriate property definition.143*/144private boolean javafx = false;145146/**147* Argument for command-line option {@code -keywords}.148* True if user wants to add member names as meta keywords.149* Set to false because meta keywords are ignored in general150* by most Internet search engines.151*/152private boolean keywords = false;153154/**155* Arguments for command-line option {@code -link}.156*/157// A list containing urls158private final List<String> linkList = new ArrayList<>();159160/**161* Arguments for command-line option {@code -linkoffline}.162*/163// A list of pairs containing urls and package list164private final List<Utils.Pair<String, String>> linkOfflineList = new ArrayList<>();165166/**167* Location of alternative platform link properties file.168*/169private String linkPlatformProperties;170171/**172* Argument for command-line option {@code -linksource}.173* True if we should generate browsable sources.174*/175private boolean linkSource = false;176177/**178* Argument for command-line option {@code -nocomment}.179* True if user wants to suppress descriptions and tags.180*/181private boolean noComment = false;182183/**184* Argument for command-line option {@code -nodeprecated}.185* Don't generate deprecated API information at all, if -nodeprecated186* option is used. <code>nodeprecated</code> is set to true if187* -nodeprecated option is used. Default is generate deprecated API188* information.189*/190private boolean noDeprecated = false;191192/**193* Argument for command-line option {@code --no-platform-links}.194* True if command-line option "--no-platform-links" is used. Default value is195* false.196*/197private boolean noPlatformLinks = false;198199/**200* Argument for command-line option {@code -nosince}.201* True if command-line option "-nosince" is used. Default value is202* false.203*/204private boolean noSince = false;205206/**207* Argument for command-line option {@code -notimestamp}.208* True if user wants to suppress time stamp in output.209* Default is false.210*/211private boolean noTimestamp = false;212213/**214* Argument for command-line option {@code -quiet}.215* Suppress all messages216*/217private boolean quiet = false;218219/**220* Argument for command-line option {@code -serialwarn}.221* This is true if option "-serialwarn" is used. Default value is false to222* suppress excessive warnings about serial tag.223*/224private boolean serialWarn = false;225226/**227* Argument for command-line option {@code -author}.228* Generate author specific information for all the classes if @author229* tag is used in the doc comment and if -author option is used.230* <code>showauthor</code> is set to true if -author option is used.231* Default is don't show author information.232*/233private boolean showAuthor = false;234235/**236* Argument for command-line option {@code --show-taglets}.237* Show taglets (internal debug switch)238*/239private boolean showTaglets = false;240241/**242* Argument for command-line option {@code -version}.243* Generate version specific information for the all the classes244* if @version tag is used in the doc comment and if -version option is245* used. {@code showVersion} is set to true if -version option is246* used. Default is don't show version information.247*/248private boolean showVersion = false;249250/**251* Argument for command-line option {@code -sourcetab}.252* The specified amount of space between tab stops.253*/254private int sourceTabSize;255256/**257* Value for command-line option {@code --override-methods summary}258* or {@code --override-methods detail}.259* Specifies whether those methods that override a super-type's method260* with no changes to the API contract should be summarized in the261* footnote section.262*/263private boolean summarizeOverriddenMethods = false;264265/**266* Argument for command-line option {@code -tagletpath}.267* The path to Taglets268*/269private String tagletPath = null;270271//</editor-fold>272273private final BaseConfiguration config;274275protected BaseOptions(BaseConfiguration config) {276this.config = config;277278excludedDocFileDirs = new HashSet<>();279excludedQualifiers = new HashSet<>();280sourceTabSize = DocletConstants.DEFAULT_TAB_STOP_LENGTH;281groupPairs = new ArrayList<>(0);282}283284public Set<? extends Option> getSupportedOptions() {285Resources resources = config.getDocResources();286Messages messages = config.getMessages();287Reporter reporter = config.getReporter();288289List<Option> options = List.of(290new Option(resources, "-author") {291@Override292public boolean process(String opt, List<String> args) {293showAuthor = true;294return true;295}296},297298new Option(resources, "-d", 1) {299@Override300public boolean process(String opt, List<String> args) {301destDirName = addTrailingFileSep(args.get(0));302return true;303}304},305306new Option(resources, "-docencoding", 1) {307@Override308public boolean process(String opt, List<String> args) {309docEncoding = args.get(0);310return true;311}312},313314new Option(resources, "-docfilessubdirs") {315@Override316public boolean process(String opt, List<String> args) {317copyDocfileSubdirs = true;318return true;319}320},321322new Hidden(resources, "-encoding", 1) {323@Override324public boolean process(String opt, List<String> args) {325encoding = args.get(0);326return true;327}328},329330new Option(resources, "-excludedocfilessubdir", 1) {331@Override332public boolean process(String opt, List<String> args) {333addToSet(excludedDocFileDirs, args.get(0));334return true;335}336},337338new Option(resources, "-group", 2) {339@Override340public boolean process(String opt, List<String> args) {341groupPairs.add(new Utils.Pair<>(args.get(0), args.get(1)));342return true;343}344},345346new Option(resources, "--javafx -javafx") {347@Override348public boolean process(String opt, List<String> args) {349javafx = true;350return true;351}352},353354new Option(resources, "-keywords") {355@Override356public boolean process(String opt, List<String> args) {357keywords = true;358return true;359}360},361362new Option(resources, "-link", 1) {363@Override364public boolean process(String opt, List<String> args) {365linkList.add(args.get(0));366return true;367}368},369370new Option(resources, "-linksource") {371@Override372public boolean process(String opt, List<String> args) {373linkSource = true;374return true;375}376},377378new Option(resources, "-linkoffline", 2) {379@Override380public boolean process(String opt, List<String> args) {381linkOfflineList.add(new Utils.Pair<>(args.get(0), args.get(1)));382return true;383}384},385386new Option(resources, "--link-platform-properties", 1) {387@Override388public boolean process(String opt, List<String> args) {389linkPlatformProperties = args.get(0);390return true;391}392},393394new Option(resources, "-nocomment") {395@Override396public boolean process(String opt, List<String> args) {397noComment = true;398return true;399}400},401402new Option(resources, "-nodeprecated") {403@Override404public boolean process(String opt, List<String> args) {405noDeprecated = true;406return true;407}408},409410new Option(resources, "-nosince") {411@Override412public boolean process(String opt, List<String> args) {413noSince = true;414return true;415}416},417418new Option(resources, "-notimestamp") {419@Override420public boolean process(String opt, List<String> args) {421noTimestamp = true;422return true;423}424},425426new Option(resources, "-noqualifier", 1) {427@Override428public boolean process(String opt, List<String> args) {429addToSet(excludedQualifiers, args.get(0));430return true;431}432},433434new Option(resources, "--no-platform-links") {435@Override436public boolean process(String opt, List<String> args) {437noPlatformLinks = true;438return true;439}440},441442new Option(resources, "--override-methods", 1) {443@Override444public boolean process(String opt, List<String> args) {445String o = args.get(0);446switch (o) {447case "summary":448summarizeOverriddenMethods = true;449break;450case "detail":451summarizeOverriddenMethods = false;452break;453default:454reporter.print(ERROR,455resources.getText("doclet.Option_invalid",o, "--override-methods"));456return false;457}458return true;459}460},461462new Hidden(resources, "-quiet") {463@Override464public boolean process(String opt, List<String> args) {465quiet = true;466return true;467}468},469470new Option(resources, "-serialwarn") {471@Override472public boolean process(String opt, List<String> args) {473serialWarn = true;474return true;475}476},477478new Option(resources, "-sourcetab", 1) {479@Override480public boolean process(String opt, List<String> args) {481linkSource = true;482try {483sourceTabSize = Integer.parseInt(args.get(0));484} catch (NumberFormatException e) {485//Set to -1 so that warning will be printed486//to indicate what is valid argument.487sourceTabSize = -1;488}489if (sourceTabSize <= 0) {490messages.warning("doclet.sourcetab_warning");491sourceTabSize = DocletConstants.DEFAULT_TAB_STOP_LENGTH;492}493return true;494}495},496497new Option(resources, "-tag", 1) {498@Override499public boolean process(String opt, List<String> args) {500ArrayList<String> list = new ArrayList<>();501list.add(opt);502list.add(args.get(0));503customTagStrs.add(list);504return true;505}506},507508new Option(resources, "-taglet", 1) {509@Override510public boolean process(String opt, List<String> args) {511ArrayList<String> list = new ArrayList<>();512list.add(opt);513list.add(args.get(0));514customTagStrs.add(list);515return true;516}517},518519new Option(resources, "-tagletpath", 1) {520@Override521public boolean process(String opt, List<String> args) {522tagletPath = args.get(0);523return true;524}525},526527new Option(resources, "-version") {528@Override529public boolean process(String opt, List<String> args) {530showVersion = true;531return true;532}533},534535new Hidden(resources, "--dump-on-error") {536@Override537public boolean process(String opt, List<String> args) {538dumpOnError = true;539return true;540}541},542543new Option(resources, "--allow-script-in-comments") {544@Override545public boolean process(String opt, List<String> args) {546allowScriptInComments = true;547return true;548}549},550551new Hidden(resources, "--disable-javafx-strict-checks") {552@Override553public boolean process(String opt, List<String> args) {554disableJavaFxStrictChecks = true;555return true;556}557},558559new Hidden(resources, "--show-taglets") {560@Override561public boolean process(String opt, List<String> args) {562showTaglets = true;563return true;564}565}566);567return new TreeSet<>(options);568}569570/**571* This checks for the validity of the options used by the user.572* As of this writing, this checks only docencoding.573*574* @return true if all the options are valid.575*/576protected boolean generalValidOptions() {577if (docEncoding != null) {578if (!checkOutputFileEncoding(docEncoding)) {579return false;580}581}582if (docEncoding == null && (encoding != null && !encoding.isEmpty())) {583if (!checkOutputFileEncoding(encoding)) {584return false;585}586}587return true;588}589590/**591* Check the validity of the given Source or Output File encoding on this592* platform.593*594* @param docencoding output file encoding.595*/596private boolean checkOutputFileEncoding(String docencoding) {597OutputStream ost = new ByteArrayOutputStream();598OutputStreamWriter osw = null;599try {600osw = new OutputStreamWriter(ost, docencoding);601} catch (UnsupportedEncodingException exc) {602config.reporter.print(ERROR,603config.getDocResources().getText("doclet.Encoding_not_supported", docencoding));604return false;605} finally {606try {607if (osw != null) {608osw.close();609}610} catch (IOException exc) {611}612}613return true;614}615616private void addToSet(Set<String> s, String str) {617StringTokenizer st = new StringTokenizer(str, ":");618String current;619while (st.hasMoreTokens()) {620current = st.nextToken();621s.add(current);622}623}624625/**626* Add a trailing file separator, if not found. Remove superfluous627* file separators if any. Preserve the front double file separator for628* UNC paths.629*630* @param path Path under consideration.631* @return String Properly constructed path string.632*/633protected static String addTrailingFileSep(String path) {634String fs = System.getProperty("file.separator");635String dblfs = fs + fs;636int indexDblfs;637while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {638path = path.substring(0, indexDblfs) +639path.substring(indexDblfs + fs.length());640}641if (!path.endsWith(fs))642path += fs;643return path;644}645646/**647* Argument for command-line option {@code --allow-script-in-comments}.648* Allow JavaScript in doc comments.649*/650boolean allowScriptInComments() {651return allowScriptInComments;652}653654/**655* Argument for command-line option {@code -docfilessubdirs}.656* True if we should recursively copy the doc-file subdirectories657*/658public boolean copyDocfileSubdirs() {659return copyDocfileSubdirs;660}661662/**663* Arguments for command-line option {@code -tag} and {@code -taglet}.664*/665LinkedHashSet<List<String>> customTagStrs() {666return customTagStrs;667}668669/**670* Argument for command-line option {@code -d}.671* Destination directory name, in which doclet will generate the entire672* documentation. Default is current directory.673*/674String destDirName() {675return destDirName;676}677678/**679* Argument for command-line option {@code --disable-javafx-strict-checks}.680* Primarily used to disable strict checks in the regression681* tests allowing those tests to be executed successfully, for682* instance, with OpenJDK builds which may not contain FX libraries.683*/684boolean disableJavaFxStrictChecks() {685return disableJavaFxStrictChecks;686}687688/**689* Argument for command-line option {@code -docencoding}.690* Encoding for this document. Default is default encoding for this691* platform.692*/693public String docEncoding() {694return docEncoding;695}696697public void setDocEncoding(String docEncoding) {698this.docEncoding = docEncoding;699}700701702/**703* Argument for command-line option {@code ???}.704* Destination directory name, in which doclet will copy the doc-files to.705*/706String docFileDestDirName() {707return docFileDestDirName;708}709710/**711* Argument for hidden command-line option {@code --dump-on-error}.712*/713boolean dumpOnError() {714return dumpOnError;715}716717/**718* Argument for command-line option {@code -encoding}.719* Encoding for this document. Default is default encoding for this720* platform.721*/722public String encoding() {723return encoding;724}725726/**727* Argument for command-line option {@code -excludedocfilessubdir}.728* The set of doc-file subdirectories to exclude.729*/730Set<String> excludedDocFileDirs() {731return excludedDocFileDirs;732}733734/**735* Argument for command-line option {@code -noqualifier}.736* The set of qualifiers to exclude.737*/738Set<String> excludedQualifiers() {739return excludedQualifiers;740}741742/**743* Arguments for command-line option {@code -group}744*/745List<Utils.Pair<String, String>> groupPairs() {746return groupPairs;747}748749/**750* Argument for command-line option {@code --javafx} or {@code -javafx}.751* Generate documentation for JavaFX getters and setters automatically752* by copying it from the appropriate property definition.753*/754public boolean javafx() {755return javafx;756}757758public void setJavaFX(boolean javafx) {759this.javafx = javafx;760}761762/**763* Argument for command-line option {@code -keywords}.764* True if user wants to add member names as meta keywords.765* Set to false because meta keywords are ignored in general766* by most Internet search engines.767*/768public boolean keywords() {769return keywords;770}771772/**773* Arguments for command-line option {@code -link}.774*/775List<String> linkList() {776return linkList;777}778779/**780* Arguments for command-line option {@code -linkoffline}.781*/782List<Utils.Pair<String, String>> linkOfflineList() {783return linkOfflineList;784}785786/**787* Argument for command-line option {@code --link-platform-properties}.788*/789String linkPlatformProperties() {790return linkPlatformProperties;791}792793/**794* Argument for command-line option {@code -linksource}.795* True if we should generate browsable sources.796*/797public boolean linkSource() {798return linkSource;799}800801/**802* Argument for command-line option {@code -nocomment}.803* True if user wants to suppress descriptions and tags.804*/805public boolean noComment() {806return noComment;807}808809/**810* Argument for command-line option {@code -nodeprecated}.811* Don't generate deprecated API information at all if -nodeprecated812* option is used. {@code noDeprecated} is set to {@code true} if813* {@code -nodeprecated} option is used.814* Default is generate deprecated API information.815*/816public boolean noDeprecated() {817return noDeprecated;818}819820/**821* Argument for command-line option {@code --no-platform-links}.822* True if command-line option {@code --no-platform-links"} is used.823* Default value is false.824*/825public boolean noPlatformLinks() {826return noPlatformLinks;827}828829/**830* Argument for command-line option {@code -nosince}.831* True if command-line option {@code -nosince"} is used.832* Default value is false.833*/834public boolean noSince() {835return noSince;836}837838/**839* Argument for command-line option {@code -notimestamp}.840* True if user wants to suppress time stamp in output.841* Default is false.842*/843public boolean noTimestamp() {844return noTimestamp;845}846847/**848* Argument for command-line option {@code -quiet}.849* Suppress all messages850*/851boolean quiet() {852return quiet;853}854855/**856* Argument for command-line option {@code -serialwarn}.857* This is true if option "-serialwarn" is used. Default value is false to858* suppress excessive warnings about serial tag.859*/860public boolean serialWarn() {861return serialWarn;862}863864/**865* Argument for command-line option {@code -author}.866* Generate author specific information for all the classes if @author867* tag is used in the doc comment and if -author option is used.868* <code>showauthor</code> is set to true if -author option is used.869* Default is don't show author information.870*/871public boolean showAuthor() {872return showAuthor;873}874875/**876* Argument for command-line option {@code --show-taglets}.877* Show taglets (internal debug switch)878*/879public boolean showTaglets() {880return showTaglets;881}882883/**884* Argument for command-line option {@code -version}.885* Generate version specific information for the all the classes886* if @version tag is used in the doc comment and if -version option is887* used. {@code showVersion} is set to true if -version option is888* used. Default is don't show version information.889*/890public boolean showVersion() {891return showVersion;892}893894/**895* Argument for command-line option {@code -sourcetab}.896* The specified amount of space between tab stops.897*/898public int sourceTabSize() {899return sourceTabSize;900}901902/**903* Value for command-line option {@code --override-methods summary}904* or {@code --override-methods detail}.905* Specifies whether those methods that override a super-type's method906* with no changes to the API contract should be summarized in the907* footnote section.908*/909public boolean summarizeOverriddenMethods() {910return summarizeOverriddenMethods;911}912913/**914* Argument for command-line option {@code -tagletpath}.915* The path to Taglets916*/917public String tagletPath() {918return tagletPath;919}920921protected abstract static class Option implements Doclet.Option, Comparable<Option> {922private final String[] names;923private final String parameters;924private final String description;925private final int argCount;926927protected Option(Resources resources, String name, int argCount) {928this(resources, null, name, argCount);929}930931protected Option(Resources resources, String keyBase, String name, int argCount) {932this.names = name.trim().split("\\s+");933if (keyBase == null) {934keyBase = "doclet.usage." + Utils.toLowerCase(names[0]).replaceAll("^-+", "");935}936String desc = getOptionsMessage(resources, keyBase + ".description");937if (desc.isEmpty()) {938this.description = "<MISSING KEY>";939this.parameters = "<MISSING KEY>";940} else {941this.description = desc;942this.parameters = getOptionsMessage(resources, keyBase + ".parameters");943}944this.argCount = argCount;945}946947protected Option(Resources resources, String name) {948this(resources, name, 0);949}950951private String getOptionsMessage(Resources resources, String key) {952try {953return resources.getText(key);954} catch (MissingResourceException ignore) {955return "";956}957}958959@Override960public String getDescription() {961return description;962}963964@Override965public Kind getKind() {966return Kind.STANDARD;967}968969@Override970public List<String> getNames() {971return Arrays.asList(names);972}973974@Override975public String getParameters() {976return parameters;977}978979@Override980public String toString() {981return Arrays.toString(names);982}983984@Override985public int getArgumentCount() {986return argCount;987}988989public boolean matches(String option) {990for (String name : names) {991boolean matchCase = name.startsWith("--");992if (option.startsWith("--") && option.contains("=")) {993return name.equals(option.substring(option.indexOf("=") + 1));994} else if (matchCase) {995return name.equals(option);996}997return name.equalsIgnoreCase(option);998}999return false;1000}10011002@Override1003public int compareTo(Option that) {1004return this.getNames().get(0).compareTo(that.getNames().get(0));1005}1006}10071008protected abstract static class XOption extends Option {10091010public XOption(Resources resources, String prefix, String name, int argCount) {1011super(resources, prefix, name, argCount);1012}10131014public XOption(Resources resources, String name, int argCount) {1015super(resources, name, argCount);1016}10171018public XOption(Resources resources, String name) {1019this(resources, name, 0);1020}10211022@Override1023public Option.Kind getKind() {1024return Kind.EXTENDED;1025}1026}10271028protected abstract static class Hidden extends Option {10291030public Hidden(Resources resources, String name, int argCount) {1031super(resources, name, argCount);1032}10331034public Hidden(Resources resources, String name) {1035this(resources, name, 0);1036}10371038@Override1039public Option.Kind getKind() {1040return Kind.OTHER;1041}1042}1043}104410451046