All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.tools.ant.taskdefs.Javadoc Maven / Gradle / Ivy

There is a newer version: 1.0-rc5
Show newest version
/*
 * Copyright  2000-2005 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.apache.tools.ant.taskdefs;

import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.DirSet;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.PatternSet;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.JavaEnvUtils;

/**
 * Generates Javadoc documentation for a collection
 * of source code.
 *
 * 

Current known limitations are: * *

    *
  • patterns must be of the form "xxx.*", every other pattern doesn't * work. *
  • there is no control on arguments sanity since they are left * to the javadoc implementation. *
* *

If no doclet is set, then the version and * author are by default "yes". * *

Note: This task is run on another VM because the Javadoc code calls * System.exit() which would break Ant functionality. * * * @since Ant 1.1 * * @ant.task category="java" */ public class Javadoc extends Task { /** * Inner class used to manage doclet parameters. */ public class DocletParam { /** The parameter name */ private String name; /** The parameter value */ private String value; /** * Set the name of the parameter. * * @param name the name of the doclet parameter */ public void setName(String name) { this.name = name; } /** * Get the parameter name. * * @return the parameter's name. */ public String getName() { return name; } /** * Set the parameter value. * * Note that only string values are supported. No resolution of file * paths is performed. * * @param value the parameter value. */ public void setValue(String value) { this.value = value; } /** * Get the parameter value. * * @return the parameter value. */ public String getValue() { return value; } } /** * A project aware class used for Javadoc extensions which take a name * and a path such as doclet and taglet arguments. * */ public static class ExtensionInfo extends ProjectComponent { /** The name of the extension */ private String name; /** The optional path to use to load the extension */ private Path path; /** * Set the name of the extension * * @param name the extension's name. */ public void setName(String name) { this.name = name; } /** * Get the name of the extension. * * @return the extension's name. */ public String getName() { return name; } /** * Set the path to use when loading the component. * * @param path a Path instance containing the classpath to use. */ public void setPath(Path path) { if (this.path == null) { this.path = path; } else { this.path.append(path); } } /** * Get the extension's path. * * @return the path to be used to load the extension. * May be null */ public Path getPath() { return path; } /** * Create an empty nested path to be configured by Ant with the * classpath for the extension. * * @return a new Path instance to be configured. */ public Path createPath() { if (path == null) { path = new Path(getProject()); } return path.createPath(); } /** * Adds a reference to a CLASSPATH defined elsewhere. * * @param r the reference containing the path. */ public void setPathRef(Reference r) { createPath().setRefid(r); } } /** * This class stores info about doclets. * */ public class DocletInfo extends ExtensionInfo { /** Collection of doclet parameters. */ private Vector params = new Vector(); /** * Create a doclet parameter to be configured by Ant. * * @return a new DocletParam instance to be configured. */ public DocletParam createParam() { DocletParam param = new DocletParam(); params.addElement(param); return param; } /** * Get the doclet's parameters. * * @return an Enumeration of DocletParam instances. */ public Enumeration getParams() { return params.elements(); } } /** * Used to track info about the packages to be javadoc'd */ public static class PackageName { /** The package name */ private String name; /** * Set the name of the package * * @param name the package name. */ public void setName(String name) { this.name = name.trim(); } /** * Get the package name. * * @return the package's name. */ public String getName() { return name; } /** * @see java.lang.Object#toString */ public String toString() { return getName(); } } /** * This class is used to manage the source files to be processed. */ public static class SourceFile { /** The source file */ private File file; /** * Default constructor */ public SourceFile() { } /** * Constructor specifying the source file directly * * @param file the source file */ public SourceFile(File file) { this.file = file; } /** * Set the source file. * * @param file the source file. */ public void setFile(File file) { this.file = file; } /** * Get the source file. * * @return the source file. */ public File getFile() { return file; } } /** * An HTML element in the javadoc. * * This class is used for those javadoc elements which contain HTML such as * footers, headers, etc. */ public static class Html { /** The text for the element */ private StringBuffer text = new StringBuffer(); /** * Add text to the element. * * @param t the text to be added. */ public void addText(String t) { text.append(t); } /** * Get the current text for the element. * * @return the current text. */ public String getText() { return text.substring(0); } } /** * EnumeratedAttribute implementation supporting the javadoc scoping * values. */ public static class AccessType extends EnumeratedAttribute { /** * @see EnumeratedAttribute#getValues(). */ public String[] getValues() { // Protected first so if any GUI tool offers a default // based on enum #0, it will be right. return new String[] {"protected", "public", "package", "private"}; } } /** The command line built to execute Javadoc. */ private Commandline cmd = new Commandline(); /** * Utility method to add an argument to the command line conditionally * based on the given flag. * * @param b the flag which controls if the argument is added. * @param arg the argument value. */ private void addArgIf(boolean b, String arg) { if (b) { cmd.createArgument().setValue(arg); } } /** * Utility method to add a javadoc argument. * * @param key the argument name. * @param value the argument value. */ private void addArgIfNotEmpty(String key, String value) { if (value != null && value.length() != 0) { cmd.createArgument().setValue(key); cmd.createArgument().setValue(value); } else { log("Warning: Leaving out empty argument '" + key + "'", Project.MSG_WARN); } } /** * Flag which indicates if the task should fail if there is a * javadoc error. */ private boolean failOnError = false; private Path sourcePath = null; private File destDir = null; private Vector sourceFiles = new Vector(); private Vector packageNames = new Vector(); private Vector excludePackageNames = new Vector(1); private boolean author = true; private boolean version = true; private DocletInfo doclet = null; private Path classpath = null; private Path bootclasspath = null; private String group = null; private String packageList = null; private Vector links = new Vector(); private Vector groups = new Vector(); private Vector tags = new Vector(); private boolean useDefaultExcludes = true; private Html doctitle = null; private Html header = null; private Html footer = null; private Html bottom = null; private boolean useExternalFile = false; private FileUtils fileUtils = FileUtils.newFileUtils(); private String source = null; private boolean linksource = false; private boolean breakiterator = false; private String noqualifier; private boolean includeNoSourcePackages = false; private boolean old = false; private String executable = null; private Vector fileSets = new Vector(); private Vector packageSets = new Vector(); /** * Work around command line length limit by using an external file * for the sourcefiles. * * @param b true if an external file is to be used. */ public void setUseExternalFile(boolean b) { useExternalFile = b; } /** * Sets whether default exclusions should be used or not. * * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions * should be used, "false"|"off"|"no" when they * shouldn't be used. */ public void setDefaultexcludes(boolean useDefaultExcludes) { this.useDefaultExcludes = useDefaultExcludes; } /** * Set the maximum memory to be used by the javadoc process * * @param max a string indicating the maximum memory according to the * JVM conventions (e.g. 128m is 128 Megabytes) */ public void setMaxmemory(String max) { cmd.createArgument().setValue("-J-Xmx" + max); } /** * Set an additional parameter on the command line * * @param add the additional command line parameter for the javadoc task. */ public void setAdditionalparam(String add) { cmd.createArgument().setLine(add); } /** * Adds a command-line argument. * @since Ant 1.6 */ public Commandline.Argument createArg() { return cmd.createArgument(); } /** * Specify where to find source file * * @param src a Path instance containing the various source directories. */ public void setSourcepath(Path src) { if (sourcePath == null) { sourcePath = src; } else { sourcePath.append(src); } } /** * Create a path to be configured with the locations of the source * files. * * @return a new Path instance to be configured by the Ant core. */ public Path createSourcepath() { if (sourcePath == null) { sourcePath = new Path(getProject()); } return sourcePath.createPath(); } /** * Adds a reference to a CLASSPATH defined elsewhere. * * @param r the reference containing the source path definition. */ public void setSourcepathRef(Reference r) { createSourcepath().setRefid(r); } /** * Set the directory where the Javadoc output will be generated. * * @param dir the destination directory. */ public void setDestdir(File dir) { destDir = dir; cmd.createArgument().setValue("-d"); cmd.createArgument().setFile(destDir); } /** * Set the list of source files to process. * * @param src a comma separated list of source files. */ public void setSourcefiles(String src) { StringTokenizer tok = new StringTokenizer(src, ","); while (tok.hasMoreTokens()) { String f = tok.nextToken(); SourceFile sf = new SourceFile(); sf.setFile(getProject().resolveFile(f.trim())); addSource(sf); } } /** * Add a single source file. * * @param sf the source file to be processed. */ public void addSource(SourceFile sf) { sourceFiles.addElement(sf); } /** * Set the package names to be processed. * * @param packages a comma separated list of packages specs * (may be wildcarded). * * @see #addPackage for wildcard information. */ public void setPackagenames(String packages) { StringTokenizer tok = new StringTokenizer(packages, ","); while (tok.hasMoreTokens()) { String p = tok.nextToken(); PackageName pn = new PackageName(); pn.setName(p); addPackage(pn); } } /** * Add a single package to be processed. * * If the package name ends with ".*" the Javadoc task * will find and process all subpackages. * * @param pn the package name, possibly wildcarded. */ public void addPackage(PackageName pn) { packageNames.addElement(pn); } /** * Set the list of packages to be excluded. * * @param packages a comma separated list of packages to be excluded. * This may not include wildcards. */ public void setExcludePackageNames(String packages) { StringTokenizer tok = new StringTokenizer(packages, ","); while (tok.hasMoreTokens()) { String p = tok.nextToken(); PackageName pn = new PackageName(); pn.setName(p); addExcludePackage(pn); } } /** * Add a package to be excluded from the javadoc run. * * @param pn the name of the package (wildcards are not permitted). */ public void addExcludePackage(PackageName pn) { excludePackageNames.addElement(pn); } /** * Specify the file containing the overview to be included in the generated * documentation. * * @param f the file containing the overview. */ public void setOverview(File f) { cmd.createArgument().setValue("-overview"); cmd.createArgument().setFile(f); } /** * Indicate whether only public classes and members are to be included in * the scope processed * * @param b true if scope is to be public. */ public void setPublic(boolean b) { addArgIf(b, "-public"); } /** * Indicate whether only protected and public classes and members are to * be included in the scope processed * * @param b true if scope is to be protected. */ public void setProtected(boolean b) { addArgIf(b, "-protected"); } /** * Indicate whether only package, protected and public classes and * members are to be included in the scope processed * * @param b true if scope is to be package level. */ public void setPackage(boolean b) { addArgIf(b, "-package"); } /** * Indicate whether all classes and * members are to be included in the scope processed * * @param b true if scope is to be private level. */ public void setPrivate(boolean b) { addArgIf(b, "-private"); } /** * Set the scope to be processed. This is an alternative to the * use of the setPublic, setPrivate, etc methods. It gives better build * file control over what scope is processed. * * @param at the scope to be processed. */ public void setAccess(AccessType at) { cmd.createArgument().setValue("-" + at.getValue()); } /** * Set the class that starts the doclet used in generating the * documentation. * * @param docletName the name of the doclet class. */ public void setDoclet(String docletName) { if (doclet == null) { doclet = new DocletInfo(); doclet.setProject(getProject()); } doclet.setName(docletName); } /** * Set the classpath used to find the doclet class. * * @param docletPath the doclet classpath. */ public void setDocletPath(Path docletPath) { if (doclet == null) { doclet = new DocletInfo(); doclet.setProject(getProject()); } doclet.setPath(docletPath); } /** * Set the classpath used to find the doclet class by reference. * * @param r the reference to the Path instance to use as the doclet * classpath. */ public void setDocletPathRef(Reference r) { if (doclet == null) { doclet = new DocletInfo(); doclet.setProject(getProject()); } doclet.createPath().setRefid(r); } /** * Create a doclet to be used in the documentation generation. * * @return a new DocletInfo instance to be configured. */ public DocletInfo createDoclet() { doclet = new DocletInfo(); return doclet; } /** * Add a taglet * * @param tagletInfo information about the taglet. */ public void addTaglet(ExtensionInfo tagletInfo) { tags.addElement(tagletInfo); } /** * Indicate whether Javadoc should produce old style (JDK 1.1) * documentation. * * This is not supported by JDK 1.1 and has been phased out in JDK 1.4 * * @param b if true attempt to generate old style documentation. */ public void setOld(boolean b) { old = b; } /** * Set the classpath to be used for this javadoc run. * * @param path an Ant Path object containing the compilation * classpath. */ public void setClasspath(Path path) { if (classpath == null) { classpath = path; } else { classpath.append(path); } } /** * Create a Path to be configured with the classpath to use * * @return a new Path instance to be configured with the classpath. */ public Path createClasspath() { if (classpath == null) { classpath = new Path(getProject()); } return classpath.createPath(); } /** * Adds a reference to a CLASSPATH defined elsewhere. * * @param r the reference to an instance defining the classpath. */ public void setClasspathRef(Reference r) { createClasspath().setRefid(r); } /** * Set the boot classpath to use. * * @param path the boot classpath. */ public void setBootclasspath(Path path) { if (bootclasspath == null) { bootclasspath = path; } else { bootclasspath.append(path); } } /** * Create a Path to be configured with the boot classpath * * @return a new Path instance to be configured with the boot classpath. */ public Path createBootclasspath() { if (bootclasspath == null) { bootclasspath = new Path(getProject()); } return bootclasspath.createPath(); } /** * Adds a reference to a CLASSPATH defined elsewhere. * * @param r the reference to an instance defining the bootclasspath. */ public void setBootClasspathRef(Reference r) { createBootclasspath().setRefid(r); } /** * Set the location of the extensions directories. * * @param path the string version of the path. * @deprecated Use the {@link #setExtdirs(Path)} version. */ public void setExtdirs(String path) { cmd.createArgument().setValue("-extdirs"); cmd.createArgument().setValue(path); } /** * Set the location of the extensions directories. * * @param path a path containing the extension directories. */ public void setExtdirs(Path path) { cmd.createArgument().setValue("-extdirs"); cmd.createArgument().setPath(path); } /** * Run javadoc in verbose mode * * @param b true if operation is to be verbose. */ public void setVerbose(boolean b) { addArgIf(b, "-verbose"); } /** * Set the local to use in documentation generation. * * @param locale the locale to use. */ public void setLocale(String locale) { // createArgument(true) is necessary to make sure, -locale // is the first argument (required in 1.3+). cmd.createArgument(true).setValue(locale); cmd.createArgument(true).setValue("-locale"); } /** * Set the encoding name of the source files, * * @param enc the name of the encoding for the source files. */ public void setEncoding(String enc) { cmd.createArgument().setValue("-encoding"); cmd.createArgument().setValue(enc); } /** * Include the version tag in the generated documentation. * * @param b true if the version tag should be included. */ public void setVersion(boolean b) { this.version = b; } /** * Generate the "use" page for each package. * * @param b true if the use page should be generated. */ public void setUse(boolean b) { addArgIf(b, "-use"); } /** * Include the author tag in the generated documentation. * * @param b true if the author tag should be included. */ public void setAuthor(boolean b) { author = b; } /** * Generate a split index * * @param b true if the index should be split into a file per letter. */ public void setSplitindex(boolean b) { addArgIf(b, "-splitindex"); } /** * Set the title to be placed in the HTML <title> tag of the * generated documentation. * * @param title the window title to use. */ public void setWindowtitle(String title) { addArgIfNotEmpty("-windowtitle", title); } /** * Set the title of the generated overview page. * * @param doctitle the Document title. */ public void setDoctitle(String doctitle) { Html h = new Html(); h.addText(doctitle); addDoctitle(h); } /** * Add a document title to use for the overview page. * * @param text the HTML element containing the document title. */ public void addDoctitle(Html text) { doctitle = text; } /** * Set the header text to be placed at the top of each output file. * * @param header the header text */ public void setHeader(String header) { Html h = new Html(); h.addText(header); addHeader(h); } /** * Set the header text to be placed at the top of each output file. * * @param text the header text */ public void addHeader(Html text) { header = text; } /** * Set the footer text to be placed at the bottom of each output file. * * @param footer the footer text. */ public void setFooter(String footer) { Html h = new Html(); h.addText(footer); addFooter(h); } /** * Set the footer text to be placed at the bottom of each output file. * * @param text the footer text. */ public void addFooter(Html text) { footer = text; } /** * Set the text to be placed at the bottom of each output file. * * @param bottom the bottom text. */ public void setBottom(String bottom) { Html h = new Html(); h.addText(bottom); addBottom(h); } /** * Set the text to be placed at the bottom of each output file. * * @param text the bottom text. */ public void addBottom(Html text) { bottom = text; } /** * Link to docs at "url" using package list at "url2" * - separate the URLs by using a space character. * * @param src the offline link specification (url and package list) */ public void setLinkoffline(String src) { if (/*1.2+*/true) { LinkArgument le = createLink(); le.setOffline(true); String linkOfflineError = "The linkoffline attribute must include" + " a URL and a package-list file location separated by a" + " space"; if (src.trim().length() == 0) { throw new BuildException(linkOfflineError); } StringTokenizer tok = new StringTokenizer(src, " ", false); le.setHref(tok.nextToken()); if (!tok.hasMoreTokens()) { throw new BuildException(linkOfflineError); } le.setPackagelistLoc(getProject().resolveFile(tok.nextToken())); } } /** * Group specified packages together in overview page. * * @param src the group packages - a command separated list of group specs, * each one being a group name and package specification separated * by a space. */ public void setGroup(String src) { group = src; } /** * Create links to javadoc output at the given URL. */ public void setLink(String src) { createLink().setHref(src); } /** * Control deprecation infromation * * @param b If true, do not include deprecated information. */ public void setNodeprecated(boolean b) { addArgIf(b, "-nodeprecated"); } /** * Control deprecated list generation * * @param b if true, do not generate deprecated list. */ public void setNodeprecatedlist(boolean b) { addArgIf(b, "-nodeprecatedlist"); } /** * Control class tree generation. * * @param b if true, do not generate class hierarchy. */ public void setNotree(boolean b) { addArgIf(b, "-notree"); } /** * Control generation of index. * * @param b if true, do not generate index. */ public void setNoindex(boolean b) { addArgIf(b, "-noindex"); } /** * Control generation of help link. * * @param b if true, do not generate help link */ public void setNohelp(boolean b) { addArgIf(b, "-nohelp"); } /** * Control generation of the navigation bar. * * @param b if true, do not generate navigation bar. */ public void setNonavbar(boolean b) { addArgIf(b, "-nonavbar"); } /** * Control warnings about serial tag. * * @param b if true, generate warning about the serial tag. */ public void setSerialwarn(boolean b) { addArgIf(b, "-serialwarn"); } /** * Specifies the CSS stylesheet file to use. * * @param f the file with the CSS to use. */ public void setStylesheetfile(File f) { cmd.createArgument().setValue("-stylesheetfile"); cmd.createArgument().setFile(f); } /** * Specifies the HTML help file to use. * * @param f the file containing help content. */ public void setHelpfile(File f) { cmd.createArgument().setValue("-helpfile"); cmd.createArgument().setFile(f); } /** * Output file encoding name. * * @param enc name of the encoding to use. */ public void setDocencoding(String enc) { cmd.createArgument().setValue("-docencoding"); cmd.createArgument().setValue(enc); } /** * The name of a file containing the packages to process. * * @param src the file containing the package list. */ public void setPackageList(String src) { packageList = src; } /** * Create link to javadoc output at the given URL. * * @return link argument to configure */ public LinkArgument createLink() { LinkArgument la = new LinkArgument(); links.addElement(la); return la; } /** * Represents a link triplet (href, whether link is offline, location of the * package list if off line) */ public class LinkArgument { private String href; private boolean offline = false; private File packagelistLoc; private boolean resolveLink = false; public LinkArgument() { } public void setHref(String hr) { href = hr; } public String getHref() { return href; } public void setPackagelistLoc(File src) { packagelistLoc = src; } public File getPackagelistLoc() { return packagelistLoc; } public void setOffline(boolean offline) { this.offline = offline; } public boolean isLinkOffline() { return offline; } /** * Sets whether Ant should resolve the link attribute relative * to the current basedir. * @param resolve a boolean value */ public void setResolveLink(boolean resolve) { this.resolveLink = resolve; } /** * should Ant resolve the link attribute relative to the * current basedir? */ public boolean shouldResolveLink() { return resolveLink; } } /** * Creates and adds a -tag argument. This is used to specify * custom tags. This argument is only available for JavaDoc 1.4, * and will generate a verbose message (and then be ignored) * when run on Java versions below 1.4. */ public TagArgument createTag() { TagArgument ta = new TagArgument(); tags.addElement (ta); return ta; } /** * Scope element verbose names. (Defined here as fields * cannot be static in inner classes.) The first letter * from each element is used to build up the scope string. */ static final String[] SCOPE_ELEMENTS = { "overview", "packages", "types", "constructors", "methods", "fields" }; /** * Class representing a -tag argument. */ public class TagArgument extends FileSet { /** Name of the tag. */ private String name = null; /** Description of the tag to place in the JavaDocs. */ private String description = null; /** Whether or not the tag is enabled. */ private boolean enabled = true; /** * Scope string of the tag. This will form the middle * argument of the -tag parameter when the tag is enabled * (with an X prepended for and is parsed from human-readable form. */ private String scope = "a"; /** Sole constructor. */ public TagArgument () { } /** * Sets the name of the tag. * * @param name The name of the tag. * Must not be null or empty. */ public void setName (String name) { this.name = name; } /** * Sets the description of the tag. This is what appears in * the JavaDoc. * * @param description The description of the tag. * Must not be null or empty. */ public void setDescription (String description) { this.description = description; } /** * Sets the scope of the tag. This is in comma-separated * form, with each element being one of "all" (the default), * "overview", "packages", "types", "constructors", "methods", * "fields". The elements are treated in a case-insensitive * manner. * * @param verboseScope The scope of the tag. * Must not be null, * should not be empty. * * @exception BuildException if all is specified along with * other elements, if any elements are repeated, if no * elements are specified, or if any unrecognised elements are * specified. */ public void setScope (String verboseScope) throws BuildException { verboseScope = verboseScope.toLowerCase(Locale.US); boolean[] elements = new boolean[SCOPE_ELEMENTS.length]; boolean gotAll = false; boolean gotNotAll = false; // Go through the tokens one at a time, updating the // elements array and issuing warnings where appropriate. StringTokenizer tok = new StringTokenizer (verboseScope, ","); while (tok.hasMoreTokens()) { String next = tok.nextToken().trim(); if (next.equals("all")) { if (gotAll) { getProject().log ("Repeated tag scope element: all", Project.MSG_VERBOSE); } gotAll = true; } else { int i; for (i = 0; i < SCOPE_ELEMENTS.length; i++) { if (next.equals (SCOPE_ELEMENTS[i])) { break; } } if (i == SCOPE_ELEMENTS.length) { throw new BuildException ("Unrecognised scope element: " + next); } else { if (elements[i]) { getProject().log ("Repeated tag scope element: " + next, Project.MSG_VERBOSE); } elements[i] = true; gotNotAll = true; } } } if (gotNotAll && gotAll) { throw new BuildException ("Mixture of \"all\" and other scope " + "elements in tag parameter."); } if (!gotNotAll && !gotAll) { throw new BuildException ("No scope elements specified in tag " + "parameter."); } if (gotAll) { this.scope = "a"; } else { StringBuffer buff = new StringBuffer (elements.length); for (int i = 0; i < elements.length; i++) { if (elements[i]) { buff.append (SCOPE_ELEMENTS[i].charAt(0)); } } this.scope = buff.toString(); } } /** * Sets whether or not the tag is enabled. * * @param enabled Whether or not this tag is enabled. */ public void setEnabled (boolean enabled) { this.enabled = enabled; } /** * Returns the -tag parameter this argument represented. * * @exception BuildException if either the name or description * is null or empty. */ public String getParameter () throws BuildException { if (name == null || name.equals("")) { throw new BuildException ("No name specified for custom tag."); } if (description != null) { return name + ":" + (enabled ? "" : "X") + scope + ":" + description; } else { return name; } } } /** * Separates packages on the overview page into whatever * groups you specify, one group per table. */ public GroupArgument createGroup() { GroupArgument ga = new GroupArgument(); groups.addElement(ga); return ga; } public class GroupArgument { private Html title; private Vector packages = new Vector(); public GroupArgument() { } public void setTitle(String src) { Html h = new Html(); h.addText(src); addTitle(h); } public void addTitle(Html text) { title = text; } public String getTitle() { return title != null ? title.getText() : null; } public void setPackages(String src) { StringTokenizer tok = new StringTokenizer(src, ","); while (tok.hasMoreTokens()) { String p = tok.nextToken(); PackageName pn = new PackageName(); pn.setName(p); addPackage(pn); } } public void addPackage(PackageName pn) { packages.addElement(pn); } public String getPackages() { StringBuffer p = new StringBuffer(); for (int i = 0; i < packages.size(); i++) { if (i > 0) { p.append(":"); } p.append(packages.elementAt(i).toString()); } return p.toString(); } } /** * Charset for cross-platform viewing of generated documentation. */ public void setCharset(String src) { this.addArgIfNotEmpty("-charset", src); } /** * Should the build process fail if javadoc fails (as indicated by * a non zero return code)? * *

Default is false.

*/ public void setFailonerror(boolean b) { failOnError = b; } /** * Enables the -source switch, will be ignored if javadoc is not * the 1.4 version. * * @since Ant 1.5 */ public void setSource(String source) { this.source = source; } /** * Sets the actual executable command to invoke, instead of the binary * javadoc found in Ant's JDK. * @since Ant 1.6.3 */ public void setExecutable(String executable) { this.executable = executable; } /** * Adds a packageset. * *

All included directories will be translated into package * names be converting the directory separator into dots.

* * @since 1.5 */ public void addPackageset(DirSet packageSet) { packageSets.addElement(packageSet); } /** * Adds a fileset. * *

All included files will be added as sourcefiles. The task * will automatically add * includes="**/*.java" to the * fileset.

* * @since 1.5 */ public void addFileset(FileSet fs) { fileSets.addElement(fs); } /** * Enables the -linksource switch, will be ignored if javadoc is not * the 1.4 version. Default is false * * @since Ant 1.6 */ public void setLinksource(boolean b) { this.linksource = b; } /** * Enables the -linksource switch, will be ignored if javadoc is not * the 1.4 version. Default is false * * @since Ant 1.6 */ public void setBreakiterator(boolean b) { this.breakiterator = b; } /** * Enables the -noqualifier switch, will be ignored if javadoc is not * the 1.4 version. * * @since Ant 1.6 */ public void setNoqualifier(String noqualifier) { this.noqualifier = noqualifier; } /** * If set to true, Ant will also accept packages that only hold * package.html files but no Java sources. * @since Ant 1.6.3 */ public void setIncludeNoSourcePackages(boolean b) { this.includeNoSourcePackages = b; } public void execute() throws BuildException { if ("javadoc2".equals(getTaskType())) { log("!! javadoc2 is deprecated. Use javadoc instead. !!"); } // Whether *this VM* is 1.4+ (but also check executable != null). boolean javadoc4 = !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2) && !JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3); Vector packagesToDoc = new Vector(); Path sourceDirs = new Path(getProject()); if (packageList != null && sourcePath == null) { String msg = "sourcePath attribute must be set when " + "specifying packagelist."; throw new BuildException(msg); } if (sourcePath != null) { sourceDirs.addExisting(sourcePath); } parsePackages(packagesToDoc, sourceDirs); if (packagesToDoc.size() != 0 && sourceDirs.size() == 0) { String msg = "sourcePath attribute must be set when " + "specifying package names."; throw new BuildException(msg); } Vector sourceFilesToDoc = (Vector) sourceFiles.clone(); addFileSets(sourceFilesToDoc); if (packageList == null && packagesToDoc.size() == 0 && sourceFilesToDoc.size() == 0) { throw new BuildException("No source files and no packages have " + "been specified."); } log("Generating Javadoc", Project.MSG_INFO); Commandline toExecute = (Commandline) cmd.clone(); if (executable != null) { toExecute.setExecutable(executable); } else { toExecute.setExecutable(JavaEnvUtils.getJdkExecutable("javadoc")); } // ------------------------------------------ general javadoc arguments if (doctitle != null) { toExecute.createArgument().setValue("-doctitle"); toExecute.createArgument().setValue(expand(doctitle.getText())); } if (header != null) { toExecute.createArgument().setValue("-header"); toExecute.createArgument().setValue(expand(header.getText())); } if (footer != null) { toExecute.createArgument().setValue("-footer"); toExecute.createArgument().setValue(expand(footer.getText())); } if (bottom != null) { toExecute.createArgument().setValue("-bottom"); toExecute.createArgument().setValue(expand(bottom.getText())); } if (classpath == null) { classpath = (new Path(getProject())).concatSystemClasspath("last"); } else { classpath = classpath.concatSystemClasspath("ignore"); } if (/*1.2+*/true) { if (classpath.size() > 0) { toExecute.createArgument().setValue("-classpath"); toExecute.createArgument().setPath(classpath); } if (sourceDirs.size() > 0) { toExecute.createArgument().setValue("-sourcepath"); toExecute.createArgument().setPath(sourceDirs); } } if (version && doclet == null) { toExecute.createArgument().setValue("-version"); } if (author && doclet == null) { toExecute.createArgument().setValue("-author"); } if (doclet == null) { if (destDir == null) { String msg = "destDir attribute must be set!"; throw new BuildException(msg); } } // ---------------------------- javadoc2 arguments for default doclet if (/*1.2+*/true) { if (doclet != null) { if (doclet.getName() == null) { throw new BuildException("The doclet name must be " + "specified.", getLocation()); } else { toExecute.createArgument().setValue("-doclet"); toExecute.createArgument().setValue(doclet.getName()); if (doclet.getPath() != null) { Path docletPath = doclet.getPath().concatSystemClasspath("ignore"); if (docletPath.size() != 0) { toExecute.createArgument().setValue("-docletpath"); toExecute.createArgument().setPath(docletPath); } } for (Enumeration e = doclet.getParams(); e.hasMoreElements();) { DocletParam param = (DocletParam) e.nextElement(); if (param.getName() == null) { throw new BuildException("Doclet parameters must " + "have a name"); } toExecute.createArgument().setValue(param.getName()); if (param.getValue() != null) { toExecute.createArgument() .setValue(param.getValue()); } } } } if (bootclasspath != null && bootclasspath.size() > 0) { toExecute.createArgument().setValue("-bootclasspath"); toExecute.createArgument().setPath(bootclasspath); } // add the links arguments if (links.size() != 0) { for (Enumeration e = links.elements(); e.hasMoreElements();) { LinkArgument la = (LinkArgument) e.nextElement(); if (la.getHref() == null || la.getHref().length() == 0) { log("No href was given for the link - skipping", Project.MSG_VERBOSE); continue; } String link = null; if (la.shouldResolveLink()) { File hrefAsFile = getProject().resolveFile(la.getHref()); if (hrefAsFile.exists()) { try { link = fileUtils.getFileURL(hrefAsFile) .toExternalForm(); } catch (MalformedURLException ex) { // should be impossible log("Warning: link location was invalid " + hrefAsFile, Project.MSG_WARN); } } } if (link == null) { // is the href a valid URL try { URL base = new URL("file://."); new URL(base, la.getHref()); link = la.getHref(); } catch (MalformedURLException mue) { // ok - just skip log("Link href \"" + la.getHref() + "\" is not a valid url - skipping link", Project.MSG_WARN); continue; } } if (la.isLinkOffline()) { File packageListLocation = la.getPackagelistLoc(); if (packageListLocation == null) { throw new BuildException("The package list " + " location for link " + la.getHref() + " must be provided because the link is " + "offline"); } File packageListFile = new File(packageListLocation, "package-list"); if (packageListFile.exists()) { try { String packageListURL = fileUtils.getFileURL(packageListLocation) .toExternalForm(); toExecute.createArgument() .setValue("-linkoffline"); toExecute.createArgument() .setValue(link); toExecute.createArgument() .setValue(packageListURL); } catch (MalformedURLException ex) { log("Warning: Package list location was " + "invalid " + packageListLocation, Project.MSG_WARN); } } else { log("Warning: No package list was found at " + packageListLocation, Project.MSG_VERBOSE); } } else { toExecute.createArgument().setValue("-link"); toExecute.createArgument().setValue(link); } } } // add the single group arguments // Javadoc 1.2 rules: // Multiple -group args allowed. // Each arg includes 3 strings: -group [name] [packagelist]. // Elements in [packagelist] are colon-delimited. // An element in [packagelist] may end with the * wildcard. // Ant javadoc task rules for group attribute: // Args are comma-delimited. // Each arg is 2 space-delimited strings. // E.g., group="XSLT_Packages org.apache.xalan.xslt*, // XPath_Packages org.apache.xalan.xpath*" if (group != null) { StringTokenizer tok = new StringTokenizer(group, ",", false); while (tok.hasMoreTokens()) { String grp = tok.nextToken().trim(); int space = grp.indexOf(" "); if (space > 0) { String name = grp.substring(0, space); String pkgList = grp.substring(space + 1); toExecute.createArgument().setValue("-group"); toExecute.createArgument().setValue(name); toExecute.createArgument().setValue(pkgList); } } } // add the group arguments if (groups.size() != 0) { for (Enumeration e = groups.elements(); e.hasMoreElements();) { GroupArgument ga = (GroupArgument) e.nextElement(); String title = ga.getTitle(); String packages = ga.getPackages(); if (title == null || packages == null) { throw new BuildException("The title and packages must " + "be specified for group " + "elements."); } toExecute.createArgument().setValue("-group"); toExecute.createArgument().setValue(expand(title)); toExecute.createArgument().setValue(packages); } } // JavaDoc 1.4 parameters if (javadoc4 || executable != null) { for (Enumeration e = tags.elements(); e.hasMoreElements();) { Object element = e.nextElement(); if (element instanceof TagArgument) { TagArgument ta = (TagArgument) element; File tagDir = ta.getDir(getProject()); if (tagDir == null) { // The tag element is not used as a fileset, // but specifies the tag directly. toExecute.createArgument().setValue ("-tag"); toExecute.createArgument().setValue (ta.getParameter()); } else { // The tag element is used as a fileset. Parse all the files and // create -tag arguments. DirectoryScanner tagDefScanner = ta.getDirectoryScanner(getProject()); String[] files = tagDefScanner.getIncludedFiles(); for (int i = 0; i < files.length; i++) { File tagDefFile = new File(tagDir, files[i]); try { BufferedReader in = new BufferedReader(new FileReader(tagDefFile)); String line = null; while ((line = in.readLine()) != null) { toExecute.createArgument().setValue ("-tag"); toExecute.createArgument().setValue (line); } in.close(); } catch (IOException ioe) { throw new BuildException("Couldn't read " + " tag file from " + tagDefFile.getAbsolutePath(), ioe); } } } } else { ExtensionInfo tagletInfo = (ExtensionInfo) element; toExecute.createArgument().setValue("-taglet"); toExecute.createArgument().setValue(tagletInfo .getName()); if (tagletInfo.getPath() != null) { Path tagletPath = tagletInfo.getPath() .concatSystemClasspath("ignore"); if (tagletPath.size() != 0) { toExecute.createArgument() .setValue("-tagletpath"); toExecute.createArgument().setPath(tagletPath); } } } } if (source != null) { toExecute.createArgument().setValue("-source"); toExecute.createArgument().setValue(source); } if (linksource && doclet == null) { toExecute.createArgument().setValue("-linksource"); } if (breakiterator && doclet == null) { toExecute.createArgument().setValue("-breakiterator"); } if (noqualifier != null && doclet == null) { toExecute.createArgument().setValue("-noqualifier"); toExecute.createArgument().setValue(noqualifier); } } else { // Not 1.4+. if (!tags.isEmpty()) { log("-tag and -taglet options not supported on Javadoc < 1.4", Project.MSG_VERBOSE); } if (source != null) { log("-source option not supported on JavaDoc < 1.4", Project.MSG_VERBOSE); } if (linksource) { log("-linksource option not supported on JavaDoc < 1.4", Project.MSG_VERBOSE); } if (breakiterator) { log("-breakiterator option not supported on JavaDoc < 1.4", Project.MSG_VERBOSE); } if (noqualifier != null) { log("-noqualifier option not supported on JavaDoc < 1.4", Project.MSG_VERBOSE); } } // Javadoc 1.2/1.3 parameters: if (!javadoc4 || executable != null) { if (old) { toExecute.createArgument().setValue("-1.1"); } } else { if (old) { log("Javadoc 1.4 doesn't support the -1.1 switch anymore", Project.MSG_WARN); } } } File tmpList = null; PrintWriter srcListWriter = null; try { /** * Write sourcefiles and package names to a temporary file * if requested. */ if (useExternalFile) { if (tmpList == null) { tmpList = fileUtils.createTempFile("javadoc", "", null); tmpList.deleteOnExit(); toExecute.createArgument() .setValue("@" + tmpList.getAbsolutePath()); } srcListWriter = new PrintWriter( new FileWriter(tmpList.getAbsolutePath(), true)); } Enumeration e = packagesToDoc.elements(); while (e.hasMoreElements()) { String packageName = (String) e.nextElement(); if (useExternalFile) { srcListWriter.println(packageName); } else { toExecute.createArgument().setValue(packageName); } } e = sourceFilesToDoc.elements(); while (e.hasMoreElements()) { SourceFile sf = (SourceFile) e.nextElement(); String sourceFileName = sf.getFile().getAbsolutePath(); if (useExternalFile) { if (javadoc4 && sourceFileName.indexOf(" ") > -1) { String name = sourceFileName; if (File.separatorChar == '\\') { name = sourceFileName.replace(File.separatorChar, '/'); } srcListWriter.println("\"" + name + "\""); } else { srcListWriter.println(sourceFileName); } } else { toExecute.createArgument().setValue(sourceFileName); } } } catch (IOException e) { tmpList.delete(); throw new BuildException("Error creating temporary file", e, getLocation()); } finally { if (srcListWriter != null) { srcListWriter.close(); } } if (packageList != null) { toExecute.createArgument().setValue("@" + packageList); } log(toExecute.describeCommand(), Project.MSG_VERBOSE); log("Javadoc execution", Project.MSG_INFO); JavadocOutputStream out = new JavadocOutputStream(Project.MSG_INFO); JavadocOutputStream err = new JavadocOutputStream(Project.MSG_WARN); Execute exe = new Execute(new PumpStreamHandler(out, err)); exe.setAntRun(getProject()); /* * No reason to change the working directory as all filenames and * path components have been resolved already. * * Avoid problems with command line length in some environments. */ exe.setWorkingDirectory(null); try { exe.setCommandline(toExecute.getCommandline()); int ret = exe.execute(); if (ret != 0 && failOnError) { throw new BuildException("Javadoc returned " + ret, getLocation()); } } catch (IOException e) { throw new BuildException("Javadoc failed: " + e, e, getLocation()); } finally { if (tmpList != null) { tmpList.delete(); tmpList = null; } out.logFlush(); err.logFlush(); try { out.close(); err.close(); } catch (IOException e) { // ignore } } } /** * Add the files matched by the nested filesets to the Vector as * SourceFile instances. * * @since 1.5 */ private void addFileSets(Vector sf) { Enumeration e = fileSets.elements(); while (e.hasMoreElements()) { FileSet fs = (FileSet) e.nextElement(); if (!fs.hasPatterns() && !fs.hasSelectors()) { fs = (FileSet) fs.clone(); fs.createInclude().setName("**/*.java"); if (includeNoSourcePackages) { fs.createInclude().setName("**/package.html"); } } File baseDir = fs.getDir(getProject()); DirectoryScanner ds = fs.getDirectoryScanner(getProject()); String[] files = ds.getIncludedFiles(); for (int i = 0; i < files.length; i++) { sf.addElement(new SourceFile(new File(baseDir, files[i]))); } } } /** * Add the directories matched by the nested dirsets to the Vector * and the base directories of the dirsets to the Path. It also * handles the packages and excludepackages attributes and * elements. * * @since 1.5 */ private void parsePackages(Vector pn, Path sp) { Vector addedPackages = new Vector(); Vector dirSets = (Vector) packageSets.clone(); // for each sourcePath entry, add a directoryset with includes // taken from packagenames attribute and nested package // elements and excludes taken from excludepackages attribute // and nested excludepackage elements if (sourcePath != null && packageNames.size() > 0) { PatternSet ps = new PatternSet(); Enumeration e = packageNames.elements(); while (e.hasMoreElements()) { PackageName p = (PackageName) e.nextElement(); String pkg = p.getName().replace('.', '/'); if (pkg.endsWith("*")) { pkg += "*"; } ps.createInclude().setName(pkg); } e = excludePackageNames.elements(); while (e.hasMoreElements()) { PackageName p = (PackageName) e.nextElement(); String pkg = p.getName().replace('.', '/'); if (pkg.endsWith("*")) { pkg += "*"; } ps.createExclude().setName(pkg); } String[] pathElements = sourcePath.list(); for (int i = 0; i < pathElements.length; i++) { DirSet ds = new DirSet(); ds.setDefaultexcludes(useDefaultExcludes); ds.setDir(new File(pathElements[i])); ds.createPatternSet().addConfiguredPatternset(ps); dirSets.addElement(ds); } } Enumeration e = dirSets.elements(); while (e.hasMoreElements()) { DirSet ds = (DirSet) e.nextElement(); File baseDir = ds.getDir(getProject()); log("scanning " + baseDir + " for packages.", Project.MSG_DEBUG); DirectoryScanner dsc = ds.getDirectoryScanner(getProject()); String[] dirs = dsc.getIncludedDirectories(); boolean containsPackages = false; for (int i = 0; i < dirs.length; i++) { // are there any java files in this directory? File pd = new File(baseDir, dirs[i]); String[] files = pd.list(new FilenameFilter () { public boolean accept(File dir1, String name) { return name.endsWith(".java") || (includeNoSourcePackages && name.equals("package.html")); } }); if (files.length > 0) { containsPackages = true; String packageName = dirs[i].replace(File.separatorChar, '.'); if (!addedPackages.contains(packageName)) { addedPackages.addElement(packageName); pn.addElement(packageName); } } } if (containsPackages) { // We don't need to care for duplicates here, // Path.list does it for us. sp.createPathElement().setLocation(baseDir); } else { log(baseDir + " doesn\'t contain any packages, dropping it.", Project.MSG_VERBOSE); } } } private class JavadocOutputStream extends LogOutputStream { JavadocOutputStream(int level) { super(Javadoc.this, level); } // // Override the logging of output in order to filter out Generating // messages. Generating messages are set to a priority of VERBOSE // unless they appear after what could be an informational message. // private String queuedLine = null; protected void processLine(String line, int messageLevel) { if (messageLevel == Project.MSG_INFO && line.startsWith("Generating ")) { if (queuedLine != null) { super.processLine(queuedLine, Project.MSG_VERBOSE); } queuedLine = line; } else { if (queuedLine != null) { if (line.startsWith("Building ")) { super.processLine(queuedLine, Project.MSG_VERBOSE); } else { super.processLine(queuedLine, Project.MSG_INFO); } queuedLine = null; } super.processLine(line, messageLevel); } } protected void logFlush() { if (queuedLine != null) { super.processLine(queuedLine, Project.MSG_VERBOSE); queuedLine = null; } } } /** * Convenience method to expand properties. */ protected String expand(String content) { return getProject().replaceProperties(content); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy