Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010-2012 Craig S. Dickson (http://craigsdickson.com)
*
* 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 com.squeakysand.jsp.tldgenerator.maven;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.apache.commons.lang.SystemUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.javadoc.options.BootclasspathArtifact;
import org.apache.maven.plugin.javadoc.options.DocletArtifact;
import org.apache.maven.plugin.javadoc.options.JavadocPathArtifact;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.reporting.MavenReportException;
import org.apache.maven.settings.Proxy;
import org.apache.maven.settings.Settings;
import org.apache.maven.toolchain.Toolchain;
import org.apache.maven.toolchain.ToolchainManager;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.codehaus.plexus.util.cli.Commandline;
/**
* Processes a set of annotated Java classes and also directories containing tag files (.tag and .tagx files) to generate a Tag
* Library Descriptor (.tld) file.
*
* @goal generate
* @phase process-sources
* @requiresDependencyResolution compile
*/
public class TldGeneratorMojo extends AbstractMojo {
/*
* Much of this code was inspired by the existing classes in org.apache.maven.plugin.javadoc, However due to the design of the code in that package and the
* poor support for extending existing plugins within the Maven framework, the code was replicated here instead of just being able to extend it.
*/
/** The Javadoc script file name when debug parameter is on, i.e. javadoc.bat or javadoc.sh */
private static final String DEBUG_JAVADOC_SCRIPT_NAME = "javadoc." + (SystemUtils.IS_OS_WINDOWS ? "bat" : "sh");
/**
* The options file name in the output directory when calling:
* javadoc.exe(or .sh) @options @packages | @argfile | @files
*/
private static final String OPTIONS_FILE_NAME = "options";
/**
* The packages file name in the output directory when calling:
* javadoc.exe(or .sh) @options @packages | @argfile | @files
*/
private static final String PACKAGES_FILE_NAME = "packages";
/**
* The argfile file name in the output directory when calling:
* javadoc.exe(or .sh) @options @packages | @argfile | @files
*/
private static final String ARGFILE_FILE_NAME = "argfile";
/**
* The files file name in the output directory when calling:
* javadoc.exe(or .sh) @options @packages | @argfile | @files
*/
private static final String FILES_FILE_NAME = "files";
/**
* For Javadoc options appears since Java 1.4. See What's
* New in Javadoc 1.4
*/
private static final float SINCE_JAVADOC_1_4 = 1.4f;
/**
* For Javadoc options appears since Java 5.0. See What's New in Javadoc 5.0
*/
private static final float SINCE_JAVADOC_1_5 = 1.5f;
/** Error message when VM could not be started using invoker. */
private static final String ERROR_INIT_VM = "Error occurred during initialization of VM, try to reduce the Java heap size for the MAVEN_OPTS "
+ "environnement variable using -Xms: and -Xmx:.";
/**
* Factory for creating artifact objects
*
* @component
*/
private ArtifactFactory artifactFactory;
/**
* Used to resolve artifacts of aggregated modules
*
* @component
*/
private ArtifactMetadataSource artifactMetadataSource;
/**
* Used for resolving artifacts
*
* @component
*/
private ArtifactResolver artifactResolver;
/**
* Project builder
*
* @component
*/
private MavenProjectBuilder mavenProjectBuilder;
/**
* @component
*/
private ToolchainManager toolchainManager;
/**
* The current build session instance. This is used for toolchain manager API calls.
*
* @parameter expression="${session}"
* @required
* @readonly
*/
private MavenSession session;
/**
* The Maven Settings.
*
* @parameter default-value="${settings}"
* @required
* @readonly
*/
private Settings settings;
/**
* The Maven Project Object
*
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* @readonly
* @expression="${maven.dependency.com.squeakysand.jsp.jsptld-maven-plugin.jar.version "
*/
private String tldGeneratorDocletVersion;
/**
* The local repository where the artifacts are located.
*
* @parameter expression="${localRepository}"
*/
private ArtifactRepository localRepository;
/**
* The remote repositories where artifacts are located.
*
* @parameter expression="${project.remoteArtifactRepositories}"
*/
private List remoteRepositories;
/**
* Sets the absolute path of the Javadoc Tool executable to use. Since version 2.5, a mere directory specification is sufficient to have the plugin use
* "javadoc" or "javadoc.exe" respectively from this directory.
*/
private String javadocExecutable;
/**
* Version of the Javadoc Tool executable to use as float.
*/
private float fJavadocVersion = 0.0f;
/**
* Specifies if the build will fail if there are errors during execution or not.
*
* @parameter expression="${maven.javadoc.failOnError}" default-value="true"
* @readonly
*/
private boolean failOnError;
/**
* Specifies the encoding name of the source files. If not specificed, the encoding value will be the value of the file.encoding system
* property.
*
* @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
*/
private String encoding;
/**
* Unconditionally excludes the specified packages and their subpackages from the list formed by -subpackages. Multiple packages can be
* separated by commas (,), colons (:) or semicolons (;).
* Example:
*
*
*
* @parameter expression="${excludePackageNames}"
*/
private String excludePackageNames;
/**
* Specifies the maximum Java heap size to be used when launching the Javadoc tool. JVMs refer to this property as the -Xmx parameter. Example:
* '512' or '512m'. The memory unit depends on the JVM used. The units supported could be: k, kb, m, mb,
* g, gb, t, tb. If no unit specified, the default unit is m.
*
* @parameter expression="${maxmemory}"
* @readonly
*/
private String maxmemory;
/**
* Specifies the minimum Java heap size to be used when launching the Javadoc tool. JVMs refer to this property as the -Xms parameter. Example:
* '512' or '512m'. The memory unit depends on the JVM used. The units supported could be: k, kb, m, mb,
* g, gb, t, tb. If no unit specified, the default unit is m.
*
* @parameter expression="${minmemory}"
* @readonly
*/
private String minmemory;
/**
* Specifies the source paths where the subpackages are located. The sourcepath can contain multiple paths by separating them with a colon (
* :) or a semi-colon (;).
*
* @parameter expression="${sourcepath}"
*/
private String sourcepath;
/**
* Specifies the package directory where this plugin will be executed. Multiple packages can be separated by colons (:).
*
* @parameter expression="${subpackages}"
*/
private String subpackages;
/**
* Provides more detailed messages while running.
*
* @parameter expression="${verbose}" default-value="false"
*/
private boolean verbose;
/**
* The description of the Tag Library. Used as the content of the <description> element in the TLD file.
*
* @parameter default-value="${project.description}"
*/
private String description;
/**
* Where the generated TLD file should be written. The default value is the correct location to have the TLD automatically included in a Jar file in the
* correct location (as defined by the JSP Specification) by the normal Maven build process.
*
* @parameter default-value="${project.build.outputDirectory}/META-INF"
* @required
*/
private File outputDirectory;
/**
* The name to use for the generated TLD file.
*
* @parameter default-value="${project.artifactId}-${project.version}.tld"
* @required
*/
private String filename;
/**
* Directory where temporary files created during the generation process can be written.
*
* @parameter default-value="${project.build.directory}/tldgenerator"
* @required
*/
private File workingDirectory;
/**
* The namespace for the Tag Library. Used as the content for the <short-name> element in the TLD file.
*
* @parameter
* @required
*/
private String shortName;
/**
* The minimum JSP specification that this Tag Library requires. Used as the value of the version attribute in the <taglib>
* element in the generated TLD file.
*
* @parameter default-value="2.1"
* @required
*/
private String specificationVersion;
/**
* The version of this Tag Library. Used as the value for the <tlib-version> element in the TLD file.
*
* @parameter default-value="${project.version}"
* @required
*/
private String tlibVersion;
/**
* A base URI namespace to be used when constructing the actual TLD <uri> element. If baseUri is specified but not
* uri, then the <uri> element in the TLD will have the value ${baseUri}/${shortName}/${version}. This is
* useful when there are multiple executions of this Plugin defined within the same pom.xml and all of the resulting TLDs have common root
* URIs.
*
* @parameter
*/
private URI baseUri;
/**
* The URI namespace for this Tag Library. Used as the value of the <uri> element in the generated TLD file. If a value is provided, then
* this WILL be the value of the <uri> element in the TLD. If no value is provided, and also no value is provided for the
* baseUri parameter, then the value of ${project.url} will be used; if ${project.url} has no meaningful value, an
* exception will be thrown.
*
* @parameter default-value="${project.url}
* @required
*/
private URI uri;
/**
* The fully qualified class name of a Tag Library validator. Used as the value of the <validator> element in the generated TLD file.
*
* @parameter
*/
private String validator;
/**
* Indicates if the generator should look for JSP Tag Files when generating the descriptor.
*
* @parameter default-value="false"
*/
private Boolean processTagFiles;
/**
* Where to find the tag file sources.
*
* @parameter default-value="${basedir}/src/main/resources/META-INF/tags"
*/
private File tagfilesSourceDirectory;
/**
* A list of tag file patterns to include. Can contain Ant-style wildcards and double wildcards. Patterns are relative to the value of
* ${tagfilesSourceDirectory}. Default value is ["**\/*.tag","**\/*.tagx"] (ie. include all).
*
* @parameter
*/
private List includeTagFiles;
/**
* A list of tag file patterns to exclude. Can contain Ant-style wildcards and double wildcards. Patterns are relative to the value of
* ${tagfilesSourceDirectory}. Default value is [] (ie. exclude none).
*
* @parameter
*/
private List excludeTagFiles;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
try {
List sourcePaths = getSourcePaths();
List files = getFiles(sourcePaths);
if (!canGenerateReport(files)) {
return;
}
List packageNames = getPackageNames(sourcePaths, files);
List filesWithUnnamedPackages = getFilesWithUnnamedPackages(sourcePaths, files);
// ----------------------------------------------------------------------
// Find the javadoc executable and version
// ----------------------------------------------------------------------
String jExecutable;
try {
jExecutable = getJavadocExecutable();
} catch (IOException e) {
throw new MavenReportException("Unable to find javadoc command: " + e.getMessage(), e);
}
setFJavadocVersion(new File(jExecutable));
// ----------------------------------------------------------------------
// Javadoc output directory as File
// ----------------------------------------------------------------------
if (workingDirectory.exists() && !workingDirectory.isDirectory()) {
throw new MavenReportException("IOException: " + getOutputDirectory() + " is not a directory.");
}
if (workingDirectory.exists() && !workingDirectory.canWrite()) {
throw new MavenReportException("IOException: " + getOutputDirectory() + " is not writable.");
}
workingDirectory.mkdirs();
// ----------------------------------------------------------------------
// Create command line for Javadoc
// ----------------------------------------------------------------------
Commandline cmd = new Commandline();
cmd.getShell().setQuotedArgumentsEnabled(false); // for Javadoc JVM args
cmd.setWorkingDirectory(workingDirectory.getAbsolutePath());
cmd.setExecutable(jExecutable);
// ----------------------------------------------------------------------
// Wrap Javadoc JVM args
// ----------------------------------------------------------------------
addMemoryArg(cmd, "-Xmx", this.maxmemory);
addMemoryArg(cmd, "-Xms", this.minmemory);
addProxyArg(cmd);
List arguments = new ArrayList();
// ----------------------------------------------------------------------
// Wrap Javadoc options
// ----------------------------------------------------------------------
addJavadocOptions(arguments, sourcePaths);
// ----------------------------------------------------------------------
// Wrap Standard doclet Options
// ----------------------------------------------------------------------
addStandardDocletOptions(workingDirectory, arguments);
addTldGeneratorOptions(arguments);
// ----------------------------------------------------------------------
// Write options file and include it in the command line
// ----------------------------------------------------------------------
if (arguments.size() > 0) {
addCommandLineOptions(cmd, arguments, workingDirectory);
}
// ----------------------------------------------------------------------
// Write packages file and include it in the command line
// ----------------------------------------------------------------------
if (!packageNames.isEmpty()) {
addCommandLinePackages(cmd, workingDirectory, packageNames);
// ----------------------------------------------------------------------
// Write argfile file and include it in the command line
// ----------------------------------------------------------------------
if (!filesWithUnnamedPackages.isEmpty()) {
addCommandLineArgFile(cmd, workingDirectory, filesWithUnnamedPackages);
}
} else {
// ----------------------------------------------------------------------
// Write argfile file and include it in the command line
// ----------------------------------------------------------------------
if (!files.isEmpty()) {
addCommandLineArgFile(cmd, workingDirectory, files);
}
}
// ----------------------------------------------------------------------
// Execute command line
// ----------------------------------------------------------------------
executeJavadocCommandLine(cmd, workingDirectory);
} catch (MavenReportException e) {
failOnError("An error has occurred in report generation", e);
} catch (RuntimeException e) {
failOnError("An error has occurred in report generation", e);
}
}
/**
* Convenience method to add an argument to the command line conditionally based on the given flag.
*
* @param arguments a list of arguments, not null
* @param b the flag which controls if the argument is added or not.
* @param value the argument value to be added.
*/
private void addArgIf(List arguments, boolean b, String value) {
if (b) {
arguments.add(value);
}
}
/**
* Convenience method to add an argument to the command line if the the value is not null or empty.
*
* Moreover, the value could be comma separated.
*
* @param arguments a list of arguments, not null
* @param key the argument name.
* @param value the argument value to be added.
* @see #addArgIfNotEmpty(java.util.List,String,String,boolean)
*/
private void addArgIfNotEmpty(List arguments, String key, String value) {
addArgIfNotEmpty(arguments, key, value, false);
}
/**
* Convenience method to add an argument to the command line if the the value is not null or empty.
*
* Moreover, the value could be comma separated.
*
* @param arguments a list of arguments, not null
* @param key the argument name.
* @param value the argument value to be added.
* @param repeatKey repeat or not the key in the command line
*/
private void addArgIfNotEmpty(List arguments, String key, String value, boolean repeatKey) {
addArgIfNotEmpty(arguments, key, value, repeatKey, true);
}
/**
* Convenience method to add an argument to the command line if the the value is not null or empty.
*
* Moreover, the value could be comma separated.
*
* @param arguments a list of arguments, not null
* @param key the argument name.
* @param value the argument value to be added.
* @param repeatKey repeat or not the key in the command line
* @param splitValue if true given value will be tokenized by comma
*/
private void addArgIfNotEmpty(List arguments, String key, String value, boolean repeatKey, boolean splitValue) {
if (StringUtils.isNotEmpty(value)) {
if (StringUtils.isNotEmpty(key)) {
arguments.add(key);
}
if (splitValue) {
StringTokenizer token = new StringTokenizer(value, ",");
while (token.hasMoreTokens()) {
String current = token.nextToken().trim();
if (StringUtils.isNotEmpty(current)) {
arguments.add(current);
if (token.hasMoreTokens() && repeatKey) {
arguments.add(key);
}
}
}
} else {
arguments.add(value);
}
}
}
/**
* Convenience method to add an argument to the command line regarding the requested Java version.
*
* @param arguments a list of arguments, not null
* @param key the argument name.
* @param value the argument value to be added.
* @param requiredJavaVersion the required Java version, for example 1.31f or 1.4f
* @see #addArgIfNotEmpty(java.util.List, String, String, float, boolean)
*/
private void addArgIfNotEmpty(List arguments, String key, String value, float requiredJavaVersion) {
addArgIfNotEmpty(arguments, key, value, requiredJavaVersion, false);
}
/**
* Convenience method to add an argument to the command line regarding the requested Java version.
*
* @param arguments a list of arguments, not null
* @param key the argument name.
* @param value the argument value to be added.
* @param requiredJavaVersion the required Java version, for example 1.31f or 1.4f
* @param repeatKey repeat or not the key in the command line
* @see #addArgIfNotEmpty(java.util.List,String,String)
* @see #isJavaDocVersionAtLeast(float)
*/
private void addArgIfNotEmpty(List arguments, String key, String value, float requiredJavaVersion, boolean repeatKey) {
if (StringUtils.isNotEmpty(value)) {
if (isJavaDocVersionAtLeast(requiredJavaVersion)) {
addArgIfNotEmpty(arguments, key, value, repeatKey);
} else {
if (getLog().isWarnEnabled()) {
getLog().warn(key + " option is not supported on Java version < " + requiredJavaVersion);
}
}
}
}
/**
* Generate a file called argfile (or files, depending the JDK) to hold files and add the @argfile (or
* @file, depending the JDK) in the command line.
*
* @see Reference Guide, Command line argument files
*
* @see What s New in Javadoc 1.4
*
* @param cmd not null
* @param javadocOutputDirectory not null
* @param files not null
* @throws MavenReportException if any
* @see #isJavaDocVersionAtLeast(float)
* @see #ARGFILE_FILE_NAME
* @see #FILES_FILE_NAME
*/
private void addCommandLineArgFile(Commandline cmd, File javadocOutputDirectory, List files) throws MavenReportException {
File argfileFile;
if (isJavaDocVersionAtLeast(SINCE_JAVADOC_1_4)) {
argfileFile = new File(javadocOutputDirectory, ARGFILE_FILE_NAME);
} else {
argfileFile = new File(javadocOutputDirectory, FILES_FILE_NAME);
}
try {
FileUtils.fileWrite(argfileFile.getAbsolutePath(), StringUtils.join(files.iterator(), SystemUtils.LINE_SEPARATOR));
} catch (IOException e) {
throw new MavenReportException("Unable to write '" + argfileFile.getName() + "' temporary file for command execution", e);
}
if (isJavaDocVersionAtLeast(SINCE_JAVADOC_1_4)) {
cmd.createArg().setValue("@" + ARGFILE_FILE_NAME);
} else {
cmd.createArg().setValue("@" + FILES_FILE_NAME);
}
}
private void addCommandLineOptions(Commandline cmd, List arguments, File javadocOutputDirectory) throws MavenReportException {
File optionsFile = new File(javadocOutputDirectory, OPTIONS_FILE_NAME);
StringBuilder options = new StringBuilder();
options.append(StringUtils.join(arguments.toArray(new String[0]), SystemUtils.LINE_SEPARATOR));
try {
FileUtils.fileWrite(optionsFile.getAbsolutePath(), options.toString());
} catch (IOException e) {
throw new MavenReportException("Unable to write '" + optionsFile.getName() + "' temporary file for command execution", e);
}
cmd.createArg().setValue("@" + OPTIONS_FILE_NAME);
}
private void addCommandLinePackages(Commandline cmd, File javadocOutputDirectory, List packageNames) throws MavenReportException {
File packagesFile = new File(javadocOutputDirectory, PACKAGES_FILE_NAME);
try {
FileUtils.fileWrite(packagesFile.getAbsolutePath(), StringUtils.join(packageNames.toArray(new String[0]), SystemUtils.LINE_SEPARATOR));
} catch (IOException e) {
throw new MavenReportException("Unable to write '" + packagesFile.getName() + "' temporary file for command execution", e);
}
cmd.createArg().setValue("@" + PACKAGES_FILE_NAME);
}
/**
* Convenience method that gets the files to be included in the javadoc.
*
* @param sourceDirectory the directory where the source files are located
* @param files the variable that contains the appended filenames of the files to be included in the javadoc
* @param excludePackages the packages to be excluded in the javadocs
*/
private void addFilesFromSource(List files, File sourceDirectory, String[] excludePackages) {
String[] fileList = FileUtils.getFilesFromExtension(sourceDirectory.getPath(), new String[] {"java"});
if (fileList != null && fileList.length != 0) {
List tmpFiles = getIncludedFiles(sourceDirectory, fileList, excludePackages);
files.addAll(tmpFiles);
}
}
private void addJavadocOptions(List arguments, List sourcePaths) throws MavenReportException {
validateJavadocOptions();
addArgIfNotEmpty(arguments, "-bootclasspath", quotedPathArgument(getBootclassPath()));
addArgIfNotEmpty(arguments, "-classpath", quotedPathArgument(getClasspath()));
addArgIfNotEmpty(arguments, "-doclet", quotedArgument("com.squeakysand.jsp.tldgenerator.TldGeneratorDoclet"));
addArgIfNotEmpty(arguments, "-docletpath", quotedPathArgument(getDocletPath()));
if (StringUtils.isEmpty(encoding)) {
getLog().warn("Source files encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING
+ ", i.e. build is platform dependent!");
}
addArgIfNotEmpty(arguments, "-encoding", quotedArgument(getEncoding()));
addArgIfNotEmpty(arguments, "-exclude", getExcludedPackages(sourcePaths), SINCE_JAVADOC_1_4);
addArgIfNotEmpty(arguments, "-source", quotedArgument("1.6"));// , SINCE_JAVADOC_1_4);
if ((StringUtils.isEmpty(sourcepath)) && (StringUtils.isNotEmpty(subpackages))) {
sourcepath = StringUtils.join(sourcePaths.iterator(), File.pathSeparator);
}
addArgIfNotEmpty(arguments, "-sourcepath", quotedPathArgument(getSourcePath(sourcePaths)));
if (StringUtils.isNotEmpty(sourcepath) && isJavaDocVersionAtLeast(SINCE_JAVADOC_1_5)) {
addArgIfNotEmpty(arguments, "-subpackages", subpackages, SINCE_JAVADOC_1_5);
}
addArgIf(arguments, verbose, "-verbose");
}
private void addMemoryArg(Commandline cmd, String arg, String memory) {
if (StringUtils.isNotEmpty(memory)) {
try {
cmd.createArg().setValue("-J" + arg + parseJavadocMemory(memory));
} catch (IllegalArgumentException e) {
if (getLog().isErrorEnabled()) {
getLog().error("Malformed memory pattern for '" + arg + memory + "'. Ignore this option.");
}
}
}
}
private void addProxyArg(Commandline cmd) {
if (settings == null || settings.getActiveProxy() == null) {
return;
}
Proxy activeProxy = settings.getActiveProxy();
String protocol = StringUtils.isNotEmpty(activeProxy.getProtocol()) ? activeProxy.getProtocol() + "." : "";
if (StringUtils.isNotEmpty(activeProxy.getHost())) {
cmd.createArg().setValue("-J-D" + protocol + "proxySet=true");
cmd.createArg().setValue("-J-D" + protocol + "proxyHost=" + activeProxy.getHost());
if (activeProxy.getPort() > 0) {
cmd.createArg().setValue("-J-D" + protocol + "proxyPort=" + activeProxy.getPort());
}
if (StringUtils.isNotEmpty(activeProxy.getNonProxyHosts())) {
cmd.createArg().setValue("-J-D" + protocol + "nonProxyHosts=\"" + activeProxy.getNonProxyHosts() + "\"");
}
if (StringUtils.isNotEmpty(activeProxy.getUsername())) {
cmd.createArg().setValue("-J-Dhttp.proxyUser=\"" + activeProxy.getUsername() + "\"");
if (StringUtils.isNotEmpty(activeProxy.getPassword())) {
cmd.createArg().setValue("-J-Dhttp.proxyPassword=\"" + activeProxy.getPassword() + "\"");
}
}
}
}
private void addStandardDocletOptions(File javadocOutputDirectory, List arguments) throws MavenReportException {
addArgIfNotEmpty(arguments, "-d", quotedPathArgument(outputDirectory.toString()));
}
private void addTldGeneratorOptions(List arguments) throws MojoExecutionException {
addArgIfNotEmpty(arguments, "-shortName", quotedArgument(shortName));
addArgIfNotEmpty(arguments, "-filename", quotedPathArgument(filename));
addArgIfNotEmpty(arguments, "-description", quotedArgument(com.squeakysand.commons.html.HtmlUtils.escape(description)));
addArgIfNotEmpty(arguments, "-tlibVersion", quotedArgument(tlibVersion));
addArgIfNotEmpty(arguments, "-uri", quotedPathArgument(determineUri()));
addArgIfNotEmpty(arguments, "-validator", quotedPathArgument(validator));
addArgIfNotEmpty(arguments, "-specificationVersion", quotedPathArgument(specificationVersion));
addArgIfNotEmpty(arguments, "-tagFilesDir", quotedPathArgument(tagfilesSourceDirectory.toString()));
addArgIfNotEmpty(arguments, "-tagFilesInclude", quotedPathArgument(determineTagFilesInclude()), false, false);
addArgIfNotEmpty(arguments, "-tagFilesExclude", quotedPathArgument(determineTagFilesExclude()), false, false);
addArgIfNotEmpty(arguments, "-processTagFiles", quotedPathArgument(String.valueOf(processTagFiles)));
}
private boolean canGenerateReport(List files) {
boolean canGenerate = true;
if (files.isEmpty() && StringUtils.isEmpty(subpackages)) {
canGenerate = false;
throw new RuntimeException("cannot generate report");
}
return canGenerate;
}
private Set collectBootClasspathArtifacts() throws MavenReportException {
Set result = new LinkedHashSet();
return result;
}
private Set collectDocletArtifacts() throws MavenReportException {
Set dArtifacts = new LinkedHashSet();
// add the tld generator doclet jar
String tldGeneratorGroupId = "com.squeakysand.jsp";
String tldGeneratorArtifactId = "jsptld-maven-plugin";
// now we need to find out what the current version is, we will use the same version as the version of the plugin we are running right now
// there is probably an easier way to figure this out
Map plugins = project.getPluginArtifactMap();
DefaultArtifact tldGeneratorArtifact = (DefaultArtifact) plugins.get(tldGeneratorGroupId + ':' + tldGeneratorArtifactId);
String tldGeneratorVersion = tldGeneratorArtifact.getVersion();
DocletArtifact tldArtifact = new DocletArtifact();
tldArtifact.setGroupId(tldGeneratorGroupId);
tldArtifact.setArtifactId(tldGeneratorArtifactId);
tldArtifact.setVersion(tldGeneratorVersion);
dArtifacts.add(tldArtifact);
// add an SLF4J implementation
DocletArtifact slf4jArtifact = new DocletArtifact();
slf4jArtifact.setGroupId("org.slf4j");
slf4jArtifact.setArtifactId("slf4j-simple");
slf4jArtifact.setVersion("1.5.8");
dArtifacts.add(slf4jArtifact);
return dArtifacts;
}
/**
* creates an {@link Artifact} representing the configured {@link JavadocPathArtifact} and resolves it.
*
* @param javadocArtifact the {@link JavadocPathArtifact} to resolve
* @return a resolved {@link Artifact}
* @throws ArtifactResolutionException if the resolution of the artifact failed.
* @throws ArtifactNotFoundException if the artifact hasn't been found.
* @throws ProjectBuildingException if the artifact POM could not be build.
*/
private Artifact createAndResolveArtifact(JavadocPathArtifact javadocArtifact) throws ArtifactResolutionException, ArtifactNotFoundException,
ProjectBuildingException {
Artifact artifact = artifactFactory.createProjectArtifact(javadocArtifact.getGroupId(), javadocArtifact.getArtifactId(), javadocArtifact.getVersion(),
Artifact.SCOPE_COMPILE);
if (artifact.getFile() == null) {
MavenProject pluginProject = mavenProjectBuilder.buildFromRepository(artifact, remoteRepositories, localRepository);
artifact = pluginProject.getArtifact();
artifactResolver.resolve(artifact, remoteRepositories, localRepository);
}
return artifact;
}
private String determineTagFilesExclude() {
String result = "";
if (excludeTagFiles != null) {
result = StringUtils.join(excludeTagFiles.iterator(), ",");
}
return result;
}
private String determineTagFilesInclude() {
String result = null;
List includePatterns = includeTagFiles;
if (includePatterns == null) {
includePatterns = new ArrayList();
includePatterns.add("**/*.tag");
includePatterns.add("**/*.tagx");
}
result = StringUtils.join(includePatterns.iterator(), ",");
getLog().info("include tag files pattern: " + result);
return result;
}
private String determineUri() throws MojoExecutionException {
String result = null;
if (uri != null && uri.toString().trim().length() > 0) {
result = uri.toString().trim();
} else if (baseUri != null && baseUri.toString().trim().length() > 0) {
result = String.format("%s/%s/%s", baseUri.toString().trim(), shortName, tlibVersion);
} else if (project.getUrl() != null && project.getUrl().trim().length() > 0) {
result = project.getUrl().trim();
} else {
throw new MojoExecutionException(String.format(
"unable to determine URI for taglib '%s' - ${uri}, ${baseUri} and ${project.url} were all null or empty", shortName));
}
getLog().info(" element set to: " + result);
return result;
}
/**
* Execute the Javadoc command line
*
* @param cmd not null
* @param javadocOutputDirectory not null
* @throws MavenReportException if any errors occur
*/
private void executeJavadocCommandLine(Commandline cmd, File javadocOutputDirectory) throws MavenReportException {
String cmdLine = null;
CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
try {
int exitCode = CommandLineUtils.executeCommandLine(cmd, out, err);
String output = (StringUtils.isEmpty(out.getOutput()) ? null : '\n' + out.getOutput().trim());
if (exitCode != 0) {
if (cmdLine == null) {
cmdLine = CommandLineUtils.toString(cmd.getCommandline()).replaceAll("'", "");
cmdLine = hideProxyPassword(cmdLine, settings);
}
writeDebugJavadocScript(cmdLine, javadocOutputDirectory);
if (StringUtils.isNotEmpty(output) && StringUtils.isEmpty(err.getOutput()) && isJavadocVMInitError(output)) {
StringBuilder msg = new StringBuilder();
msg.append(output);
msg.append('\n').append('\n');
msg.append(ERROR_INIT_VM).append('\n');
msg.append("Or, try to reduce the Java heap size for the Javadoc goal using ");
msg.append("-Dminmemory= and -Dmaxmemory=.").append('\n').append('\n');
msg.append("Command line was: ").append(cmdLine).append('\n').append('\n');
msg.append("Refer to the generated Javadoc files in '").append(javadocOutputDirectory).append("' dir.\n");
throw new MavenReportException(msg.toString());
}
if (StringUtils.isNotEmpty(output)) {
getLog().info(output);
}
StringBuilder msg = new StringBuilder("\nExit code: ");
msg.append(exitCode);
if (StringUtils.isNotEmpty(err.getOutput())) {
msg.append(" - ").append(err.getOutput());
}
msg.append('\n');
msg.append("Command line was: ").append(cmdLine).append('\n').append('\n');
msg.append("Refer to the generated Javadoc files in '").append(javadocOutputDirectory).append("' dir.\n");
throw new MavenReportException(msg.toString());
}
if (StringUtils.isNotEmpty(output)) {
getLog().info(output);
}
} catch (CommandLineException e) {
throw new MavenReportException("Unable to execute javadoc command: " + e.getMessage(), e);
}
// ----------------------------------------------------------------------
// Handle Javadoc warnings
// ----------------------------------------------------------------------
if (StringUtils.isNotEmpty(err.getOutput()) && getLog().isWarnEnabled()) {
getLog().warn("Javadoc Warnings");
StringTokenizer token = new StringTokenizer(err.getOutput(), "\n");
while (token.hasMoreTokens()) {
String current = token.nextToken().trim();
getLog().warn(current);
}
}
}
private void failOnError(String prefix, Exception e) throws MojoExecutionException {
if (failOnError) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new MojoExecutionException(prefix + ": " + e.getMessage(), e);
}
getLog().error(prefix + ": " + e.getMessage(), e);
}
/**
* Return the Javadoc artifact path and its transitive dependencies path from the local repository
*
* @param javadocArtifact not null
* @return a list of locale artifacts absolute path
* @throws MavenReportException if any
*/
private List getArtifactsAbsolutePath(JavadocPathArtifact javadocArtifact) throws MavenReportException {
if ((StringUtils.isEmpty(javadocArtifact.getGroupId())) && (StringUtils.isEmpty(javadocArtifact.getArtifactId()))
&& (StringUtils.isEmpty(javadocArtifact.getVersion()))) {
return Collections.emptyList();
}
List path = new ArrayList();
try {
Artifact artifact = createAndResolveArtifact(javadocArtifact);
path.add(artifact.getFile().getAbsolutePath());
// Find its transitive dependencies in the local repo
MavenProject artifactProject = mavenProjectBuilder.buildFromRepository(artifact, remoteRepositories, localRepository);
Set dependencyArtifacts = artifactProject.createArtifacts(artifactFactory, null, null);
if (!dependencyArtifacts.isEmpty()) {
ArtifactResolutionResult result = artifactResolver.resolveTransitively(dependencyArtifacts, artifactProject.getArtifact(),
artifactProject.getRemoteArtifactRepositories(), localRepository, artifactMetadataSource);
Set artifacts = result.getArtifacts();
Map compileArtifactMap = new HashMap();
populateCompileArtifactMap(compileArtifactMap, artifacts);
for (Artifact a : compileArtifactMap.values()) {
path.add(a.getFile().getAbsolutePath());
}
}
return path;
} catch (ArtifactResolutionException e) {
throw new MavenReportException("Unable to resolve artifact:" + javadocArtifact, e);
} catch (ArtifactNotFoundException e) {
throw new MavenReportException("Unable to find artifact:" + javadocArtifact, e);
} catch (ProjectBuildingException e) {
throw new MavenReportException("Unable to build the Maven project for the artifact:" + javadocArtifact, e);
}
}
/**
* Method to get the path of the bootclass artifacts used in the -bootclasspath option.
*
* @return a string that contains bootclass path, separated by the System pathSeparator string (colon (:) on Solaris or semi-colon (
* ;) on Windows).
* @throws MavenReportException if any
* @see File#pathSeparator
*/
private String getBootclassPath() throws MavenReportException {
Set bootclasspathArtifacts = collectBootClasspathArtifacts();
List bootclassPath = new ArrayList();
for (BootclasspathArtifact aBootclasspathArtifact : bootclasspathArtifacts) {
if ((StringUtils.isNotEmpty(aBootclasspathArtifact.getGroupId())) && (StringUtils.isNotEmpty(aBootclasspathArtifact.getArtifactId()))
&& (StringUtils.isNotEmpty(aBootclasspathArtifact.getVersion()))) {
bootclassPath.addAll(getArtifactsAbsolutePath(aBootclasspathArtifact));
}
}
bootclassPath = pruneFiles(bootclassPath);
StringBuilder path = new StringBuilder();
path.append(StringUtils.join(bootclassPath.iterator(), File.pathSeparator));
return path.toString();
}
/**
* Method that sets the classpath elements that will be specified in the javadoc -classpath parameter.
*
* @return a String that contains the concatenated classpath elements, separated by the System pathSeparator string (colon (:) on Solaris or
* semi-colon (;) on Windows).
* @throws MavenReportException if any.
* @see File#pathSeparator
*/
private String getClasspath() throws MavenReportException {
List classpathElements = new ArrayList();
Map compileArtifactMap = new HashMap();
classpathElements.addAll(getProjectBuildOutputDirs(project));
populateCompileArtifactMap(compileArtifactMap, getProjectArtifacts(project));
for (Artifact a : compileArtifactMap.values()) {
classpathElements.add(a.getFile().toString());
}
String result = StringUtils.join(classpathElements.iterator(), File.pathSeparator);
return result;
}
/**
* Method to get the path of the doclet artifacts used in the -docletpath option.
*
* Either docletArtifact or doclectArtifacts can be defined and used, not both, docletArtifact takes precedence over doclectArtifacts. docletPath is always
* appended to any result path definition.
*
* @return a string that contains doclet path, separated by the System pathSeparator string (colon (:) on Solaris or semi-colon (;
* ) on Windows).
* @throws MavenReportException if any
* @see File#pathSeparator
*/
private String getDocletPath() throws MavenReportException {
Set docletArtifacts = collectDocletArtifacts();
List pathParts = new ArrayList();
for (DocletArtifact docletArtifact : docletArtifacts) {
if (!isDocletArtifactEmpty(docletArtifact)) {
pathParts.addAll(getArtifactsAbsolutePath(docletArtifact));
}
}
StringBuilder path = new StringBuilder();
path.append(StringUtils.join(pathParts.iterator(), File.pathSeparator));
if (StringUtils.isEmpty(path.toString()) && getLog().isWarnEnabled()) {
getLog().warn("No docletpath option was found. Please review or " + " or .");
}
return path.toString();
}
/**
* @return the encoding attribute or the value of file.encoding system property if null.
*/
private String getEncoding() {
return (StringUtils.isEmpty(encoding)) ? ReaderFactory.FILE_ENCODING : encoding;
}
/**
* Method that gets all the source files to be excluded from the javadoc on the given source paths.
*
* @param sourcePaths the path to the source files
* @param subpackagesList list of subpackages to be included in the javadoc
* @param excludedPackages the package names to be excluded in the javadoc
* @return a List of the source files to be excluded in the generated javadoc
*/
private List getExcludedNames(List sourcePaths, String[] subpackagesList, String[] excludedPackages) {
List excludedNames = new ArrayList();
for (String path : sourcePaths) {
for (String element : subpackagesList) {
List excludes = getExcludedPackages(path, excludedPackages);
excludedNames.addAll(excludes);
}
}
return excludedNames;
}
/**
* Method to get the packages specified in the excludePackageNames parameter. The packages are split with ',', ':', or ';' and then formatted.
*
* @return an array of String objects that contain the package names
* @throws MavenReportException
*/
private String[] getExcludedPackages() throws MavenReportException {
Set excluded = new LinkedHashSet();
// for the specified excludePackageNames
if (StringUtils.isNotEmpty(excludePackageNames)) {
excluded.addAll(Arrays.asList(excludePackageNames.split("[,:;]")));
}
String[] result = new String[excluded.size()];
if (isNotEmpty(excluded)) {
int idx = 0;
for (String exclude : excluded) {
result[idx] = exclude.replace('.', File.separatorChar);
idx++;
}
}
return result;
}
// ----------------------------------------------------------------------
// private methods
// ----------------------------------------------------------------------
/**
* Method to get the excluded source files from the javadoc and create the argument string that will be included in the javadoc commandline execution.
*
* @param sourcePaths the list of paths to the source files
* @return a String that contains the exclude argument that will be used by javadoc
* @throws MavenReportException
*/
private String getExcludedPackages(List sourcePaths) throws MavenReportException {
List excludedNames = null;
if (StringUtils.isNotEmpty(sourcepath) && StringUtils.isNotEmpty(subpackages)) {
String[] excludedPackages = getExcludedPackages();
String[] subpackagesList = subpackages.split("[:]");
excludedNames = getExcludedNames(sourcePaths, subpackagesList, excludedPackages);
}
String excludeArg = "";
if (StringUtils.isNotEmpty(subpackages) && excludedNames != null) {
// add the excludedpackage names
excludeArg = StringUtils.join(excludedNames.iterator(), ":");
}
return excludeArg;
}
/**
* Method that gets the complete package names (including subpackages) of the packages that were defined in the excludePackageNames parameter.
*
* @param sourceDirectory the directory where the source files are located
* @param excludePackagenames package names to be excluded in the javadoc
* @return a List of the packagenames to be excluded
*/
private List getExcludedPackages(String sourceDirectory, String[] excludePackagenames) {
List files = new ArrayList();
for (String excludePackagename : excludePackagenames) {
String[] fileList = FileUtils.getFilesFromExtension(sourceDirectory, new String[] {"java"});
for (String element : fileList) {
String[] excludeName = excludePackagename.split("[*]");
int u = 0;
while (u < excludeName.length) {
if (!"".equals(excludeName[u].trim()) && element.indexOf(excludeName[u]) != -1 && sourceDirectory.indexOf(excludeName[u]) == -1) {
files.add(element);
}
u++;
}
}
}
List excluded = new ArrayList();
for (String file : files) {
int idx = file.lastIndexOf(File.separatorChar);
String tmpStr = file.substring(0, idx);
tmpStr = tmpStr.replace('\\', '/');
String[] srcSplit = tmpStr.split(sourceDirectory.replace('\\', '/') + '/');
String excludedPackage = srcSplit[1].replace('/', '.');
if (!excluded.contains(excludedPackage)) {
excluded.add(excludedPackage);
}
}
return excluded;
}
/**
*
*/
private List getFiles(List sourcePaths) throws MavenReportException {
List files = new ArrayList();
if (StringUtils.isEmpty(subpackages)) {
String[] excludedPackages = getExcludedPackages();
for (String sourcePath : sourcePaths) {
File sourceDirectory = new File(sourcePath);
addFilesFromSource(files, sourceDirectory, excludedPackages);
}
}
return files;
}
private List getFilesWithUnnamedPackages(List sourcePaths, List files) {
return getPackageNamesOrFilesWithUnnamedPackages(sourcePaths, files, false);
}
/**
* Method that gets the files or classes that would be included in the javadocs using the subpackages parameter.
*
* @param sourceDirectory the directory where the source files are located
* @param fileList the list of all files found in the sourceDirectory
* @param excludePackages package names to be excluded in the javadoc
* @return a StringBuffer that contains the appended file names of the files to be included in the javadoc
*/
private List getIncludedFiles(File sourceDirectory, String[] fileList, String[] excludePackages) {
List files = new ArrayList();
for (String element : fileList) {
boolean include = true;
for (int k = 0; k < excludePackages.length && include; k++) {
// handle wildcards (*) in the excludePackageNames
String[] excludeName = excludePackages[k].split("[*]");
if (excludeName.length == 0) {
continue;
}
if (excludeName.length > 1) {
int u = 0;
while (include && u < excludeName.length) {
if (!"".equals(excludeName[u].trim()) && element.indexOf(excludeName[u]) != -1) {
include = false;
}
u++;
}
} else {
if (element.startsWith(sourceDirectory.toString() + File.separatorChar + excludeName[0])) {
if (excludeName[0].endsWith(String.valueOf(File.separatorChar))) {
int i = element.lastIndexOf(File.separatorChar);
String packageName = element.substring(0, i + 1);
File currentPackage = new File(packageName);
File excludedPackage = new File(sourceDirectory, excludeName[0]);
if (currentPackage.equals(excludedPackage) && element.substring(i).indexOf(".java") != -1) {
include = true;
} else {
include = false;
}
} else {
include = false;
}
}
}
}
if (include) {
files.add(quotedPathArgument(element));
}
}
return files;
}
private String getJavadocExecutable() throws IOException {
Toolchain tc = getToolchain();
if (tc != null) {
getLog().info("Toolchain in javadoc-plugin: " + tc);
if (javadocExecutable != null) {
getLog().warn("Toolchains are ignored, 'javadocExecutable' parameter is set to " + javadocExecutable);
} else {
javadocExecutable = tc.findTool("javadoc");
}
}
String javadocCommand = "javadoc" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "");
File javadocExe;
// ----------------------------------------------------------------------
// The javadoc executable is defined by the user
// ----------------------------------------------------------------------
if (StringUtils.isNotEmpty(javadocExecutable)) {
javadocExe = new File(javadocExecutable);
if (javadocExe.isDirectory()) {
javadocExe = new File(javadocExe, javadocCommand);
}
if (SystemUtils.IS_OS_WINDOWS && javadocExe.getName().indexOf('.') < 0) {
javadocExe = new File(javadocExe.getPath() + ".exe");
}
if (!javadocExe.isFile()) {
throw new IOException("The javadoc executable '" + javadocExe + "' doesn't exist or is not a file. Verify the parameter.");
}
return javadocExe.getAbsolutePath();
}
// ----------------------------------------------------------------------
// Try to find javadocExe from System.getProperty( "java.home" )
// By default, System.getProperty( "java.home" ) = JRE_HOME and JRE_HOME
// should be in the JDK_HOME
// ----------------------------------------------------------------------
// For IBM's JDK 1.2
if (SystemUtils.IS_OS_AIX) {
javadocExe = new File(SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "sh", javadocCommand);
} else if (SystemUtils.IS_OS_MAC_OSX) {
javadocExe = new File(SystemUtils.getJavaHome() + File.separator + "bin", javadocCommand);
} else {
javadocExe = new File(SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "bin", javadocCommand);
}
// ----------------------------------------------------------------------
// Try to find javadocExe from JAVA_HOME environment variable
// ----------------------------------------------------------------------
if (!javadocExe.exists() || !javadocExe.isFile()) {
Properties env = CommandLineUtils.getSystemEnvVars();
String javaHome = env.getProperty("JAVA_HOME");
if (StringUtils.isEmpty(javaHome)) {
throw new IOException("The environment variable JAVA_HOME is not correctly set.");
}
if ((!new File(javaHome).exists()) || (!new File(javaHome).isDirectory())) {
throw new IOException("The environment variable JAVA_HOME=" + javaHome + " doesn't exist or is not a valid directory.");
}
javadocExe = new File(env.getProperty("JAVA_HOME") + File.separator + "bin", javadocCommand);
}
if (!javadocExe.exists() || !javadocExe.isFile()) {
throw new IOException("The javadoc executable '" + javadocExe + "' doesn't exist or is not a file. Verify the JAVA_HOME environment variable.");
}
return javadocExe.getAbsolutePath();
}
/**
* Call the Javadoc tool and parse its output to find its version, i.e.:
*
*
* javadoc.exe(or.sh) - J - version
*
*
* @param javadocExe not null file
* @return the javadoc version as float
* @throws IOException if javadocExe is null, doesn't exist or is not a file
* @throws CommandLineException if any
* @throws IllegalArgumentException if no output was found in the command line
* @throws PatternSyntaxException if the output contains a syntax error in the regular-expression pattern.
* @see #parseJavadocVersion(String)
*/
private float getJavadocVersion(File javadocExe) throws IOException, CommandLineException, IllegalArgumentException, PatternSyntaxException {
if ((javadocExe == null) || (!javadocExe.exists()) || (!javadocExe.isFile())) {
throw new IOException("The javadoc executable '" + javadocExe + "' doesn't exist or is not a file. ");
}
Commandline cmd = new Commandline();
cmd.setExecutable(javadocExe.getAbsolutePath());
cmd.setWorkingDirectory(javadocExe.getParentFile());
cmd.createArg().setValue("-J-version");
CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
int exitCode = CommandLineUtils.executeCommandLine(cmd, out, err);
if (exitCode != 0) {
StringBuffer msg = new StringBuffer("Exit code: " + exitCode + " - " + err.getOutput());
msg.append('\n');
msg.append("Command line was:" + CommandLineUtils.toString(cmd.getCommandline()));
throw new CommandLineException(msg.toString());
}
if (StringUtils.isNotEmpty(err.getOutput())) {
return parseJavadocVersion(err.getOutput());
} else if (StringUtils.isNotEmpty(out.getOutput())) {
return parseJavadocVersion(out.getOutput());
}
throw new IllegalArgumentException("No output found from the command line 'javadoc -J-version'");
}
private String getOutputDirectory() {
return outputDirectory.getAbsoluteFile().toString();
}
private List getPackageNames(List sourcePaths, List files) {
return getPackageNamesOrFilesWithUnnamedPackages(sourcePaths, files, true);
}
/**
* @param sourcePaths not null, containing absolute and relative paths
* @param files not null, containing list of quoted files
* @param onlyPackageName boolean for only package name
* @return a list of package names or files with unnamed package names, depending the value of the unnamed flag
* @see #getFiles(List)
* @see #getSourcePaths()
*/
private List getPackageNamesOrFilesWithUnnamedPackages(List sourcePaths, List files, boolean onlyPackageName) {
List returnList = new ArrayList();
if (!StringUtils.isEmpty(sourcepath)) {
return returnList;
}
for (String currentFile : files) {
currentFile = currentFile.replace('\\', '/');
for (String currentSourcePath : sourcePaths) {
currentSourcePath = currentSourcePath.replace('\\', '/');
if (!currentSourcePath.endsWith("/")) {
currentSourcePath += "/";
}
if (currentFile.indexOf(currentSourcePath) != -1) {
String packagename = currentFile.substring(currentSourcePath.length() + 1);
/*
* Remove the miscellaneous files http://download.oracle.com/javase/1.4.2/docs/tooldocs/solaris/javadoc.html#unprocessed
*/
if (packagename.indexOf("doc-files") != -1) {
continue;
}
if (onlyPackageName && packagename.lastIndexOf("/") != -1) {
packagename = packagename.substring(0, packagename.lastIndexOf("/"));
packagename = packagename.replace('/', '.');
if (!returnList.contains(packagename)) {
returnList.add(packagename);
}
}
if (!onlyPackageName && packagename.lastIndexOf("/") == -1) {
returnList.add(currentFile);
}
}
}
}
return returnList;
}
/**
* @param p not null maven project
* @return the list of artifacts for the given project
*/
private List getProjectArtifacts(MavenProject p) {
List compileArtifacts = p.getCompileArtifacts();
// getLog().info("compile artifacts: " + ToStringHelper.toString(compileArtifacts));
return (compileArtifacts == null ? Collections. emptyList() : new LinkedList(p.getCompileArtifacts()));
}
/**
* @param p not null maven project
* @return the list of directories where compiled classes are placed for the given project. These dirs are added in the javadoc classpath.
*/
private List getProjectBuildOutputDirs(MavenProject p) {
if (StringUtils.isEmpty(p.getBuild().getOutputDirectory())) {
return Collections.emptyList();
}
return Collections.singletonList(p.getBuild().getOutputDirectory());
}
/**
* @param p not null maven project
* @return the list of source paths for the given project
*/
@SuppressWarnings("unchecked")
private List getProjectSourceRoots(MavenProject p) {
List result = Collections.emptyList();
if (!"pom".equals(p.getPackaging().toLowerCase()) && p.getCompileSourceRoots() != null) {
result = p.getCompileSourceRoots();
}
return result;
}
/**
* Method to format the specified source paths that will be accepted by the javadoc tool.
*
* @param sourcePaths the list of paths to the source files that will be included in the javadoc.
* @return a String that contains the formatted source path argument, separated by the System pathSeparator string (colon (:) on Solaris or
* semi-colon (;) on Windows).
* @see File#pathSeparator
*/
private String getSourcePath(List sourcePaths) {
String sourcePath = null;
if (StringUtils.isEmpty(subpackages) || StringUtils.isNotEmpty(sourcepath)) {
sourcePath = StringUtils.join(sourcePaths.iterator(), File.pathSeparator);
}
return sourcePath;
}
private List getSourcePaths() throws MavenReportException {
List sourcePaths = getProjectSourceRoots(project);
sourcePaths = pruneDirs(project, sourcePaths);
return sourcePaths;
}
/**
* TODO remove the part with ToolchainManager lookup once we depend on 2.0.9 (have it as prerequisite). Define as regular component field then.
*
* @return Toolchain instance
*/
private Toolchain getToolchain() {
Toolchain tc = null;
if (toolchainManager != null) {
tc = toolchainManager.getToolchainFromBuildContext("jdk", session);
}
return tc;
}
/**
* For security reasons, if an active proxy is defined and needs an authentication by username/password, hide the proxy password in the command line.
*
* @param cmdLine a command line, not null
* @param settings the user settings
* @return the cmdline with '*' for the http.proxyPassword JVM property
*/
private String hideProxyPassword(String cmdLine, Settings settings) {
if (cmdLine == null) {
throw new IllegalArgumentException("cmdLine could not be null");
}
if (settings == null) {
return cmdLine;
}
Proxy activeProxy = settings.getActiveProxy();
if (activeProxy != null && StringUtils.isNotEmpty(activeProxy.getHost()) && StringUtils.isNotEmpty(activeProxy.getUsername())
&& StringUtils.isNotEmpty(activeProxy.getPassword())) {
String pass = "-J-Dhttp.proxyPassword=\"" + activeProxy.getPassword() + "\"";
String hidepass = "-J-Dhttp.proxyPassword=\"" + StringUtils.repeat("*", activeProxy.getPassword().length()) + "\"";
return StringUtils.replace(cmdLine, pass, hidepass);
}
return cmdLine;
}
/**
* Verify if a doclet artifact is empty or not
*
* @param aDocletArtifact could be null
* @return true if aDocletArtifact or the groupId/artifactId/version of the doclet artifact is null, false otherwise.
*/
private boolean isDocletArtifactEmpty(DocletArtifact aDocletArtifact) {
if (aDocletArtifact == null) {
return true;
}
return StringUtils.isEmpty(aDocletArtifact.getGroupId()) && StringUtils.isEmpty(aDocletArtifact.getArtifactId())
&& StringUtils.isEmpty(aDocletArtifact.getVersion());
}
/**
* Convenience method to determine that a collection is empty or null.
*/
private boolean isEmpty(final Collection> collection) {
return collection == null || collection.isEmpty();
}
/**
* Is the Javadoc version at least the requested version.
*
* @param requiredVersion the required version, for example 1.5f
* @return true if the javadoc version is equal or greater than the required version
*/
private boolean isJavaDocVersionAtLeast(float requiredVersion) {
return fJavadocVersion >= requiredVersion;
}
/**
* Check if the Javadoc JVM is correctly started or not.
*
* @param output the command line output, not null.
* @return true if Javadoc output command line contains Javadoc word, false otherwise.
* @see #executeJavadocCommandLine(Commandline, File)
*/
private boolean isJavadocVMInitError(String output) {
/*
* see main.usage and main.Building_tree keys from com.sun.tools.javadoc.resources.javadoc bundle in tools.jar
*/
return !(output.contains("Javadoc") || output.contains("javadoc"));
}
/**
* Convenience method to determine that a collection is not empty or null.
*/
private boolean isNotEmpty(final Collection> collection) {
return collection != null && !collection.isEmpty();
}
/**
* Logs an error with throwable content only if in debug.
*
* @param message
* @param t
*/
private void logError(String message, Throwable t) {
if (getLog().isDebugEnabled()) {
getLog().error(message, t);
} else {
getLog().error(message);
}
}
/**
* Parse a memory string which be used in the JVM arguments -Xms or -Xmx.
* Here are some supported memory string depending the JDK used:
*
*
*
JDK
*
Memory argument support for -Xms or -Xmx
*
*
*
SUN
*
1024k | 128m | 1g | 1t
*
*
*
IBM
*
1024k | 1024b | 128m | 128mb | 1g | 1gb
*
*
*
BEA
*
1024k | 1024kb | 128m | 128mb | 1g | 1gb
*
*
*
* @param memory the memory to be parsed, not null.
* @return the memory parsed with a supported unit. If no unit specified in the memory parameter, the default unit is m. The units
* g | gb or t | tb will be converted in m.
* @throws IllegalArgumentException if the memory parameter is null or doesn't match any pattern.
*/
private String parseJavadocMemory(String memory) throws IllegalArgumentException {
if (StringUtils.isEmpty(memory)) {
throw new IllegalArgumentException("The memory could not be null.");
}
Pattern p = Pattern.compile("^\\s*(\\d+)\\s*?\\s*$");
Matcher m = p.matcher(memory);
if (m.matches()) {
return m.group(1) + "m";
}
p = Pattern.compile("^\\s*(\\d+)\\s*k(b)?\\s*$", Pattern.CASE_INSENSITIVE);
m = p.matcher(memory);
if (m.matches()) {
return m.group(1) + "k";
}
p = Pattern.compile("^\\s*(\\d+)\\s*m(b)?\\s*$", Pattern.CASE_INSENSITIVE);
m = p.matcher(memory);
if (m.matches()) {
return m.group(1) + "m";
}
p = Pattern.compile("^\\s*(\\d+)\\s*g(b)?\\s*$", Pattern.CASE_INSENSITIVE);
m = p.matcher(memory);
if (m.matches()) {
return (Integer.parseInt(m.group(1)) * 1024) + "m";
}
p = Pattern.compile("^\\s*(\\d+)\\s*t(b)?\\s*$", Pattern.CASE_INSENSITIVE);
m = p.matcher(memory);
if (m.matches()) {
return (Integer.parseInt(m.group(1)) * 1024 * 1024) + "m";
}
throw new IllegalArgumentException("Could convert not to a memory size: " + memory);
}
/**
* Parse the output for 'javadoc -J-version' and return the javadoc version recognized.
* Here are some output for 'javadoc -J-version' depending the JDK used:
*
*
*
JDK
*
Output for 'javadoc -J-version'
*
*
*
Sun 1.4
*
java full version "1.4.2_12-b03"
*
*
*
Sun 1.5
*
java full version "1.5.0_07-164"
*
*
*
IBM 1.4
*
javadoc full version "J2RE 1.4.2 IBM Windows 32 build cn1420-20040626"
*
*
*
IBM 1.5 (French JVM)
*
javadoc version complète de "J2RE 1.5.0 IBM Windows 32 build pwi32pdev-20070426a"
*
*
*
FreeBSD 1.5
*
java full version "diablo-1.5.0-b01"
*
*
*
BEA jrockit 1.5
*
java full version "1.5.0_11-b03"
*
*
*
* @param output for 'javadoc -J-version'
* @return the version of the javadoc for the output.
* @throws PatternSyntaxException if the output doesn't match with the output pattern (?s).*?([0-9]+\\.[0-9]+)(\\.([0-9]+))?.*.
* @throws IllegalArgumentException if the output is null
*/
private float parseJavadocVersion(String output) throws IllegalArgumentException, PatternSyntaxException {
if (StringUtils.isEmpty(output)) {
throw new IllegalArgumentException("The output could not be null.");
}
Pattern pattern = Pattern.compile("(?s).*?([0-9]+\\.[0-9]+)(\\.([0-9]+))?.*");
Matcher matcher = pattern.matcher(output);
if (!matcher.matches()) {
throw new PatternSyntaxException("Unrecognized version of Javadoc: '" + output + "'", pattern.pattern(), pattern.toString().length() - 1);
}
String version = matcher.group(3);
if (version == null) {
version = matcher.group(1);
} else {
version = matcher.group(1) + version;
}
return Float.parseFloat(version);
}
/**
* Method to put the artifacts in the hashmap.
*
* @param compileArtifactMap the hashmap that will contain the artifacts
* @param artifactList the list of artifacts that will be put in the map
* @throws MavenReportException if any
*/
private void populateCompileArtifactMap(Map compileArtifactMap, Collection artifactList) throws MavenReportException {
if (artifactList == null) {
return;
}
for (Artifact newArtifact : artifactList) {
File file = newArtifact.getFile();
if (file == null) {
throw new MavenReportException("Error in plugin descriptor - " + "dependency was not resolved for artifact: " + newArtifact.getGroupId() + ":"
+ newArtifact.getArtifactId() + ":" + newArtifact.getVersion());
}
if (compileArtifactMap.get(newArtifact.getDependencyConflictId()) != null) {
Artifact oldArtifact = compileArtifactMap.get(newArtifact.getDependencyConflictId());
ArtifactVersion oldVersion = new DefaultArtifactVersion(oldArtifact.getVersion());
ArtifactVersion newVersion = new DefaultArtifactVersion(newArtifact.getVersion());
if (newVersion.compareTo(oldVersion) > 0) {
compileArtifactMap.put(newArtifact.getDependencyConflictId(), newArtifact);
}
} else {
compileArtifactMap.put(newArtifact.getDependencyConflictId(), newArtifact);
}
}
}
/**
* Method that removes the invalid directories in the specified directories. Note: All elements in dirs could be an absolute or relative
* against the project's base directory String path.
*
* @param project the current Maven project not null
* @param dirs the list of String directories path that will be validated.
* @return a List of valid String directories absolute paths.
*/
private List pruneDirs(MavenProject project, List dirs) {
List pruned = new ArrayList(dirs.size());
for (String dir : dirs) {
if (dir == null) {
continue;
}
File directory = new File(dir);
if (!directory.isAbsolute()) {
directory = new File(project.getBasedir(), directory.getPath());
}
if (directory.isDirectory() && !pruned.contains(directory.getAbsolutePath())) {
pruned.add(directory.getAbsolutePath());
}
}
return pruned;
}
/**
* Method that removes the invalid files in the specified files. Note: All elements in files should be an absolute String
* path.
*
* @param files the list of String files paths that will be validated.
* @return a List of valid File objects.
*/
private List pruneFiles(List files) {
List pruned = new ArrayList(files.size());
for (String f : files) {
if (!shouldPruneFile(f, pruned)) {
pruned.add(f);
}
}
return pruned;
}
/**
* Convenience method to wrap an argument value in single quotes (i.e. '). Intended for values which may contain whitespaces.
* To prevent javadoc error, the line separator (i.e. \n) are skipped.
*
* @param value the argument value.
* @return argument with quote
*/
private String quotedArgument(String value) {
String arg = value;
if (StringUtils.isNotEmpty(arg)) {
if (arg.indexOf("'") != -1) {
arg = StringUtils.replace(arg, "'", "\\'");
}
arg = "'" + arg + "'";
// To prevent javadoc error
arg = StringUtils.replace(arg, "\n", " ");
}
return arg;
}
/**
* Convenience method to format a path argument so that it is properly interpreted by the javadoc tool. Intended for path values which may contain
* whitespaces.
*
* @param value the argument value.
* @return path argument with quote
*/
private String quotedPathArgument(String value) {
String path = value;
if (StringUtils.isNotEmpty(path)) {
path = path.replace('\\', '/');
if (path.indexOf("\'") != -1) {
String split[] = path.split("\'");
path = "";
for (int i = 0; i < split.length; i++) {
if (i != split.length - 1) {
path = path + split[i] + "\\'";
} else {
path = path + split[i];
}
}
}
path = "'" + path + "'";
}
return path;
}
private void setFJavadocVersion(File jExecutable) throws MavenReportException {
float jVersion;
try {
jVersion = getJavadocVersion(jExecutable);
} catch (IOException e) {
if (getLog().isWarnEnabled()) {
getLog().warn("Unable to find the javadoc version: " + e.getMessage());
getLog().warn("Using the Java version instead of, i.e. " + SystemUtils.JAVA_VERSION_FLOAT);
}
jVersion = SystemUtils.JAVA_VERSION_FLOAT;
} catch (CommandLineException e) {
if (getLog().isWarnEnabled()) {
getLog().warn("Unable to find the javadoc version: " + e.getMessage());
getLog().warn("Using the Java the version instead of, i.e. " + SystemUtils.JAVA_VERSION_FLOAT);
}
jVersion = SystemUtils.JAVA_VERSION_FLOAT;
} catch (IllegalArgumentException e) {
if (getLog().isWarnEnabled()) {
getLog().warn("Unable to find the javadoc version: " + e.getMessage());
getLog().warn("Using the Java the version instead of, i.e. " + SystemUtils.JAVA_VERSION_FLOAT);
}
jVersion = SystemUtils.JAVA_VERSION_FLOAT;
}
fJavadocVersion = jVersion;
}
/**
* Determine whether a file should be excluded from the provided list of paths, based on whether it exists and is already present in the list.
*/
private boolean shouldPruneFile(String f, List pruned) {
if (f != null) {
File file = new File(f);
if (file.isFile() && (isEmpty(pruned) || !pruned.contains(f))) {
return false;
}
}
return true;
}
/**
* Validate if a charset is supported on this platform.
*
* @param charsetName the charsetName to be check.
* @return true if the given charset is supported by the JVM, false otherwise.
*/
private boolean validateEncoding(String charsetName) {
if (StringUtils.isEmpty(charsetName)) {
return false;
}
OutputStream ost = new ByteArrayOutputStream();
OutputStreamWriter osw = null;
try {
osw = new OutputStreamWriter(ost, charsetName);
} catch (UnsupportedEncodingException exc) {
return false;
} finally {
IOUtil.close(osw);
}
return true;
}
/**
* Checks for the validity of the Javadoc options used by the user.
*
* @throws MavenReportException if error
*/
private void validateJavadocOptions() throws MavenReportException {
// encoding
if (StringUtils.isNotEmpty(getEncoding()) && !validateEncoding(getEncoding())) {
throw new MavenReportException("Unsupported option '" + getEncoding() + "'");
}
}
/**
* Write a debug javadoc script in case of command line error or in debug mode.
*
* @param cmdLine the current command line as string, not null.
* @param javadocOutputDirectory the output dir, not null.
* @see #executeJavadocCommandLine(Commandline, File)
*/
private void writeDebugJavadocScript(String cmdLine, File javadocOutputDirectory) {
File commandLineFile = new File(javadocOutputDirectory, DEBUG_JAVADOC_SCRIPT_NAME);
commandLineFile.getParentFile().mkdirs();
try {
FileUtils.fileWrite(commandLineFile.getAbsolutePath(), "UTF-8", cmdLine);
if (!SystemUtils.IS_OS_WINDOWS) {
Runtime.getRuntime().exec(new String[] {"chmod", "a+x", commandLineFile.getAbsolutePath()});
}
} catch (IOException e) {
logError("Unable to write '" + commandLineFile.getName() + "' debug script file", e);
}
}
}