feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -0,0 +1,989 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, 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.internal.toolkit;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.tools.JavaFileManager;
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
import com.sun.tools.javac.sym.Profiles;
|
||||
import com.sun.tools.javac.jvm.Profile;
|
||||
import com.sun.tools.doclets.internal.toolkit.builders.BuilderFactory;
|
||||
import com.sun.tools.doclets.internal.toolkit.taglets.*;
|
||||
import com.sun.tools.doclets.internal.toolkit.util.*;
|
||||
import com.sun.tools.javac.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Configure the output based on the options. Doclets should sub-class
|
||||
* Configuration, to configure and add their own options. This class contains
|
||||
* all user options which are supported by the 1.1 doclet and the standard
|
||||
* doclet.
|
||||
*
|
||||
* <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
|
||||
*/
|
||||
public abstract class Configuration {
|
||||
|
||||
/**
|
||||
* Exception used to report a problem during setOptions.
|
||||
*/
|
||||
public static class Fault extends Exception {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
Fault(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
Fault(String msg, Exception cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory for builders.
|
||||
*/
|
||||
protected BuilderFactory builderFactory;
|
||||
|
||||
/**
|
||||
* The taglet manager.
|
||||
*/
|
||||
public TagletManager tagletManager;
|
||||
|
||||
/**
|
||||
* The path to the builder XML input file.
|
||||
*/
|
||||
public String builderXMLPath;
|
||||
|
||||
/**
|
||||
* The default path to the builder XML.
|
||||
*/
|
||||
private static final String DEFAULT_BUILDER_XML = "resources/doclet.xml";
|
||||
|
||||
/**
|
||||
* The path to Taglets
|
||||
*/
|
||||
public String tagletpath = "";
|
||||
|
||||
/**
|
||||
* This is true if option "-serialwarn" is used. Defualt value is false to
|
||||
* suppress excessive warnings about serial tag.
|
||||
*/
|
||||
public boolean serialwarn = false;
|
||||
|
||||
/**
|
||||
* The specified amount of space between tab stops.
|
||||
*/
|
||||
public int sourcetab;
|
||||
|
||||
public String tabSpaces;
|
||||
|
||||
/**
|
||||
* True if we should generate browsable sources.
|
||||
*/
|
||||
public boolean linksource = false;
|
||||
|
||||
/**
|
||||
* True if command line option "-nosince" is used. Default value is
|
||||
* false.
|
||||
*/
|
||||
public boolean nosince = false;
|
||||
|
||||
/**
|
||||
* True if we should recursively copy the doc-file subdirectories
|
||||
*/
|
||||
public boolean copydocfilesubdirs = false;
|
||||
|
||||
/**
|
||||
* The META charset tag used for cross-platform viewing.
|
||||
*/
|
||||
public String charset = "";
|
||||
|
||||
/**
|
||||
* True if user wants to add member names as meta keywords.
|
||||
* Set to false because meta keywords are ignored in general
|
||||
* by most Internet search engines.
|
||||
*/
|
||||
public boolean keywords = false;
|
||||
|
||||
/**
|
||||
* The meta tag keywords instance.
|
||||
*/
|
||||
public final MetaKeywords metakeywords = new MetaKeywords(this);
|
||||
|
||||
/**
|
||||
* The list of doc-file subdirectories to exclude
|
||||
*/
|
||||
protected Set<String> excludedDocFileDirs;
|
||||
|
||||
/**
|
||||
* The list of qualifiers to exclude
|
||||
*/
|
||||
protected Set<String> excludedQualifiers;
|
||||
|
||||
/**
|
||||
* The Root of the generated Program Structure from the Doclet API.
|
||||
*/
|
||||
public RootDoc root;
|
||||
|
||||
/**
|
||||
* Destination directory name, in which doclet will generate the entire
|
||||
* documentation. Default is current directory.
|
||||
*/
|
||||
public String destDirName = "";
|
||||
|
||||
/**
|
||||
* Destination directory name, in which doclet will copy the doc-files to.
|
||||
*/
|
||||
public String docFileDestDirName = "";
|
||||
|
||||
/**
|
||||
* Encoding for this document. Default is default encoding for this
|
||||
* platform.
|
||||
*/
|
||||
public String docencoding = null;
|
||||
|
||||
/**
|
||||
* True if user wants to suppress descriptions and tags.
|
||||
*/
|
||||
public boolean nocomment = false;
|
||||
|
||||
/**
|
||||
* Encoding for this document. Default is default encoding for this
|
||||
* platform.
|
||||
*/
|
||||
public String encoding = null;
|
||||
|
||||
/**
|
||||
* Generate author specific information for all the classes if @author
|
||||
* tag is used in the doc comment and if -author option is used.
|
||||
* <code>showauthor</code> is set to true if -author option is used.
|
||||
* Default is don't show author information.
|
||||
*/
|
||||
public boolean showauthor = false;
|
||||
|
||||
/**
|
||||
* Generate documentation for JavaFX getters and setters automatically
|
||||
* by copying it from the appropriate property definition.
|
||||
*/
|
||||
public boolean javafx = false;
|
||||
|
||||
/**
|
||||
* Generate version specific information for the all the classes
|
||||
* if @version tag is used in the doc comment and if -version option is
|
||||
* used. <code>showversion</code> is set to true if -version option is
|
||||
* used.Default is don't show version information.
|
||||
*/
|
||||
public boolean showversion = false;
|
||||
|
||||
/**
|
||||
* Sourcepath from where to read the source files. Default is classpath.
|
||||
*
|
||||
*/
|
||||
public String sourcepath = "";
|
||||
|
||||
/**
|
||||
* Argument for command line option "-Xprofilespath".
|
||||
*/
|
||||
public String profilespath = "";
|
||||
|
||||
/**
|
||||
* Generate profiles documentation if profilespath is set and valid profiles
|
||||
* are present.
|
||||
*/
|
||||
public boolean showProfiles = false;
|
||||
|
||||
/**
|
||||
* Don't generate deprecated API information at all, if -nodeprecated
|
||||
* option is used. <code>nodepracted</code> is set to true if
|
||||
* -nodeprecated option is used. Default is generate deprected API
|
||||
* information.
|
||||
*/
|
||||
public boolean nodeprecated = false;
|
||||
|
||||
/**
|
||||
* The catalog of classes specified on the command-line
|
||||
*/
|
||||
public ClassDocCatalog classDocCatalog;
|
||||
|
||||
/**
|
||||
* Message Retriever for the doclet, to retrieve message from the resource
|
||||
* file for this Configuration, which is common for 1.1 and standard
|
||||
* doclets.
|
||||
*
|
||||
* TODO: Make this private!!!
|
||||
*/
|
||||
public MessageRetriever message = null;
|
||||
|
||||
/**
|
||||
* True if user wants to suppress time stamp in output.
|
||||
* Default is false.
|
||||
*/
|
||||
public boolean notimestamp= false;
|
||||
|
||||
/**
|
||||
* The package grouping instance.
|
||||
*/
|
||||
public final Group group = new Group(this);
|
||||
|
||||
/**
|
||||
* The tracker of external package links.
|
||||
*/
|
||||
public final Extern extern = new Extern(this);
|
||||
|
||||
/**
|
||||
* Return the build date for the doclet.
|
||||
*/
|
||||
public abstract String getDocletSpecificBuildDate();
|
||||
|
||||
/**
|
||||
* This method should be defined in all those doclets(configurations),
|
||||
* which want to derive themselves from this Configuration. This method
|
||||
* can be used to set its own command line options.
|
||||
*
|
||||
* @param options The array of option names and values.
|
||||
* @throws DocletAbortException
|
||||
*/
|
||||
public abstract void setSpecificDocletOptions(String[][] options) throws Fault;
|
||||
|
||||
/**
|
||||
* Return the doclet specific {@link MessageRetriever}
|
||||
* @return the doclet specific MessageRetriever.
|
||||
*/
|
||||
public abstract MessageRetriever getDocletSpecificMsg();
|
||||
|
||||
/**
|
||||
* A profiles object used to access profiles across various pages.
|
||||
*/
|
||||
public Profiles profiles;
|
||||
|
||||
/**
|
||||
* An map of the profiles to packages.
|
||||
*/
|
||||
public Map<String,PackageDoc[]> profilePackages;
|
||||
|
||||
/**
|
||||
* An array of the packages specified on the command-line merged
|
||||
* with the array of packages that contain the classes specified on the
|
||||
* command-line. The array is sorted.
|
||||
*/
|
||||
public PackageDoc[] packages;
|
||||
|
||||
/**
|
||||
* Constructor. Constructs the message retriever with resource file.
|
||||
*/
|
||||
public Configuration() {
|
||||
message =
|
||||
new MessageRetriever(this,
|
||||
"com.sun.tools.doclets.internal.toolkit.resources.doclets");
|
||||
excludedDocFileDirs = new HashSet<String>();
|
||||
excludedQualifiers = new HashSet<String>();
|
||||
setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the builder factory for this doclet.
|
||||
*
|
||||
* @return the builder factory for this doclet.
|
||||
*/
|
||||
public BuilderFactory getBuilderFactory() {
|
||||
if (builderFactory == null) {
|
||||
builderFactory = new BuilderFactory(this);
|
||||
}
|
||||
return builderFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should be defined in all those doclets
|
||||
* which want to inherit from this Configuration. This method
|
||||
* should return the number of arguments to the command line
|
||||
* option (including the option name). For example,
|
||||
* -notimestamp is a single-argument option, so this method would
|
||||
* return 1.
|
||||
*
|
||||
* @param option Command line option under consideration.
|
||||
* @return number of arguments to option (including the
|
||||
* option name). Zero return means option not known.
|
||||
* Negative value means error occurred.
|
||||
*/
|
||||
public int optionLength(String option) {
|
||||
option = StringUtils.toLowerCase(option);
|
||||
if (option.equals("-author") ||
|
||||
option.equals("-docfilessubdirs") ||
|
||||
option.equals("-javafx") ||
|
||||
option.equals("-keywords") ||
|
||||
option.equals("-linksource") ||
|
||||
option.equals("-nocomment") ||
|
||||
option.equals("-nodeprecated") ||
|
||||
option.equals("-nosince") ||
|
||||
option.equals("-notimestamp") ||
|
||||
option.equals("-quiet") ||
|
||||
option.equals("-xnodate") ||
|
||||
option.equals("-version")) {
|
||||
return 1;
|
||||
} else if (option.equals("-d") ||
|
||||
option.equals("-docencoding") ||
|
||||
option.equals("-encoding") ||
|
||||
option.equals("-excludedocfilessubdir") ||
|
||||
option.equals("-link") ||
|
||||
option.equals("-sourcetab") ||
|
||||
option.equals("-noqualifier") ||
|
||||
option.equals("-output") ||
|
||||
option.equals("-sourcepath") ||
|
||||
option.equals("-tag") ||
|
||||
option.equals("-taglet") ||
|
||||
option.equals("-tagletpath") ||
|
||||
option.equals("-xprofilespath")) {
|
||||
return 2;
|
||||
} else if (option.equals("-group") ||
|
||||
option.equals("-linkoffline")) {
|
||||
return 3;
|
||||
} else {
|
||||
return -1; // indicate we don't know about it
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform error checking on the given options.
|
||||
*
|
||||
* @param options the given options to check.
|
||||
* @param reporter the reporter used to report errors.
|
||||
*/
|
||||
public abstract boolean validOptions(String options[][],
|
||||
DocErrorReporter reporter);
|
||||
|
||||
private void initProfiles() throws IOException {
|
||||
if (profilespath.isEmpty())
|
||||
return;
|
||||
|
||||
profiles = Profiles.read(new File(profilespath));
|
||||
|
||||
// Group the packages to be documented by the lowest profile (if any)
|
||||
// in which each appears
|
||||
Map<Profile, List<PackageDoc>> interimResults =
|
||||
new EnumMap<Profile, List<PackageDoc>>(Profile.class);
|
||||
for (Profile p: Profile.values())
|
||||
interimResults.put(p, new ArrayList<PackageDoc>());
|
||||
|
||||
for (PackageDoc pkg: packages) {
|
||||
if (nodeprecated && Util.isDeprecated(pkg)) {
|
||||
continue;
|
||||
}
|
||||
// the getProfile method takes a type name, not a package name,
|
||||
// but isn't particularly fussy about the simple name -- so just use *
|
||||
int i = profiles.getProfile(pkg.name().replace(".", "/") + "/*");
|
||||
Profile p = Profile.lookup(i);
|
||||
if (p != null) {
|
||||
List<PackageDoc> pkgs = interimResults.get(p);
|
||||
pkgs.add(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the profilePackages structure used by the doclet
|
||||
profilePackages = new HashMap<String,PackageDoc[]>();
|
||||
List<PackageDoc> prev = Collections.<PackageDoc>emptyList();
|
||||
int size;
|
||||
for (Map.Entry<Profile,List<PackageDoc>> e: interimResults.entrySet()) {
|
||||
Profile p = e.getKey();
|
||||
List<PackageDoc> pkgs = e.getValue();
|
||||
pkgs.addAll(prev); // each profile contains all lower profiles
|
||||
Collections.sort(pkgs);
|
||||
size = pkgs.size();
|
||||
// For a profile, if there are no packages to be documented, do not add
|
||||
// it to profilePackages map.
|
||||
if (size > 0)
|
||||
profilePackages.put(p.name, pkgs.toArray(new PackageDoc[pkgs.size()]));
|
||||
prev = pkgs;
|
||||
}
|
||||
|
||||
// Generate profiles documentation if any profile contains any
|
||||
// of the packages to be documented.
|
||||
showProfiles = !prev.isEmpty();
|
||||
}
|
||||
|
||||
private void initPackageArray() {
|
||||
Set<PackageDoc> set = new HashSet<PackageDoc>(Arrays.asList(root.specifiedPackages()));
|
||||
ClassDoc[] classes = root.specifiedClasses();
|
||||
for (int i = 0; i < classes.length; i++) {
|
||||
set.add(classes[i].containingPackage());
|
||||
}
|
||||
ArrayList<PackageDoc> results = new ArrayList<PackageDoc>(set);
|
||||
Collections.sort(results);
|
||||
packages = results.toArray(new PackageDoc[] {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the command line options supported by this configuration.
|
||||
*
|
||||
* @param options the two dimensional array of options.
|
||||
*/
|
||||
public void setOptions(String[][] options) throws Fault {
|
||||
LinkedHashSet<String[]> customTagStrs = new LinkedHashSet<String[]>();
|
||||
|
||||
// Some options, specifically -link and -linkoffline, require that
|
||||
// the output directory has already been created: so do that first.
|
||||
for (int oi = 0; oi < options.length; ++oi) {
|
||||
String[] os = options[oi];
|
||||
String opt = StringUtils.toLowerCase(os[0]);
|
||||
if (opt.equals("-d")) {
|
||||
destDirName = addTrailingFileSep(os[1]);
|
||||
docFileDestDirName = destDirName;
|
||||
ensureOutputDirExists();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int oi = 0; oi < options.length; ++oi) {
|
||||
String[] os = options[oi];
|
||||
String opt = StringUtils.toLowerCase(os[0]);
|
||||
if (opt.equals("-docfilessubdirs")) {
|
||||
copydocfilesubdirs = true;
|
||||
} else if (opt.equals("-docencoding")) {
|
||||
docencoding = os[1];
|
||||
} else if (opt.equals("-encoding")) {
|
||||
encoding = os[1];
|
||||
} else if (opt.equals("-author")) {
|
||||
showauthor = true;
|
||||
} else if (opt.equals("-javafx")) {
|
||||
javafx = true;
|
||||
} else if (opt.equals("-nosince")) {
|
||||
nosince = true;
|
||||
} else if (opt.equals("-version")) {
|
||||
showversion = true;
|
||||
} else if (opt.equals("-nodeprecated")) {
|
||||
nodeprecated = true;
|
||||
} else if (opt.equals("-sourcepath")) {
|
||||
sourcepath = os[1];
|
||||
} else if ((opt.equals("-classpath") || opt.equals("-cp")) &&
|
||||
sourcepath.length() == 0) {
|
||||
sourcepath = os[1];
|
||||
} else if (opt.equals("-excludedocfilessubdir")) {
|
||||
addToSet(excludedDocFileDirs, os[1]);
|
||||
} else if (opt.equals("-noqualifier")) {
|
||||
addToSet(excludedQualifiers, os[1]);
|
||||
} else if (opt.equals("-linksource")) {
|
||||
linksource = true;
|
||||
} else if (opt.equals("-sourcetab")) {
|
||||
linksource = true;
|
||||
try {
|
||||
setTabWidth(Integer.parseInt(os[1]));
|
||||
} catch (NumberFormatException e) {
|
||||
//Set to -1 so that warning will be printed
|
||||
//to indicate what is valid argument.
|
||||
sourcetab = -1;
|
||||
}
|
||||
if (sourcetab <= 0) {
|
||||
message.warning("doclet.sourcetab_warning");
|
||||
setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
|
||||
}
|
||||
} else if (opt.equals("-notimestamp")) {
|
||||
notimestamp = true;
|
||||
} else if (opt.equals("-nocomment")) {
|
||||
nocomment = true;
|
||||
} else if (opt.equals("-tag") || opt.equals("-taglet")) {
|
||||
customTagStrs.add(os);
|
||||
} else if (opt.equals("-tagletpath")) {
|
||||
tagletpath = os[1];
|
||||
} else if (opt.equals("-xprofilespath")) {
|
||||
profilespath = os[1];
|
||||
} else if (opt.equals("-keywords")) {
|
||||
keywords = true;
|
||||
} else if (opt.equals("-serialwarn")) {
|
||||
serialwarn = true;
|
||||
} else if (opt.equals("-group")) {
|
||||
group.checkPackageGroups(os[1], os[2]);
|
||||
} else if (opt.equals("-link")) {
|
||||
String url = os[1];
|
||||
extern.link(url, url, root, false);
|
||||
} else if (opt.equals("-linkoffline")) {
|
||||
String url = os[1];
|
||||
String pkglisturl = os[2];
|
||||
extern.link(url, pkglisturl, root, true);
|
||||
}
|
||||
}
|
||||
if (sourcepath.length() == 0) {
|
||||
sourcepath = System.getProperty("env.class.path") == null ? "" :
|
||||
System.getProperty("env.class.path");
|
||||
}
|
||||
if (docencoding == null) {
|
||||
docencoding = encoding;
|
||||
}
|
||||
|
||||
classDocCatalog = new ClassDocCatalog(root.specifiedClasses(), this);
|
||||
initTagletManager(customTagStrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the command line options supported by this configuration.
|
||||
*
|
||||
* @throws DocletAbortException
|
||||
*/
|
||||
public void setOptions() throws Fault {
|
||||
initPackageArray();
|
||||
setOptions(root.options());
|
||||
try {
|
||||
initProfiles();
|
||||
} catch (Exception e) {
|
||||
throw new DocletAbortException(e);
|
||||
}
|
||||
setSpecificDocletOptions(root.options());
|
||||
}
|
||||
|
||||
private void ensureOutputDirExists() throws Fault {
|
||||
DocFile destDir = DocFile.createFileForDirectory(this, destDirName);
|
||||
if (!destDir.exists()) {
|
||||
//Create the output directory (in case it doesn't exist yet)
|
||||
root.printNotice(getText("doclet.dest_dir_create", destDirName));
|
||||
destDir.mkdirs();
|
||||
} else if (!destDir.isDirectory()) {
|
||||
throw new Fault(getText(
|
||||
"doclet.destination_directory_not_directory_0",
|
||||
destDir.getPath()));
|
||||
} else if (!destDir.canWrite()) {
|
||||
throw new Fault(getText(
|
||||
"doclet.destination_directory_not_writable_0",
|
||||
destDir.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the taglet manager. The strings to initialize the simple custom tags should
|
||||
* be in the following format: "[tag name]:[location str]:[heading]".
|
||||
* @param customTagStrs the set two dimensional arrays of strings. These arrays contain
|
||||
* either -tag or -taglet arguments.
|
||||
*/
|
||||
private void initTagletManager(Set<String[]> customTagStrs) {
|
||||
tagletManager = tagletManager == null ?
|
||||
new TagletManager(nosince, showversion, showauthor, javafx, message) :
|
||||
tagletManager;
|
||||
String[] args;
|
||||
for (Iterator<String[]> it = customTagStrs.iterator(); it.hasNext(); ) {
|
||||
args = it.next();
|
||||
if (args[0].equals("-taglet")) {
|
||||
tagletManager.addCustomTag(args[1], getFileManager(), tagletpath);
|
||||
continue;
|
||||
}
|
||||
String[] tokens = tokenize(args[1],
|
||||
TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3);
|
||||
if (tokens.length == 1) {
|
||||
String tagName = args[1];
|
||||
if (tagletManager.isKnownCustomTag(tagName)) {
|
||||
//reorder a standard tag
|
||||
tagletManager.addNewSimpleCustomTag(tagName, null, "");
|
||||
} else {
|
||||
//Create a simple tag with the heading that has the same name as the tag.
|
||||
StringBuilder heading = new StringBuilder(tagName + ":");
|
||||
heading.setCharAt(0, Character.toUpperCase(tagName.charAt(0)));
|
||||
tagletManager.addNewSimpleCustomTag(tagName, heading.toString(), "a");
|
||||
}
|
||||
} else if (tokens.length == 2) {
|
||||
//Add simple taglet without heading, probably to excluding it in the output.
|
||||
tagletManager.addNewSimpleCustomTag(tokens[0], tokens[1], "");
|
||||
} else if (tokens.length >= 3) {
|
||||
tagletManager.addNewSimpleCustomTag(tokens[0], tokens[2], tokens[1]);
|
||||
} else {
|
||||
message.error("doclet.Error_invalid_custom_tag_argument", args[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, return an array of tokens. The separator can be escaped
|
||||
* with the '\' character. The '\' character may also be escaped by the
|
||||
* '\' character.
|
||||
*
|
||||
* @param s the string to tokenize.
|
||||
* @param separator the separator char.
|
||||
* @param maxTokens the maximum number of tokens returned. If the
|
||||
* max is reached, the remaining part of s is appended
|
||||
* to the end of the last token.
|
||||
*
|
||||
* @return an array of tokens.
|
||||
*/
|
||||
private String[] tokenize(String s, char separator, int maxTokens) {
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
StringBuilder token = new StringBuilder ();
|
||||
boolean prevIsEscapeChar = false;
|
||||
for (int i = 0; i < s.length(); i += Character.charCount(i)) {
|
||||
int currentChar = s.codePointAt(i);
|
||||
if (prevIsEscapeChar) {
|
||||
// Case 1: escaped character
|
||||
token.appendCodePoint(currentChar);
|
||||
prevIsEscapeChar = false;
|
||||
} else if (currentChar == separator && tokens.size() < maxTokens-1) {
|
||||
// Case 2: separator
|
||||
tokens.add(token.toString());
|
||||
token = new StringBuilder();
|
||||
} else if (currentChar == '\\') {
|
||||
// Case 3: escape character
|
||||
prevIsEscapeChar = true;
|
||||
} else {
|
||||
// Case 4: regular character
|
||||
token.appendCodePoint(currentChar);
|
||||
}
|
||||
}
|
||||
if (token.length() > 0) {
|
||||
tokens.add(token.toString());
|
||||
}
|
||||
return tokens.toArray(new String[] {});
|
||||
}
|
||||
|
||||
private void addToSet(Set<String> s, String str){
|
||||
StringTokenizer st = new StringTokenizer(str, ":");
|
||||
String current;
|
||||
while(st.hasMoreTokens()){
|
||||
current = st.nextToken();
|
||||
s.add(current);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a trailing file separator, if not found. Remove superfluous
|
||||
* file separators if any. Preserve the front double file separator for
|
||||
* UNC paths.
|
||||
*
|
||||
* @param path Path under consideration.
|
||||
* @return String Properly constructed path string.
|
||||
*/
|
||||
public static String addTrailingFileSep(String path) {
|
||||
String fs = System.getProperty("file.separator");
|
||||
String dblfs = fs + fs;
|
||||
int indexDblfs;
|
||||
while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {
|
||||
path = path.substring(0, indexDblfs) +
|
||||
path.substring(indexDblfs + fs.length());
|
||||
}
|
||||
if (!path.endsWith(fs))
|
||||
path += fs;
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks for the validity of the options used by the user.
|
||||
* This works exactly like
|
||||
* {@link com.sun.javadoc.Doclet#validOptions(String[][],
|
||||
* DocErrorReporter)}. This will validate the options which are shared
|
||||
* by our doclets. For example, this method will flag an error using
|
||||
* the DocErrorReporter if user has used "-nohelp" and "-helpfile" option
|
||||
* together.
|
||||
*
|
||||
* @param options options used on the command line.
|
||||
* @param reporter used to report errors.
|
||||
* @return true if all the options are valid.
|
||||
*/
|
||||
public boolean generalValidOptions(String options[][],
|
||||
DocErrorReporter reporter) {
|
||||
boolean docencodingfound = false;
|
||||
String encoding = "";
|
||||
for (int oi = 0; oi < options.length; oi++) {
|
||||
String[] os = options[oi];
|
||||
String opt = StringUtils.toLowerCase(os[0]);
|
||||
if (opt.equals("-docencoding")) {
|
||||
docencodingfound = true;
|
||||
if (!checkOutputFileEncoding(os[1], reporter)) {
|
||||
return false;
|
||||
}
|
||||
} else if (opt.equals("-encoding")) {
|
||||
encoding = os[1];
|
||||
}
|
||||
}
|
||||
if (!docencodingfound && encoding.length() > 0) {
|
||||
if (!checkOutputFileEncoding(encoding, reporter)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the validity of the given profile. Return false if there are no
|
||||
* valid packages to be documented for the profile.
|
||||
*
|
||||
* @param profileName the profile that needs to be validated.
|
||||
* @return true if the profile has valid packages to be documented.
|
||||
*/
|
||||
public boolean shouldDocumentProfile(String profileName) {
|
||||
return profilePackages.containsKey(profileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the validity of the given Source or Output File encoding on this
|
||||
* platform.
|
||||
*
|
||||
* @param docencoding output file encoding.
|
||||
* @param reporter used to report errors.
|
||||
*/
|
||||
private boolean checkOutputFileEncoding(String docencoding,
|
||||
DocErrorReporter reporter) {
|
||||
OutputStream ost= new ByteArrayOutputStream();
|
||||
OutputStreamWriter osw = null;
|
||||
try {
|
||||
osw = new OutputStreamWriter(ost, docencoding);
|
||||
} catch (UnsupportedEncodingException exc) {
|
||||
reporter.printError(getText("doclet.Encoding_not_supported",
|
||||
docencoding));
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
if (osw != null) {
|
||||
osw.close();
|
||||
}
|
||||
} catch (IOException exc) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given doc-file subdirectory should be excluded and
|
||||
* false otherwise.
|
||||
* @param docfilesubdir the doc-files subdirectory to check.
|
||||
*/
|
||||
public boolean shouldExcludeDocFileDir(String docfilesubdir){
|
||||
if (excludedDocFileDirs.contains(docfilesubdir)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given qualifier should be excluded and false otherwise.
|
||||
* @param qualifier the qualifier to check.
|
||||
*/
|
||||
public boolean shouldExcludeQualifier(String qualifier){
|
||||
if (excludedQualifiers.contains("all") ||
|
||||
excludedQualifiers.contains(qualifier) ||
|
||||
excludedQualifiers.contains(qualifier + ".*")) {
|
||||
return true;
|
||||
} else {
|
||||
int index = -1;
|
||||
while ((index = qualifier.indexOf(".", index + 1)) != -1) {
|
||||
if (excludedQualifiers.contains(qualifier.substring(0, index + 1) + "*")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the qualified name of the <code>ClassDoc</code> if it's qualifier is not excluded. Otherwise,
|
||||
* return the unqualified <code>ClassDoc</code> name.
|
||||
* @param cd the <code>ClassDoc</code> to check.
|
||||
*/
|
||||
public String getClassName(ClassDoc cd) {
|
||||
PackageDoc pd = cd.containingPackage();
|
||||
if (pd != null && shouldExcludeQualifier(cd.containingPackage().name())) {
|
||||
return cd.name();
|
||||
} else {
|
||||
return cd.qualifiedName();
|
||||
}
|
||||
}
|
||||
|
||||
public String getText(String key) {
|
||||
try {
|
||||
//Check the doclet specific properties file.
|
||||
return getDocletSpecificMsg().getText(key);
|
||||
} catch (Exception e) {
|
||||
//Check the shared properties file.
|
||||
return message.getText(key);
|
||||
}
|
||||
}
|
||||
|
||||
public String getText(String key, String a1) {
|
||||
try {
|
||||
//Check the doclet specific properties file.
|
||||
return getDocletSpecificMsg().getText(key, a1);
|
||||
} catch (Exception e) {
|
||||
//Check the shared properties file.
|
||||
return message.getText(key, a1);
|
||||
}
|
||||
}
|
||||
|
||||
public String getText(String key, String a1, String a2) {
|
||||
try {
|
||||
//Check the doclet specific properties file.
|
||||
return getDocletSpecificMsg().getText(key, a1, a2);
|
||||
} catch (Exception e) {
|
||||
//Check the shared properties file.
|
||||
return message.getText(key, a1, a2);
|
||||
}
|
||||
}
|
||||
|
||||
public String getText(String key, String a1, String a2, String a3) {
|
||||
try {
|
||||
//Check the doclet specific properties file.
|
||||
return getDocletSpecificMsg().getText(key, a1, a2, a3);
|
||||
} catch (Exception e) {
|
||||
//Check the shared properties file.
|
||||
return message.getText(key, a1, a2, a3);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Content newContent();
|
||||
|
||||
/**
|
||||
* Get the configuration string as a content.
|
||||
*
|
||||
* @param key the key to look for in the configuration file
|
||||
* @return a content tree for the text
|
||||
*/
|
||||
public Content getResource(String key) {
|
||||
Content c = newContent();
|
||||
c.addContent(getText(key));
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration string as a content.
|
||||
*
|
||||
* @param key the key to look for in the configuration file
|
||||
* @param o string or content argument added to configuration text
|
||||
* @return a content tree for the text
|
||||
*/
|
||||
public Content getResource(String key, Object o) {
|
||||
return getResource(key, o, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration string as a content.
|
||||
*
|
||||
* @param key the key to look for in the configuration file
|
||||
* @param o string or content argument added to configuration text
|
||||
* @return a content tree for the text
|
||||
*/
|
||||
public Content getResource(String key, Object o1, Object o2) {
|
||||
return getResource(key, o1, o2, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration string as a content.
|
||||
*
|
||||
* @param key the key to look for in the configuration file
|
||||
* @param o1 string or content argument added to configuration text
|
||||
* @param o2 string or content argument added to configuration text
|
||||
* @return a content tree for the text
|
||||
*/
|
||||
public Content getResource(String key, Object o0, Object o1, Object o2) {
|
||||
Content c = newContent();
|
||||
Pattern p = Pattern.compile("\\{([012])\\}");
|
||||
String text = getText(key);
|
||||
Matcher m = p.matcher(text);
|
||||
int start = 0;
|
||||
while (m.find(start)) {
|
||||
c.addContent(text.substring(start, m.start()));
|
||||
|
||||
Object o = null;
|
||||
switch (m.group(1).charAt(0)) {
|
||||
case '0': o = o0; break;
|
||||
case '1': o = o1; break;
|
||||
case '2': o = o2; break;
|
||||
}
|
||||
|
||||
if (o == null) {
|
||||
c.addContent("{" + m.group(1) + "}");
|
||||
} else if (o instanceof String) {
|
||||
c.addContent((String) o);
|
||||
} else if (o instanceof Content) {
|
||||
c.addContent((Content) o);
|
||||
}
|
||||
|
||||
start = m.end();
|
||||
}
|
||||
|
||||
c.addContent(text.substring(start));
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the ClassDoc element is getting documented, depending upon
|
||||
* -nodeprecated option and the deprecation information. Return true if
|
||||
* -nodeprecated is not used. Return false if -nodeprecated is used and if
|
||||
* either ClassDoc element is deprecated or the containing package is deprecated.
|
||||
*
|
||||
* @param cd the ClassDoc for which the page generation is checked
|
||||
*/
|
||||
public boolean isGeneratedDoc(ClassDoc cd) {
|
||||
if (!nodeprecated) {
|
||||
return true;
|
||||
}
|
||||
return !(Util.isDeprecated(cd) || Util.isDeprecated(cd.containingPackage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the doclet specific instance of a writer factory.
|
||||
* @return the {@link WriterFactory} for the doclet.
|
||||
*/
|
||||
public abstract WriterFactory getWriterFactory();
|
||||
|
||||
/**
|
||||
* Return the input stream to the builder XML.
|
||||
*
|
||||
* @return the input steam to the builder XML.
|
||||
* @throws FileNotFoundException when the given XML file cannot be found.
|
||||
*/
|
||||
public InputStream getBuilderXML() throws IOException {
|
||||
return builderXMLPath == null ?
|
||||
Configuration.class.getResourceAsStream(DEFAULT_BUILDER_XML) :
|
||||
DocFile.createFileForInput(this, builderXMLPath).openInputStream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Locale for this document.
|
||||
*/
|
||||
public abstract Locale getLocale();
|
||||
|
||||
/**
|
||||
* Return the current file manager.
|
||||
*/
|
||||
public abstract JavaFileManager getFileManager();
|
||||
|
||||
/**
|
||||
* Return the comparator that will be used to sort member documentation.
|
||||
* To no do any sorting, return null.
|
||||
*
|
||||
* @return the {@link java.util.Comparator} used to sort members.
|
||||
*/
|
||||
public abstract Comparator<ProgramElementDoc> getMemberComparator();
|
||||
|
||||
private void setTabWidth(int n) {
|
||||
sourcetab = n;
|
||||
tabSpaces = String.format("%" + n + "s", "");
|
||||
}
|
||||
|
||||
public abstract boolean showMessage(SourcePosition pos, String key);
|
||||
}
|
||||
Reference in New Issue
Block a user