Index: src/main/java/org/apache/maven/plugin/javadoc/AbstractJavadocMojo.java =================================================================== --- src/main/java/org/apache/maven/plugin/javadoc/AbstractJavadocMojo.java (revision 632407) +++ src/main/java/org/apache/maven/plugin/javadoc/AbstractJavadocMojo.java (working copy) @@ -54,7 +54,9 @@ import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException; 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.DefaultPluginManager; import org.apache.maven.plugin.javadoc.options.DocletArtifact; import org.apache.maven.plugin.javadoc.options.Group; import org.apache.maven.plugin.javadoc.options.JavadocPathArtifact; @@ -59,6 +61,7 @@ import org.apache.maven.plugin.javadoc.options.Group; import org.apache.maven.plugin.javadoc.options.JavadocPathArtifact; import org.apache.maven.plugin.javadoc.options.OfflineLink; +import org.apache.maven.plugin.javadoc.options.ResourcesArtifact; import org.apache.maven.plugin.javadoc.options.Tag; import org.apache.maven.plugin.javadoc.options.Taglet; import org.apache.maven.plugin.javadoc.options.TagletArtifact; @@ -67,9 +70,16 @@ 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.apache.maven.wagon.PathUtils; +import org.codehaus.plexus.archiver.UnArchiver; +import org.codehaus.plexus.archiver.manager.ArchiverManager; +import org.codehaus.plexus.archiver.manager.NoSuchArchiverException; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 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; @@ -84,7 +94,6 @@ * @version $Id$ * @since 2.0 * @requiresDependencyResolution compile - * @aggregator */ public abstract class AbstractJavadocMojo extends AbstractMojo @@ -90,6 +99,16 @@ extends AbstractMojo { /** + * The current build session instance. This is used for + * toolchain manager API calls. + * + * @parameter expression="${session}" + * @required + * @readonly + */ + private MavenSession session; + + /** * The current class directory */ private static final String RESOURCE_DIR = ClassUtils.getPackageName( JavadocReport.class ).replace( '.', '/' ); @@ -203,6 +222,25 @@ private ArtifactResolver resolver; /** + * A list of artifacts containing resources which sould be copied into the + * javadoc output directory (like stylesheets, icons, etc.). + *
+ * Example: + *
+     * <resourcesArtifacts>
+ * <resourcesArtifact>
+ * <groupId>external.group.id</groupId>
+ * <artifactId>external-resources</artifactId>
+ * <version>1.0</version>
+ * </resourcesArtifact>
+ * </resourcesArtifacts> + *
+ * + * @parameter expression="${resourcesArtifacts}" + */ + private ResourcesArtifact[] resourcesArtifacts; + + /** * Factory for creating artifact objects * * @component @@ -255,7 +293,8 @@ private boolean debug; /** - * Sets the path of the Javadoc Tool executable to use. + * 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. * * @since 2.3 * @parameter expression="${javadocExecutable}" @@ -352,9 +391,10 @@ *
* See encoding. *
- * Note: Since 2.4, the default value is locked to ISO-8859-1 to better reproducing build. + * Note: In 2.4, the default value was locked to ISO-8859-1 to better reproducing build,but + * this was reverted in 2.5. * - * @parameter expression="${encoding}" default-value="ISO-8859-1" + * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}" */ private String encoding; @@ -1036,6 +1076,12 @@ */ private String windowtitle; + /** + * @component + */ + private ArchiverManager archiverManager; + + // ---------------------------------------------------------------------- // protected methods // ---------------------------------------------------------------------- @@ -1269,6 +1315,46 @@ throw new MavenReportException( "Unable to copy javadoc resources: " + e.getMessage(), e ); } } + + // ---------------------------------------------------------------------- + // Copy additional javadoc resources in artifacts + // ---------------------------------------------------------------------- + if ( resourcesArtifacts != null && resourcesArtifacts.length > 0 ) + { + for ( int i = 0; i < resourcesArtifacts.length; i++ ) + { + ResourcesArtifact item = resourcesArtifacts[i]; + + File target = javadocOutputDirectory; + + UnArchiver unArchiver; + try + { + unArchiver = archiverManager.getUnArchiver( "jar" ); + } + catch ( NoSuchArchiverException e ) + { + throw new MavenReportException( "Unable to extract resources artifact. No archiver for 'jar' available.", e ); + } + + unArchiver.setSourceFile( getArtifactFile( item ) ); + unArchiver.setDestDirectory( target ); + + getLog().info( + "extracting contents of resources artifact: " + item.getGroupId() + ":" + + item.getArtifactId() + ":" + item.getVersion() ); + try + { + unArchiver.extract(); + } + catch ( Exception e ) + { + throw new MavenReportException( "extraction of resources failed. Artifact item that failed was: " + + item ,e); + } + } + } + // ---------------------------------------------------------------------- // Wrap javadoc options @@ -1320,6 +1406,11 @@ addArgIfNotEmpty( arguments, "-doclet", JavadocUtil.quotedArgument( doclet ) ); addArgIfNotEmpty( arguments, "-docletpath", JavadocUtil.quotedPathArgument( getDocletPath() ) ); } + if ( StringUtils.isEmpty( encoding ) ) + { + getLog().warn( "File encoding has not been set, using platform encoding " + ReaderFactory.FILE_ENCODING + + ", i.e. build is platform dependent!" ); + } addArgIfNotEmpty( arguments, "-encoding", JavadocUtil.quotedArgument( encoding ) ); addArgIfNotEmpty( arguments, "-extdirs", JavadocUtil.quotedPathArgument( extdirs ) ); @@ -1668,11 +1759,6 @@ { List sourceRoots = getProjectSourceRoots( subProject ); - if ( subProject.getExecutionProject() != null ) - { - sourceRoots.addAll( getExecutionProjectSourceRoots( subProject ) ); - } - ArtifactHandler artifactHandler = subProject.getArtifact().getArtifactHandler(); if ( "java".equals( artifactHandler.getLanguage() ) ) { @@ -1679,14 +1765,11 @@ sourcePaths.addAll( sourceRoots ); } - if ( subProject.getExecutionProject() != null ) + String javadocDirRelative = PathUtils.toRelative( project.getBasedir(), getJavadocDirectory().getAbsolutePath() ); + File javadocDir = new File( subProject.getBasedir(), javadocDirRelative ); + if ( javadocDir.exists() && javadocDir.isDirectory() ) { - String javadocDirRelative = PathUtils.toRelative( project.getBasedir(), getJavadocDirectory().getAbsolutePath() ); - File javadocDir = new File( subProject.getExecutionProject().getBasedir(), javadocDirRelative ); - if ( javadocDir.exists() && javadocDir.isDirectory() ) - { - sourcePaths.add( javadocDir.getAbsolutePath() ); - } + sourcePaths.add( javadocDir.getAbsolutePath() ); } } } @@ -1701,7 +1784,7 @@ } } - sourcePaths = JavadocUtil.pruneSourceDirs( sourcePaths ); + sourcePaths = JavadocUtil.pruneDirs( sourcePaths ); return sourcePaths; } @@ -1911,6 +1994,31 @@ return StringUtils.join( classpathElements.iterator(), File.pathSeparator ); } + //TODO remove the part with ToolchainManager lookup once we depend on + //3.0.9 (have it as prerequisite). Define as regular component field then. + private Toolchain getToolchain() + { + Toolchain tc = null; + try + { + if ( session != null ) //session is null in tests.. + { + ToolchainManager toolchainManager = (ToolchainManager) session.getContainer() + .lookup( ToolchainManager.ROLE ); + if ( toolchainManager != null ) + { + tc = toolchainManager.getToolchainFromBuildContext( "jdk", session ); + } + } + } + catch ( ComponentLookupException componentLookupException ) + { + //just ignore, could happen in pre-3.0.9 builds.. + } + + return tc; + } + /** * Method to put the artifacts in the hashmap. * @@ -2154,37 +2262,36 @@ } else if ( taglets != null ) { + List tagletsPath = new ArrayList(); for ( int i = 0; i < taglets.length; i++ ) { Taglet current = taglets[i]; - if ( current != null ) + + if ( current == null ) { - boolean separated = false; - if ( current.getTagletArtifact() != null ) - { - path.append( getArtifactAbsolutePath( current.getTagletArtifact() ) ); - separated = true; - } - else if ( ( current.getTagletArtifact() != null ) - && ( StringUtils.isNotEmpty( current.getTagletArtifact().getGroupId() ) ) - && ( StringUtils.isNotEmpty( current.getTagletArtifact().getArtifactId() ) ) - && ( StringUtils.isNotEmpty( current.getTagletArtifact().getVersion() ) ) ) - { - path.append( getArtifactAbsolutePath( current.getTagletArtifact() ) ); - separated = true; - } - else if ( StringUtils.isNotEmpty( current.getTagletpath() ) ) - { - path.append( current.getTagletpath() ); - separated = true; - } + continue; + } - if ( separated && ( i < taglets.length - 1 ) ) - { - path.append( File.pathSeparator ); - } + if ( current.getTagletArtifact() != null ) + { + tagletsPath.add( getArtifactAbsolutePath( current.getTagletArtifact() ) ); + } + else if ( ( current.getTagletArtifact() != null ) + && ( StringUtils.isNotEmpty( current.getTagletArtifact().getGroupId() ) ) + && ( StringUtils.isNotEmpty( current.getTagletArtifact().getArtifactId() ) ) + && ( StringUtils.isNotEmpty( current.getTagletArtifact().getVersion() ) ) ) + { + tagletsPath.add( getArtifactAbsolutePath( current.getTagletArtifact() ) ); + } + else if ( StringUtils.isNotEmpty( current.getTagletpath() ) ) + { + tagletsPath.add( current.getTagletpath() ); } } + + tagletsPath = JavadocUtil.pruneFiles( tagletsPath ); + + path.append( StringUtils.join( tagletsPath.iterator(), File.pathSeparator ) ); } else { @@ -2204,6 +2311,17 @@ private String getArtifactAbsolutePath( JavadocPathArtifact javadocArtifact ) throws MavenReportException { + File artifactFile = getArtifactFile( javadocArtifact ); + if ( artifactFile == null ) + { + return ""; + } + return artifactFile.getAbsolutePath(); + } + + private File getArtifactFile( JavadocPathArtifact javadocArtifact ) + throws MavenReportException + { if ( ( StringUtils.isEmpty( javadocArtifact.getGroupId() ) ) && ( StringUtils.isEmpty( javadocArtifact.getArtifactId() ) ) && ( StringUtils.isEmpty( javadocArtifact.getVersion() ) ) ) @@ -2208,7 +2326,7 @@ && ( StringUtils.isEmpty( javadocArtifact.getArtifactId() ) ) && ( StringUtils.isEmpty( javadocArtifact.getVersion() ) ) ) { - return ""; + return null; } Artifact artifact = factory.createArtifact( javadocArtifact.getGroupId(), javadocArtifact.getArtifactId(), @@ -2216,8 +2334,6 @@ try { resolver.resolve( artifact, remoteRepositories, localRepository ); - - return artifact.getFile().getAbsolutePath(); } catch ( ArtifactResolutionException e ) { @@ -2227,6 +2343,9 @@ { throw new MavenReportException( "Unable to find artifact:" + javadocArtifact, e ); } + + File artifactFile = artifact.getFile(); + return artifactFile; } /** @@ -2332,6 +2451,21 @@ 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; @@ -2343,7 +2477,17 @@ { javadocExe = new File( javadocExecutable ); - if ( !javadocExe.exists() || !javadocExe.isFile() ) + 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." ); @@ -2443,16 +2587,19 @@ */ private void addArgIf( List arguments, boolean b, String value, float requiredJavaVersion ) { - if ( isJavaDocVersionAtLeast( requiredJavaVersion ) ) + if ( b ) { - addArgIf( arguments, b, value ); - } - else - { - if ( getLog().isWarnEnabled() ) + if ( isJavaDocVersionAtLeast( requiredJavaVersion ) ) + { + addArgIf( arguments, b, value ); + } + else { - getLog().warn( value + " option is not supported on Java version < " + requiredJavaVersion - + ". Ignore this option." ); + if ( getLog().isWarnEnabled() ) + { + getLog().warn( value + " option is not supported on Java version < " + requiredJavaVersion + + ". Ignore this option." ); + } } } } @@ -2490,16 +2637,19 @@ */ private void addArgIfNotEmpty( List arguments, String key, String value, boolean repeatKey, boolean splitValue, float requiredJavaVersion ) { - if ( isJavaDocVersionAtLeast( requiredJavaVersion ) ) + if ( StringUtils.isNotEmpty( value ) ) { - addArgIfNotEmpty( arguments, key, value, repeatKey, splitValue ); - } - else - { - if ( getLog().isWarnEnabled() ) + if ( isJavaDocVersionAtLeast( requiredJavaVersion ) ) + { + addArgIfNotEmpty( arguments, key, value, repeatKey, splitValue ); + } + else { - getLog().warn( key + " option is not supported on Java version < " + requiredJavaVersion - + ". Ignore this option." ); + if ( getLog().isWarnEnabled() ) + { + getLog().warn( key + " option is not supported on Java version < " + requiredJavaVersion + + ". Ignore this option." ); + } } } } @@ -2596,15 +2746,18 @@ private void addArgIfNotEmpty( List arguments, String key, String value, float requiredJavaVersion, boolean repeatKey ) { - if ( isJavaDocVersionAtLeast( requiredJavaVersion ) ) - { - addArgIfNotEmpty( arguments, key, value, repeatKey ); - } - else + if ( StringUtils.isNotEmpty( value ) ) { - if ( getLog().isWarnEnabled() ) + if ( isJavaDocVersionAtLeast( requiredJavaVersion ) ) + { + addArgIfNotEmpty( arguments, key, value, repeatKey ); + } + else { - getLog().warn( key + " option is not supported on Java version < " + requiredJavaVersion ); + if ( getLog().isWarnEnabled() ) + { + getLog().warn( key + " option is not supported on Java version < " + requiredJavaVersion ); + } } } } @@ -2616,7 +2769,8 @@ */ private void addLinkofflineArguments( List arguments ) { - List offlineLinksList = ( offlineLinks != null ? new ArrayList( Arrays.asList( offlineLinks ) ): new ArrayList() ); + List offlineLinksList = ( offlineLinks != null ? new ArrayList( Arrays.asList( offlineLinks ) ) + : new ArrayList() ); if ( !aggregate && reactorProjects != null ) { Index: src/main/mdo/javadocOptions.mdo =================================================================== --- src/main/mdo/javadocOptions.mdo (revision 632407) +++ src/main/mdo/javadocOptions.mdo (working copy) @@ -178,6 +178,13 @@ + ResourcesArtifact + A artifact containing resources. + 1.0.0 + JavadocPathArtifact + + + Taglet A Taglet parameter. 1.0.0 Index: pom.xml =================================================================== --- pom.xml (revision 657826) +++ pom.xml (working copy) @@ -247,6 +247,7 @@ src/it + **/extra-resources/pom.xml **/MJAVADOC-110/pom.xml **/MJAVADOC-137/pom.xml **/MJAVADOC-172/pom.xml