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

com.squeakysand.jsp.tldgenerator.maven.TldGeneratorMojo Maven / Gradle / Ivy

/*
 * 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: * *
     * <excludePackageNames>*.internal:org.acme.exclude1.*:org.acme.exclude2</excludePackageNames>
     * 
* * @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: * * * * * * * * * * * * * * * * * *
JDKMemory argument support for -Xms or -Xmx
SUN1024k | 128m | 1g | 1t
IBM1024k | 1024b | 128m | 128mb | 1g | 1gb
BEA1024k | 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: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
JDKOutput for 'javadoc -J-version'
Sun 1.4java full version "1.4.2_12-b03"
Sun 1.5java full version "1.5.0_07-164"
IBM 1.4javadoc 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.5java full version "diablo-1.5.0-b01"
BEA jrockit 1.5java 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); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy