* <!-- Use all mojo extractors -->
* <extractors/>
- *
+ *
* <!-- Use no mojo extractors -->
* <extractors>
* <extractor/>
* </extractors>
- *
+ *
* <!-- Use only bsh mojo extractor -->
* <extractors>
* <extractor>bsh</extractor>
@@ -114,6 +128,36 @@ public abstract class AbstractGeneratorMojo
*/
protected boolean skip;
+ /**
+ * The set of dependencies for the current project
+ *
+ * @parameter default-value = "${project.artifacts}"
+ * @required
+ * @readonly
+ * @since 3.0
+ */
+ protected Set dependencies;
+
+ /**
+ * List of Remote Repositories used by the resolver
+ *
+ * @parameter expression="${project.remoteArtifactRepositories}"
+ * @readonly
+ * @required
+ * @since 3.0
+ */
+ protected List remoteRepos;
+
+ /**
+ * Location of the local repository.
+ *
+ * @parameter expression="${localRepository}"
+ * @readonly
+ * @required
+ * @since 3.0
+ */
+ protected ArtifactRepository local;
+
/**
* @return the output directory where files will be generated.
*/
@@ -124,7 +168,9 @@ public abstract class AbstractGeneratorMojo
*/
protected abstract Generator createGenerator();
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public void execute()
throws MojoExecutionException
{
@@ -138,11 +184,11 @@ public abstract class AbstractGeneratorMojo
return;
}
- if ( project.getArtifactId().toLowerCase().startsWith( "maven-" )
- && project.getArtifactId().toLowerCase().endsWith( "-plugin" )
- && !"org.apache.maven.plugins".equals( project.getGroupId() ) )
+ if ( project.getArtifactId().toLowerCase().startsWith( "maven-" )
+ && project.getArtifactId().toLowerCase().endsWith( "-plugin" ) && !"org.apache.maven.plugins".equals(
+ project.getGroupId() ) )
{
- getLog().error( "\n\nArtifact Ids of the format maven-___-plugin are reserved for \n"
+ getLog().error( "\n\nArtifact Ids of the format maven-___-plugin are reserved for \n"
+ "plugins in the Group Id org.apache.maven.plugins\n"
+ "Please change your artifactId to the format ___-maven-plugin\n"
+ "In the future this error will break the build.\n\n" );
@@ -156,8 +202,8 @@ public abstract class AbstractGeneratorMojo
else if ( !goalPrefix.equals( defaultGoalPrefix ) )
{
getLog().warn(
- "\n\nGoal prefix is specified as: '" + goalPrefix + "'. "
- + "Maven currently expects it to be '" + defaultGoalPrefix + "'.\n" );
+ "\n\nGoal prefix is specified as: '" + goalPrefix + "'. " + "Maven currently expects it to be '"
+ + defaultGoalPrefix + "'.\n" );
}
mojoScanner.setActiveExtractors( extractors );
@@ -180,19 +226,23 @@ public abstract class AbstractGeneratorMojo
if ( encoding == null || encoding.length() < 1 )
{
getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
- + " actually) to read mojo metadata, i.e. build is platform dependent!" );
+ + " actually) to read mojo metadata, i.e. build is platform dependent!" );
}
else
{
getLog().info( "Using '" + encoding + "' encoding to read mojo metadata." );
}
-
+
try
{
pluginDescriptor.setDependencies( PluginUtils.toComponentDependencies( project.getRuntimeDependencies() ) );
-
+
PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
request.setEncoding( encoding );
+ request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
+ request.setDependencies( dependencies );
+ request.setLocal( this.local );
+ request.setRemoteRepos( this.remoteRepos );
mojoScanner.populatePluginDescriptor( request );
@@ -200,7 +250,7 @@ public abstract class AbstractGeneratorMojo
createGenerator().execute( getOutputDirectory(), request );
}
- catch ( IOException e )
+ catch ( GeneratorException e )
{
throw new MojoExecutionException( "Error writing plugin descriptor", e );
}
@@ -217,7 +267,8 @@ public abstract class AbstractGeneratorMojo
catch ( LinkageError e )
{
throw new MojoExecutionException( "The API of the mojo scanner is not compatible with this plugin version."
- + " Please check the plugin dependencies configured in the POM and ensure the versions match.", e );
+ + " Please check the plugin dependencies configured in the POM and ensure the versions match.",
+ e );
}
}
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
index 1bac881..ae14d31 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
@@ -19,20 +19,21 @@ package org.apache.maven.plugin.plugin;
* under the License.
*/
-import java.io.File;
-
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.tools.plugin.generator.Generator;
import org.apache.maven.tools.plugin.generator.PluginHelpGenerator;
+import org.codehaus.plexus.velocity.VelocityComponent;
+
+import java.io.File;
/**
* Generates a HelpMojo class.
*
* @author Vincent Siveton
* @version $Id$
- * @since 2.4
* @goal helpmojo
* @phase generate-sources
+ * @since 2.4
*/
public class HelpGeneratorMojo
extends AbstractGeneratorMojo
@@ -47,7 +48,7 @@ public class HelpGeneratorMojo
/**
* The name of the package for the generated HelpMojo. By default, the package will be calculated based
* on the packages of the other plugin goals.
- *
+ *
* @parameter
* @since 2.6
*/
@@ -61,19 +62,35 @@ public class HelpGeneratorMojo
*/
private boolean useJava5;
- /** {@inheritDoc} */
+ /**
+ * Velocity component.
+ *
+ * @component
+ * @readonly
+ * @required
+ */
+ private VelocityComponent velocity;
+
+ /**
+ * {@inheritDoc}
+ */
protected File getOutputDirectory()
{
return outputDirectory;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
protected Generator createGenerator()
{
- return new PluginHelpGenerator().setHelpPackageName( helpPackageName ).setUseJava5( useJava5 );
+ return new PluginHelpGenerator().setHelpPackageName( helpPackageName ).setUseJava5(
+ useJava5 ).setVelocityComponent( this.velocity );
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public void execute()
throws MojoExecutionException
{
@@ -83,5 +100,7 @@ public class HelpGeneratorMojo
{
project.addCompileSourceRoot( outputDirectory.getAbsolutePath() );
}
+
}
+
}
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java
index b2ee032..ec0bbf1 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/PluginReport.java
@@ -19,15 +19,6 @@ package org.apache.maven.plugin.plugin;
* under the License.
*/
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.ResourceBundle;
-
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.model.Plugin;
@@ -42,21 +33,30 @@ import org.apache.maven.reporting.MavenReportException;
import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
import org.apache.maven.tools.plugin.PluginToolsRequest;
import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.generator.GeneratorException;
import org.apache.maven.tools.plugin.generator.PluginXdocGenerator;
import org.apache.maven.tools.plugin.scanner.MojoScanner;
import org.apache.maven.tools.plugin.util.PluginUtils;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.Xpp3Dom;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
/**
* Generates the Plugin's documentation report.
*
* @author Stephane Nicoll
* @author Vincent Siveton
* @version $Id$
- * @since 2.0
* @goal report
* @execute phase="compile"
+ * @since 2.0
*/
public class PluginReport
extends AbstractMavenReport
@@ -91,13 +91,12 @@ public class PluginReport
*/
protected MojoScanner mojoScanner;
- /**
- * The file encoding of the source files.
- *
- * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
- *
- * @since 2.7
- */
+ /**
+ * The file encoding of the source files.
+ *
+ * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
+ * @since 2.7
+ */
private String encoding;
@@ -124,10 +123,10 @@ public class PluginReport
private Requirements requirements;
/**
- * The goal prefix that will appear before the ":".
- * By default, this plugin applies a heuristic to derive a heuristic from
- * the plugin's artifactId.
- *
+ * The goal prefix that will appear before the ":".
+ * By default, this plugin applies a heuristic to derive a heuristic from
+ * the plugin's artifactId.
+ *
* It removes any occurrences of the regular expression -?maven-?,
* and then removes any occurrences of -?plugin-?.
*
@@ -158,31 +157,41 @@ public class PluginReport
*/
private boolean skipReport;
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
protected Renderer getSiteRenderer()
{
return siteRenderer;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
protected String getOutputDirectory()
{
return outputDirectory.getPath();
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
protected MavenProject getProject()
{
return project;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public boolean canGenerateReport()
{
return "maven-plugin".equals( project.getPackaging() );
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
@SuppressWarnings( "unchecked" )
protected void executeReport( Locale locale )
throws MavenReportException
@@ -205,8 +214,7 @@ public class PluginReport
}
else
{
- getLog().warn(
- "\n\nGoal prefix is specified as: '" + goalPrefix + "'. Maven currently expects it to be '"
+ getLog().warn( "\n\nGoal prefix is specified as: '" + goalPrefix + "'. Maven currently expects it to be '"
+ defaultGoalPrefix + "'.\n" );
}
@@ -224,11 +232,11 @@ public class PluginReport
try
{
pluginDescriptor.setDependencies( PluginUtils.toComponentDependencies( project.getRuntimeDependencies() ) );
-
+
PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
request.setEncoding( encoding );
- try
+ try
{
mojoScanner.populatePluginDescriptor( request );
}
@@ -243,11 +251,11 @@ public class PluginReport
generatePluginDocumentation( pluginDescriptor, locale );
// Write the overview
- PluginOverviewRenderer r = new PluginOverviewRenderer( project, requirements, getSink(), pluginDescriptor,
- locale );
+ PluginOverviewRenderer r =
+ new PluginOverviewRenderer( project, requirements, getSink(), pluginDescriptor, locale );
r.render();
}
-
+
catch ( ExtractionException e )
{
throw new MavenReportException( "Error extracting plugin descriptor: \'" + e.getLocalizedMessage() + "\'",
@@ -255,19 +263,25 @@ public class PluginReport
}
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getDescription( Locale locale )
{
return getBundle( locale ).getString( "report.plugin.description" );
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getName( Locale locale )
{
return getBundle( locale ).getString( "report.plugin.name" );
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getOutputName()
{
return "plugin-info";
@@ -275,7 +289,7 @@ public class PluginReport
/**
* @param pluginDescriptor not null
- * @param locale not null
+ * @param locale not null
* @throws MavenReportException if any
*/
private void generatePluginDocumentation( PluginDescriptor pluginDescriptor, Locale locale )
@@ -287,9 +301,10 @@ public class PluginReport
outputDir.mkdirs();
PluginXdocGenerator generator = new PluginXdocGenerator( project, locale );
- generator.execute( outputDir, pluginDescriptor );
+ PluginToolsRequest pluginToolsRequest = new DefaultPluginToolsRequest( project, pluginDescriptor );
+ generator.execute( outputDir, pluginToolsRequest );
}
- catch ( IOException e )
+ catch ( GeneratorException e )
{
throw new MavenReportException( "Error writing plugin documentation", e );
}
@@ -321,11 +336,11 @@ public class PluginReport
private final Locale locale;
/**
- * @param project not null
- * @param requirements not null
- * @param sink not null
+ * @param project not null
+ * @param requirements not null
+ * @param sink not null
* @param pluginDescriptor not null
- * @param locale not null
+ * @param locale not null
*/
public PluginOverviewRenderer( MavenProject project, Requirements requirements, Sink sink,
PluginDescriptor pluginDescriptor, Locale locale )
@@ -341,13 +356,17 @@ public class PluginReport
this.locale = locale;
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public String getTitle()
{
return getBundle( locale ).getString( "report.plugin.title" );
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
@SuppressWarnings( { "unchecked", "rawtypes" } )
public void renderBody()
{
@@ -362,7 +381,6 @@ public class PluginReport
paragraph( getBundle( locale ).getString( "report.plugin.goals.intro" ) );
-
boolean hasMavenReport = false;
for ( Iterator i = pluginDescriptor.getMojos().iterator(); i.hasNext(); )
{
@@ -381,11 +399,11 @@ public class PluginReport
String descriptionColumnName = getBundle( locale ).getString( "report.plugin.goals.column.description" );
if ( hasMavenReport )
{
- tableHeader( new String[] { goalColumnName, isMavenReport, descriptionColumnName } );
+ tableHeader( new String[]{ goalColumnName, isMavenReport, descriptionColumnName } );
}
else
{
- tableHeader( new String[] { goalColumnName, descriptionColumnName } );
+ tableHeader( new String[]{ goalColumnName, descriptionColumnName } );
}
List mojos = new ArrayList();
@@ -449,15 +467,16 @@ public class PluginReport
String maven = discoverMavenRequirement( project, requirements );
sink.tableRow();
tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.maven" ) );
- tableCell( ( maven != null ? maven : getBundle( locale )
- .getString( "report.plugin.systemrequirements.nominimum" ) ) );
+ tableCell( ( maven != null
+ ? maven
+ : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
sink.tableRow_();
String jdk = discoverJdkRequirement( project, requirements );
sink.tableRow();
tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.jdk" ) );
- tableCell( ( jdk != null ? jdk : getBundle( locale )
- .getString( "report.plugin.systemrequirements.nominimum" ) ) );
+ tableCell(
+ ( jdk != null ? jdk : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
sink.tableRow_();
sink.tableRow();
@@ -482,9 +501,9 @@ public class PluginReport
sink.tableRow();
tableCell( key );
- tableCell( ( StringUtils.isNotEmpty( requirements.getOthers().getProperty( key ) ) ? requirements
- .getOthers().getProperty( key ) : getBundle( locale )
- .getString( "report.plugin.systemrequirements.nominimum" ) ) );
+ tableCell( ( StringUtils.isNotEmpty( requirements.getOthers().getProperty( key ) )
+ ? requirements.getOthers().getProperty( key )
+ : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
sink.tableRow_();
}
}
@@ -515,31 +534,32 @@ public class PluginReport
sb.append( "" ).append( '\n' );
sb.append( " ..." ).append( '\n' );
sb.append( " " ).append( '\n' );
- sb.append( " " )
- .append( '\n' );
+ sb.append(
+ " " ).append(
+ '\n' );
sb.append( " " ).append( '\n' );
sb.append( " " ).append( '\n' );
sb.append( " " ).append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( " " )
- .append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( " " )
- .append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getVersion() ).append( " " )
- .append( '\n' );
+ sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( " " ).append(
+ '\n' );
+ sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append(
+ " " ).append( '\n' );
+ sb.append( " " ).append( pluginDescriptor.getVersion() ).append( " " ).append(
+ '\n' );
sb.append( " " ).append( '\n' );
sb.append( " ..." ).append( '\n' );
sb.append( " " ).append( '\n' );
sb.append( " " ).append( '\n' );
- sb.append( " " )
- .append( '\n' );
+ sb.append( " " ).append(
+ '\n' );
sb.append( " " ).append( '\n' );
sb.append( " " ).append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( " " )
- .append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( " " )
- .append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getVersion() ).append( " " )
- .append( '\n' );
+ sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( " " ).append(
+ '\n' );
+ sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append(
+ " " ).append( '\n' );
+ sb.append( " " ).append( pluginDescriptor.getVersion() ).append( " " ).append(
+ '\n' );
sb.append( " " ).append( '\n' );
sb.append( " ..." ).append( '\n' );
sb.append( " " ).append( '\n' );
@@ -548,17 +568,18 @@ public class PluginReport
if ( hasMavenReport )
{
sb.append( " ..." ).append( '\n' );
- sb.append( " " )
- .append( '\n' );
+ sb.append(
+ " " ).append(
+ '\n' );
sb.append( " " ).append( '\n' );
sb.append( " " ).append( '\n' );
sb.append( " " ).append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( " " )
- .append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append( " " )
- .append( '\n' );
- sb.append( " " ).append( pluginDescriptor.getVersion() ).append( " " )
- .append( '\n' );
+ sb.append( " " ).append( pluginDescriptor.getGroupId() ).append( " " ).append(
+ '\n' );
+ sb.append( " " ).append( pluginDescriptor.getArtifactId() ).append(
+ " " ).append( '\n' );
+ sb.append( " " ).append( pluginDescriptor.getVersion() ).append( " " ).append(
+ '\n' );
sb.append( " " ).append( '\n' );
sb.append( " ..." ).append( '\n' );
sb.append( " " ).append( '\n' );
@@ -581,7 +602,7 @@ public class PluginReport
* Try to lookup on the Maven prerequisites property.
* If not specified, uses the value defined by the user.
*
- * @param project not null
+ * @param project not null
* @param requirements not null
* @return the Maven version
*/
@@ -606,7 +627,7 @@ public class PluginReport
* If not specified, uses the value defined by the user.
* If not specified, uses the value of the system property java.specification.version.
*
- * @param project not null
+ * @param project not null
* @param requirements not null
* @return the JDK version
*/
@@ -686,11 +707,11 @@ public class PluginReport
jdk = pluginConf.getChild( "target" ).getValue();
}
- if ( jdk == null )
+ if ( jdk == null )
{
return backupJdk;
}
- else
+ else
{
return jdk;
}
diff --git a/maven-plugin-tools-annotations/pom.xml b/maven-plugin-tools-annotations/pom.xml
new file mode 100644
index 0000000..bef9e8a
--- /dev/null
+++ b/maven-plugin-tools-annotations/pom.xml
@@ -0,0 +1,125 @@
+
+
+
+ 4.0.0
+
+ org.apache.maven.plugin-tools
+ maven-plugin-tools
+ 3.0-SNAPSHOT
+
+
+ maven-plugin-tools-annotations
+
+ Maven Plugin Tools Annotations
+
+
+
+
+
+ org.apache.maven
+ maven-project
+
+
+ org.apache.maven
+ maven-model
+
+
+ org.apache.maven
+ maven-plugin-descriptor
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-tools-api
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+
+
+
+ org.codehaus.plexus
+ plexus-utils
+
+
+ org.codehaus.plexus
+ plexus-container-default
+
+
+ asm
+ asm
+
+
+ asm
+ asm-commons
+
+
+
+ org.codehaus.plexus
+ plexus-archiver
+
+
+
+ com.thoughtworks.qdox
+ qdox
+
+
+
+ org.codehaus.plexus
+ plexus-compiler-manager
+ 1.8.6
+
+
+ org.codehaus.plexus
+ plexus-component-api
+
+
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ test-jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+
+ test-jar-no-fork
+
+
+
+
+
+
+
+
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/JavaAnnotationsMojoDescriptorExtractor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/JavaAnnotationsMojoDescriptorExtractor.java
new file mode 100644
index 0000000..e24eb5e
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/JavaAnnotationsMojoDescriptorExtractor.java
@@ -0,0 +1,647 @@
+package org.apache.maven.tools.plugin.annotations;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.model.DocletTag;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaField;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.plugin.descriptor.DuplicateParameterException;
+import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.descriptor.Requirement;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
+import org.apache.maven.tools.plugin.PluginToolsRequest;
+import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass;
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner;
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScannerRequest;
+import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
+import org.codehaus.plexus.archiver.UnArchiver;
+import org.codehaus.plexus.archiver.manager.ArchiverManager;
+import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
+import org.codehaus.plexus.util.StringUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class JavaAnnotationsMojoDescriptorExtractor
+ extends AbstractLogEnabled
+ implements MojoDescriptorExtractor
+{
+
+ /**
+ * @requirement
+ */
+ private MojoAnnotationsScanner mojoAnnotationsScanner;
+
+ /**
+ * @requirement
+ */
+ private ArtifactResolver artifactResolver;
+
+ /**
+ * @requirement
+ */
+ private ArtifactFactory artifactFactory;
+
+ /**
+ * @requirement
+ */
+ private ArchiverManager archiverManager;
+
+ public List execute( MavenProject project, PluginDescriptor pluginDescriptor )
+ throws ExtractionException, InvalidPluginDescriptorException
+ {
+ return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) );
+ }
+
+ public List execute( PluginToolsRequest request )
+ throws ExtractionException, InvalidPluginDescriptorException
+ {
+
+ MojoAnnotationsScannerRequest mojoAnnotationsScannerRequest = new MojoAnnotationsScannerRequest();
+
+ mojoAnnotationsScannerRequest.setClassesDirectories(
+ Arrays.asList( new File( request.getProject().getBuild().getOutputDirectory() ) ) );
+
+ mojoAnnotationsScannerRequest.setDependencies( request.getDependencies() );
+
+ mojoAnnotationsScannerRequest.setProject( request.getProject() );
+
+ Map mojoAnnotatedClasses =
+ mojoAnnotationsScanner.scan( mojoAnnotationsScannerRequest );
+
+ // found artifact from reactors to scan sources
+ // we currently only scan sources from reactors
+ List mavenProjects = new ArrayList();
+
+ // if we need to scan sources from external artifacts
+ Set externalArtifacts = new HashSet();
+
+ for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses.values() )
+ {
+ if ( !StringUtils.equals( mojoAnnotatedClass.getArtifact().getArtifactId(),
+ request.getProject().getArtifact().getArtifactId() ) )
+ {
+ MavenProject mavenProject =
+ getFromProjectReferences( mojoAnnotatedClass.getArtifact(), request.getProject() );
+ if ( mavenProject != null )
+ {
+ mavenProjects.add( mavenProject );
+ }
+ else
+ {
+ externalArtifacts.add( mojoAnnotatedClass.getArtifact() );
+ }
+ }
+ }
+
+ Map javaClassesMap = new HashMap();
+
+ // try to get artifact with classifier sources
+ // extract somewhere then scan doclet for @since, @deprecated
+ for ( Artifact artifact : externalArtifacts )
+ {
+ // parameter for test-sources too ?? olamy I need that for it test only
+ if ( StringUtils.equalsIgnoreCase( "tests", artifact.getClassifier() ) )
+ {
+ javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "test-sources" ) );
+ }
+ else
+ {
+ javaClassesMap.putAll( discoverClassesFromSourcesJar( artifact, request, "sources" ) );
+ }
+
+ }
+
+ for ( MavenProject mavenProject : mavenProjects )
+ {
+ javaClassesMap.putAll( discoverClasses( request.getEncoding(), mavenProject ) );
+ }
+
+ javaClassesMap.putAll( discoverClasses( request ) );
+
+ populateDataFromJavadoc( mojoAnnotatedClasses, javaClassesMap );
+
+ return toMojoDescriptors( mojoAnnotatedClasses, request, javaClassesMap );
+
+ }
+
+
+ protected Map discoverClassesFromSourcesJar( Artifact artifact, PluginToolsRequest request,
+ String classifier )
+ throws ExtractionException
+ {
+ try
+ {
+ Artifact sourcesArtifact =
+ artifactFactory.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(),
+ artifact.getVersion(), artifact.getType(), classifier );
+
+ artifactResolver.resolve( sourcesArtifact, request.getRemoteRepos(), request.getLocal() );
+ if ( sourcesArtifact.getFile() != null && sourcesArtifact.getFile().exists() )
+ {
+ File extractDirectory = new File( request.getProject().getBuild().getDirectory(),
+ "maven-plugin-plugin-sources/" + sourcesArtifact.getGroupId() + "/"
+ + sourcesArtifact.getArtifactId() + "/"
+ + sourcesArtifact.getVersion() + "/"
+ + sourcesArtifact.getClassifier() );
+ if ( !extractDirectory.exists() )
+ {
+ extractDirectory.mkdirs();
+ }
+ // extract sources in a directory
+ //target/maven-plugin-plugin/${groupId}/${artifact}/sources
+ UnArchiver unArchiver = archiverManager.getUnArchiver( "jar" );
+ unArchiver.setSourceFile( sourcesArtifact.getFile() );
+ unArchiver.setDestDirectory( extractDirectory );
+ unArchiver.extract();
+
+ return discoverClasses( request.getEncoding(), Arrays.asList( extractDirectory ) );
+ }
+ }
+ catch ( ArtifactResolutionException e )
+ {
+ throw new ExtractionException( e.getMessage(), e );
+ }
+ catch ( ArtifactNotFoundException e )
+ {
+ //throw new ExtractionException( e.getMessage(), e );
+ getLogger().debug( "skip ArtifactNotFoundException:" + e.getMessage() );
+ getLogger().warn(
+ "Impossible to get sources artifact for " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":"
+ + artifact.getVersion() + ". Some javadoc tags (@since, @deprecated and comments) won't be used" );
+ }
+ catch ( NoSuchArchiverException e )
+ {
+ throw new ExtractionException( e.getMessage(), e );
+ }
+ return Collections.emptyMap();
+ }
+
+ /**
+ * from sources scan to get @since and @deprecated and description of classes and fields.
+ *
+ * @param mojoAnnotatedClasses
+ * @param javaClassesMap
+ */
+ protected void populateDataFromJavadoc( Map mojoAnnotatedClasses,
+ Map javaClassesMap )
+ {
+
+ for ( Map.Entry entry : mojoAnnotatedClasses.entrySet() )
+ {
+ JavaClass javaClass = javaClassesMap.get( entry.getKey() );
+ if ( javaClass != null )
+ {
+ MojoAnnotationContent mojoAnnotationContent = entry.getValue().getMojo();
+ if ( mojoAnnotationContent != null )
+ {
+ mojoAnnotationContent.setDescription( javaClass.getComment() );
+ DocletTag since = findInClassHierarchy( javaClass, "since" );
+ if ( since != null )
+ {
+ mojoAnnotationContent.setSince( since.getValue() );
+ }
+
+ DocletTag deprecated = findInClassHierarchy( javaClass, "deprecated" );
+ if ( deprecated != null )
+ {
+ mojoAnnotationContent.setDeprecated( deprecated.getValue() );
+ }
+ }
+ Map fieldsMap =
+ extractFieldParameterTags( javaClass, javaClassesMap, mojoAnnotatedClasses );
+ Map parameters =
+ getParametersParentHierarchy( entry.getValue(), new HashMap(),
+ mojoAnnotatedClasses );
+ for ( Map.Entry parameter : new TreeMap(
+ parameters ).entrySet() )
+ {
+ JavaField javaField = fieldsMap.get( parameter.getKey() );
+ if ( javaField != null )
+ {
+ ParameterAnnotationContent parameterAnnotationContent = parameter.getValue();
+ DocletTag deprecated = javaField.getTagByName( "deprecated" );
+ if ( deprecated != null )
+ {
+ parameterAnnotationContent.setDeprecated( deprecated.getValue() );
+ }
+ DocletTag since = javaField.getTagByName( "since" );
+ if ( since != null )
+ {
+ parameterAnnotationContent.setSince( since.getValue() );
+ }
+ parameterAnnotationContent.setDescription( javaField.getComment() );
+ }
+ }
+
+ for ( Map.Entry component : entry.getValue().getComponents().entrySet() )
+ {
+ JavaField javaField = fieldsMap.get( component.getKey() );
+ if ( javaField != null )
+ {
+ ComponentAnnotationContent componentAnnotationContent = component.getValue();
+ DocletTag deprecated = javaField.getTagByName( "deprecated" );
+ if ( deprecated != null )
+ {
+ componentAnnotationContent.setDeprecated( deprecated.getValue() );
+ }
+ DocletTag since = javaField.getTagByName( "since" );
+ if ( since != null )
+ {
+ componentAnnotationContent.setSince( since.getValue() );
+ }
+ componentAnnotationContent.setDescription( javaField.getComment() );
+ }
+ }
+
+ }
+ }
+
+ }
+
+ /**
+ * @param javaClass not null
+ * @param tagName not null
+ * @return docletTag instance
+ */
+ private DocletTag findInClassHierarchy( JavaClass javaClass, String tagName )
+ {
+ DocletTag tag = javaClass.getTagByName( tagName );
+
+ if ( tag == null )
+ {
+ JavaClass superClass = javaClass.getSuperJavaClass();
+
+ if ( superClass != null )
+ {
+ tag = findInClassHierarchy( superClass, tagName );
+ }
+ }
+
+ return tag;
+ }
+
+ /**
+ * extract fields that are either parameters or components.
+ *
+ * @param javaClass not null
+ * @return map with Mojo parameters names as keys
+ */
+ private Map extractFieldParameterTags( JavaClass javaClass,
+ Map javaClassesMap,
+ Map mojoAnnotatedClasses )
+ {
+ Map rawParams = new TreeMap();
+
+ // we have to add the parent fields first, so that they will be overwritten by the local fields if
+ // that actually happens...
+ JavaClass superClass = javaClass.getSuperJavaClass();
+
+ if ( superClass != null )
+ {
+ if ( superClass.getFields().length > 0 )
+ {
+ rawParams = extractFieldParameterTags( superClass, javaClassesMap, mojoAnnotatedClasses );
+ }
+ // maybe sources comes from scan of sources artifact
+ superClass = javaClassesMap.get( superClass.getFullyQualifiedName() );
+ if ( superClass != null )
+ {
+ rawParams = extractFieldParameterTags( superClass, javaClassesMap, mojoAnnotatedClasses );
+ }
+ }
+ else
+ {
+
+ rawParams = new TreeMap();
+ }
+
+ JavaField[] classFields = javaClass.getFields();
+
+ if ( classFields != null )
+ {
+ for ( JavaField field : classFields )
+ {
+ rawParams.put( field.getName(), field );
+ }
+ }
+ return rawParams;
+ }
+
+ protected Map discoverClasses( final PluginToolsRequest request )
+ {
+ return discoverClasses( request.getEncoding(), request.getProject() );
+ }
+
+ protected Map discoverClasses( final String encoding, final MavenProject project )
+ {
+ List sources = new ArrayList();
+
+ for ( String source : (List) project.getCompileSourceRoots() )
+ {
+ sources.add( new File( source ) );
+ }
+
+ // TODO be more dynamic
+ File generatedPlugin = new File( project.getBasedir(), "target/generated-sources/plugin" );
+ if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() )
+ && generatedPlugin.exists() )
+ {
+ sources.add( generatedPlugin );
+ }
+
+ return discoverClasses( encoding, sources );
+ }
+
+ protected Map discoverClasses( final String encoding, List sourceDirectories )
+ {
+ JavaDocBuilder builder = new JavaDocBuilder();
+ builder.setEncoding( encoding );
+
+ for ( File source : sourceDirectories )
+ {
+ builder.addSourceTree( source );
+ }
+
+ JavaClass[] javaClasses = builder.getClasses();
+
+ if ( javaClasses == null || javaClasses.length < 1 )
+ {
+ return Collections.emptyMap();
+ }
+
+ Map javaClassMap = new HashMap( javaClasses.length );
+
+ for ( JavaClass javaClass : javaClasses )
+ {
+ javaClassMap.put( javaClass.getFullyQualifiedName(), javaClass );
+ }
+
+ return javaClassMap;
+ }
+
+ private List toMojoDescriptors( Map mojoAnnotatedClasses,
+ PluginToolsRequest request, Map javaClassesMap )
+ throws DuplicateParameterException
+ {
+ List mojoDescriptors = new ArrayList( mojoAnnotatedClasses.size() );
+ for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses.values() )
+ {
+ // no mojo so skip it
+ if ( mojoAnnotatedClass.getMojo() == null )
+ {
+ continue;
+ }
+
+ ExtendedMojoDescriptor mojoDescriptor = new ExtendedMojoDescriptor();
+
+ //mojoDescriptor.setRole( mojoAnnotatedClass.getClassName() );
+ //mojoDescriptor.setRoleHint( "default" );
+ mojoDescriptor.setImplementation( mojoAnnotatedClass.getClassName() );
+ mojoDescriptor.setLanguage( "java" );
+
+ MojoAnnotationContent mojo = mojoAnnotatedClass.getMojo();
+
+ mojoDescriptor.setDescription( mojo.getDescription() );
+ mojoDescriptor.setSince( mojo.getSince() );
+ mojo.setDeprecated( mojo.getDeprecated() );
+
+ mojoDescriptor.setAggregator( mojo.aggregator() );
+ mojoDescriptor.setDependencyResolutionRequired( mojo.requiresDependencyResolution() );
+ mojoDescriptor.setDependencyCollectionRequired( mojo.requiresDependencyCollection() );
+
+ mojoDescriptor.setDirectInvocationOnly( mojo.requiresDirectInvocation() );
+ mojoDescriptor.setDeprecated( mojo.getDeprecated() );
+ mojoDescriptor.setThreadSafe( mojo.threadSafe() );
+
+ ExecuteAnnotationContent execute = findExecuteInParentHierarchy( mojoAnnotatedClass, mojoAnnotatedClasses );
+ if ( execute != null )
+ {
+ mojoDescriptor.setExecuteGoal( execute.goal() );
+ mojoDescriptor.setExecuteLifecycle( execute.lifecycle() );
+ mojoDescriptor.setExecutePhase( execute.phase().id() );
+ }
+
+ mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() );
+ // ???
+ //mojoDescriptor.alwaysExecute(mojo.a)
+
+ mojoDescriptor.setGoal( mojo.name() );
+ mojoDescriptor.setOnlineRequired( mojo.requiresOnline() );
+
+ mojoDescriptor.setPhase( mojo.defaultPhase().id() );
+
+ Map parameters =
+ getParametersParentHierarchy( mojoAnnotatedClass, new HashMap(),
+ mojoAnnotatedClasses );
+
+ for ( ParameterAnnotationContent parameterAnnotationContent : new TreeSet(
+ parameters.values() ) )
+ {
+ org.apache.maven.plugin.descriptor.Parameter parameter =
+ new org.apache.maven.plugin.descriptor.Parameter();
+ parameter.setName( parameterAnnotationContent.getFieldName() );
+ parameter.setAlias( parameterAnnotationContent.alias() );
+ parameter.setDefaultValue( parameterAnnotationContent.defaultValue() );
+ parameter.setDeprecated( parameterAnnotationContent.getDeprecated() );
+ parameter.setDescription( parameterAnnotationContent.getDescription() );
+ parameter.setEditable( !parameterAnnotationContent.readonly() );
+ parameter.setExpression( parameterAnnotationContent.expression() );
+ parameter.setType( parameterAnnotationContent.getClassName() );
+ parameter.setSince( parameterAnnotationContent.getSince() );
+ parameter.setRequired( parameterAnnotationContent.required() );
+
+ mojoDescriptor.addParameter( parameter );
+ }
+
+ Map components =
+ getComponentsParentHierarchy( mojoAnnotatedClass, new HashMap(),
+ mojoAnnotatedClasses );
+
+ for ( ComponentAnnotationContent componentAnnotationContent : new TreeSet(
+ components.values() ) )
+ {
+ org.apache.maven.plugin.descriptor.Parameter parameter =
+ new org.apache.maven.plugin.descriptor.Parameter();
+ parameter.setName( componentAnnotationContent.getFieldName() );
+ parameter.setRequirement(
+ new Requirement( componentAnnotationContent.role(), componentAnnotationContent.roleHint() ) );
+ parameter.setEditable( false );
+ parameter.setDeprecated( componentAnnotationContent.getDeprecated() );
+ parameter.setSince( componentAnnotationContent.getSince() );
+ mojoDescriptor.addParameter( parameter );
+ }
+
+ mojoDescriptor.setPluginDescriptor( request.getPluginDescriptor() );
+
+ mojoDescriptors.add( mojoDescriptor );
+ }
+ return mojoDescriptors;
+ }
+
+
+ protected ExecuteAnnotationContent findExecuteInParentHierarchy( MojoAnnotatedClass mojoAnnotatedClass,
+ Map mojoAnnotatedClasses )
+ {
+
+ if ( mojoAnnotatedClass.getExecute() != null )
+ {
+ return mojoAnnotatedClass.getExecute();
+ }
+ String parentClassName = mojoAnnotatedClass.getParentClassName();
+ if ( StringUtils.isEmpty( parentClassName ) )
+ {
+ return null;
+ }
+ MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName );
+ if ( parent == null )
+ {
+ return null;
+ }
+ return findExecuteInParentHierarchy( parent, mojoAnnotatedClasses );
+ }
+
+
+ protected Map getParametersParentHierarchy(
+ MojoAnnotatedClass mojoAnnotatedClass, Map parameters,
+ Map mojoAnnotatedClasses )
+ {
+ List parameterAnnotationContents = new ArrayList();
+
+ parameterAnnotationContents =
+ getParametersParent( mojoAnnotatedClass, parameterAnnotationContents, mojoAnnotatedClasses );
+
+ // move to parent first to build the Map
+ Collections.reverse( parameterAnnotationContents );
+
+ Map map =
+ new HashMap( parameterAnnotationContents.size() );
+
+ for ( ParameterAnnotationContent parameterAnnotationContent : parameterAnnotationContents )
+ {
+ map.put( parameterAnnotationContent.getFieldName(), parameterAnnotationContent );
+ }
+ return map;
+ }
+
+ protected List getParametersParent( MojoAnnotatedClass mojoAnnotatedClass,
+ List parameterAnnotationContents,
+ Map mojoAnnotatedClasses )
+ {
+ parameterAnnotationContents.addAll( mojoAnnotatedClass.getParameters().values() );
+ String parentClassName = mojoAnnotatedClass.getParentClassName();
+ if ( parentClassName != null )
+ {
+ MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName );
+ if ( parent != null )
+ {
+ return getParametersParent( parent, parameterAnnotationContents, mojoAnnotatedClasses );
+ }
+ }
+ return parameterAnnotationContents;
+ }
+
+
+ protected Map getComponentsParentHierarchy(
+ MojoAnnotatedClass mojoAnnotatedClass, Map components,
+ Map mojoAnnotatedClasses )
+ {
+ List componentAnnotationContents = new ArrayList();
+
+ componentAnnotationContents =
+ getComponentParent( mojoAnnotatedClass, componentAnnotationContents, mojoAnnotatedClasses );
+
+ // move to parent first to build the Map
+ Collections.reverse( componentAnnotationContents );
+
+ Map map =
+ new HashMap( componentAnnotationContents.size() );
+
+ for ( ComponentAnnotationContent componentAnnotationContent : componentAnnotationContents )
+ {
+ map.put( componentAnnotationContent.getFieldName(), componentAnnotationContent );
+ }
+ return map;
+ }
+
+ protected List getComponentParent( MojoAnnotatedClass mojoAnnotatedClass,
+ List componentAnnotationContents,
+ Map mojoAnnotatedClasses )
+ {
+ componentAnnotationContents.addAll( mojoAnnotatedClass.getComponents().values() );
+ String parentClassName = mojoAnnotatedClass.getParentClassName();
+ if ( parentClassName != null )
+ {
+ MojoAnnotatedClass parent = mojoAnnotatedClasses.get( parentClassName );
+ if ( parent != null )
+ {
+ return getComponentParent( parent, componentAnnotationContents, mojoAnnotatedClasses );
+ }
+ }
+ return componentAnnotationContents;
+ }
+
+ protected MavenProject getFromProjectReferences( Artifact artifact, MavenProject project )
+ {
+ if ( project.getProjectReferences() == null || project.getProjectReferences().isEmpty() )
+ {
+ return null;
+ }
+ Collection mavenProjects = project.getProjectReferences().values();
+ for ( MavenProject mavenProject : mavenProjects )
+ {
+ if ( StringUtils.equals( mavenProject.getId(), artifact.getId() ) )
+ {
+ return mavenProject;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedContent.java
new file mode 100644
index 0000000..3869117
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedContent.java
@@ -0,0 +1,66 @@
+package org.apache.maven.tools.plugin.annotations.datamodel;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class AnnotatedContent
+{
+
+ private String description;
+
+ private String since;
+
+ private String deprecated;
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public void setDescription( String description )
+ {
+ this.description = description;
+ }
+
+ public String getSince()
+ {
+ return since;
+ }
+
+ public void setSince( String since )
+ {
+ this.since = since;
+ }
+
+ public String getDeprecated()
+ {
+ return deprecated;
+ }
+
+ public void setDeprecated( String deprecated )
+ {
+ this.deprecated = deprecated;
+ }
+
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedField.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedField.java
new file mode 100644
index 0000000..ec69326
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/AnnotatedField.java
@@ -0,0 +1,60 @@
+package org.apache.maven.tools.plugin.annotations.datamodel;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class AnnotatedField
+ extends AnnotatedContent
+ implements Comparable
+{
+ private String fieldName;
+
+ public AnnotatedField( String fieldName )
+ {
+ this.fieldName = fieldName;
+ }
+
+ public String getFieldName()
+ {
+ return fieldName;
+ }
+
+ public void setFieldName( String name )
+ {
+ this.fieldName = name;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "AnnotatedField" );
+ sb.append( "{fieldName='" ).append( fieldName ).append( '\'' );
+ sb.append( '}' );
+ return sb.toString();
+ }
+
+ public int compareTo( AnnotatedField annotatedField )
+ {
+ return getFieldName().compareTo( annotatedField.getFieldName() );
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ComponentAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ComponentAnnotationContent.java
new file mode 100644
index 0000000..5fee961
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ComponentAnnotationContent.java
@@ -0,0 +1,86 @@
+package org.apache.maven.tools.plugin.annotations.datamodel;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+
+import org.apache.maven.plugins.annotations.Component;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class ComponentAnnotationContent
+ extends AnnotatedField
+ implements Component
+{
+ private String role;
+
+ private String roleHint;
+
+ public ComponentAnnotationContent( String fieldName )
+ {
+ super( fieldName );
+ }
+
+ public ComponentAnnotationContent( String fieldName, String role, String roleHint )
+ {
+ this( fieldName );
+ this.role = role;
+ this.roleHint = roleHint;
+ }
+
+ public String role()
+ {
+ return role == null ? "" : role;
+ }
+
+ public void role( String role )
+ {
+ this.role = role;
+ }
+
+ public String roleHint()
+ {
+ return roleHint == null ? "" : roleHint;
+ }
+
+ public void roleHint( String roleHint )
+ {
+ this.roleHint = roleHint;
+ }
+
+ public Class extends Annotation> annotationType()
+ {
+ return null;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( super.toString() );
+ sb.append( "ComponentAnnotationContent" );
+ sb.append( "{role='" ).append( role ).append( '\'' );
+ sb.append( ", roleHint='" ).append( roleHint ).append( '\'' );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ExecuteAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ExecuteAnnotationContent.java
new file mode 100644
index 0000000..c680f3b
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ExecuteAnnotationContent.java
@@ -0,0 +1,87 @@
+package org.apache.maven.tools.plugin.annotations.datamodel;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class ExecuteAnnotationContent
+ implements Execute
+{
+ private String goal;
+
+ private String lifecycle;
+
+ private LifecyclePhase phase;
+
+ public LifecyclePhase phase()
+ {
+ return this.phase;
+ }
+
+ public String goal()
+ {
+ return this.goal;
+ }
+
+ public String lifecycle()
+ {
+ return this.lifecycle;
+ }
+
+
+ public void phase( String phase )
+ {
+ this.phase = LifecyclePhase.valueOf( phase );
+ }
+
+ public void goal( String goal )
+ {
+ this.goal = goal;
+ }
+
+ public void lifecycle( String lifecycle )
+ {
+ this.lifecycle = lifecycle;
+ }
+
+
+ public Class extends Annotation> annotationType()
+ {
+ return null;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "ExecuteAnnotationContent" );
+ sb.append( "{goal='" ).append( goal ).append( '\'' );
+ sb.append( ", lifecycle='" ).append( lifecycle ).append( '\'' );
+ sb.append( ", phase=" ).append( phase );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/MojoAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/MojoAnnotationContent.java
new file mode 100644
index 0000000..ea70331
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/MojoAnnotationContent.java
@@ -0,0 +1,229 @@
+package org.apache.maven.tools.plugin.annotations.datamodel;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class MojoAnnotationContent
+ extends AnnotatedContent
+ implements Mojo
+{
+ private String name;
+
+ private LifecyclePhase defaultPhase = LifecyclePhase.NONE;
+
+ private String requiresDependencyResolution = "runtime";
+
+ private String requiresDependencyCollection;
+
+ private String instantiationStrategy = "per-lookup";
+
+ private String executionStrategy = "once-per-session";
+
+ private boolean requiresProject = true;
+
+ private boolean requiresReports = false;
+
+ private boolean aggregator = false;
+
+ private boolean requiresDirectInvocation = false;
+
+ private boolean requiresOnline = false;
+
+ private boolean inheritByDefault = true;
+
+ private String configurator;
+
+ private boolean threadSafe = false;
+
+ public Class extends Annotation> annotationType()
+ {
+ return null;
+ }
+
+ public LifecyclePhase defaultPhase()
+ {
+ return defaultPhase;
+ }
+
+ public void defaultPhase( String phase )
+ {
+ this.defaultPhase = LifecyclePhase.valueOf( phase );
+ }
+
+ public String requiresDependencyResolution()
+ {
+ return requiresDependencyResolution;
+ }
+
+ public void requiresDependencyResolution( String requiresDependencyResolution )
+ {
+ this.requiresDependencyResolution = requiresDependencyResolution;
+ }
+
+ public String requiresDependencyCollection()
+ {
+ return requiresDependencyCollection == null ? "" : requiresDependencyCollection;
+ }
+
+ public void requiresDependencyCollection( String requiresDependencyCollection )
+ {
+ this.requiresDependencyCollection = requiresDependencyCollection;
+ }
+
+ public String instantiationStrategy()
+ {
+ return instantiationStrategy;
+ }
+
+ public void instantiationStrategy( String instantiationStrategy )
+ {
+ this.instantiationStrategy = instantiationStrategy;
+ }
+
+ public String executionStrategy()
+ {
+ return executionStrategy;
+ }
+
+ public void executionStrategy( String executionStrategy )
+ {
+ this.executionStrategy = executionStrategy;
+ }
+
+ public boolean requiresProject()
+ {
+ return requiresProject;
+ }
+
+ public void requiresProject( boolean requiresProject )
+ {
+ this.requiresProject = requiresProject;
+ }
+
+ public boolean requiresReports()
+ {
+ return requiresReports;
+ }
+
+ public void requiresReports( boolean requiresReports )
+ {
+ this.requiresReports = requiresReports;
+ }
+
+ public boolean aggregator()
+ {
+ return aggregator;
+ }
+
+ public void aggregator( boolean aggregator )
+ {
+ this.aggregator = aggregator;
+ }
+
+ public boolean requiresDirectInvocation()
+ {
+ return requiresDirectInvocation;
+ }
+
+ public void requiresDirectInvocation( boolean requiresDirectInvocation )
+ {
+ this.requiresDirectInvocation = requiresDirectInvocation;
+ }
+
+ public boolean requiresOnline()
+ {
+ return requiresOnline;
+ }
+
+ public void requiresOnline( boolean requiresOnline )
+ {
+ this.requiresOnline = requiresOnline;
+ }
+
+ public boolean inheritByDefault()
+ {
+ return inheritByDefault;
+ }
+
+ public void inheritByDefault( boolean inheritByDefault )
+ {
+ this.inheritByDefault = inheritByDefault;
+ }
+
+ public String configurator()
+ {
+ return configurator;
+ }
+
+ public void configurator( String configurator )
+ {
+ this.configurator = configurator;
+ }
+
+ public boolean threadSafe()
+ {
+ return threadSafe;
+ }
+
+ public void threadSafe( boolean threadSafe )
+ {
+ this.threadSafe = threadSafe;
+ }
+
+ public String name()
+ {
+ return this.name;
+ }
+
+ public void name( String name )
+ {
+ this.name = name;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "MojoAnnotationContent" );
+ sb.append( "{name='" ).append( name ).append( '\'' );
+ sb.append( ", defaultPhase=" ).append( defaultPhase );
+ sb.append( ", requiresDependencyResolution='" ).append( requiresDependencyResolution ).append( '\'' );
+ sb.append( ", requiresDependencyCollection='" ).append( requiresDependencyCollection ).append( '\'' );
+ sb.append( ", instantiationStrategy='" ).append( instantiationStrategy ).append( '\'' );
+ sb.append( ", executionStrategy='" ).append( executionStrategy ).append( '\'' );
+ sb.append( ", requiresProject=" ).append( requiresProject );
+ sb.append( ", requiresReports=" ).append( requiresReports );
+ sb.append( ", aggregator=" ).append( aggregator );
+ sb.append( ", requiresDirectInvocation=" ).append( requiresDirectInvocation );
+ sb.append( ", requiresOnline=" ).append( requiresOnline );
+ sb.append( ", inheritByDefault=" ).append( inheritByDefault );
+ sb.append( ", configurator='" ).append( configurator ).append( '\'' );
+ sb.append( ", threadSafe=" ).append( threadSafe );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ParameterAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ParameterAnnotationContent.java
new file mode 100644
index 0000000..82a82bd
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/datamodel/ParameterAnnotationContent.java
@@ -0,0 +1,198 @@
+package org.apache.maven.tools.plugin.annotations.datamodel;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.plugins.annotations.Parameter;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class ParameterAnnotationContent
+ extends AnnotatedField
+ implements Parameter
+{
+
+ private String alias;
+
+ private String expression;
+
+ private String defaultValue;
+
+ private boolean required = false;
+
+ private boolean readonly = false;
+
+ private String className;
+
+ public ParameterAnnotationContent( String fieldName, String className )
+ {
+ super( fieldName );
+ this.className = className;
+ }
+
+ public ParameterAnnotationContent( String fieldName, String alias, String expression, String defaultValue,
+ boolean required, boolean readonly, String className )
+ {
+ this( fieldName, className );
+ this.alias = alias;
+ this.expression = expression;
+ this.defaultValue = defaultValue;
+ this.required = required;
+ this.readonly = readonly;
+ }
+
+ public String alias()
+ {
+ return alias;
+ }
+
+ public void alias( String alias )
+ {
+ this.alias = alias;
+ }
+
+ public String expression()
+ {
+ return expression;
+ }
+
+ public void expression( String expression )
+ {
+ this.expression = expression;
+ }
+
+ public String defaultValue()
+ {
+ return defaultValue;
+ }
+
+ public void defaultValue( String defaultValue )
+ {
+ this.defaultValue = defaultValue;
+ }
+
+ public boolean required()
+ {
+ return required;
+ }
+
+ public void required( boolean required )
+ {
+ this.required = required;
+ }
+
+ public boolean readonly()
+ {
+ return readonly;
+ }
+
+ public void readonly( boolean readonly )
+ {
+ this.readonly = readonly;
+ }
+
+ public Class extends Annotation> annotationType()
+ {
+ return null;
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+ public void setClassName( String className )
+ {
+ this.className = className;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( super.toString() );
+ sb.append( "ParameterAnnotationContent" );
+ sb.append( "{alias='" ).append( alias ).append( '\'' );
+ sb.append( ", expression='" ).append( expression ).append( '\'' );
+ sb.append( ", defaultValue='" ).append( defaultValue ).append( '\'' );
+ sb.append( ", required=" ).append( required );
+ sb.append( ", readonly=" ).append( readonly );
+ sb.append( '}' );
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+ if ( !( o instanceof ParameterAnnotationContent ) )
+ {
+ return false;
+ }
+
+ ParameterAnnotationContent that = (ParameterAnnotationContent) o;
+
+ if ( readonly != that.readonly )
+ {
+ return false;
+ }
+ if ( required != that.required )
+ {
+ return false;
+ }
+
+ if ( getFieldName() != null ? !getFieldName().equals( that.getFieldName() ) : that.getFieldName() != null )
+ {
+ return false;
+ }
+
+ if ( alias != null ? !alias.equals( that.alias ) : that.alias != null )
+ {
+ return false;
+ }
+ if ( defaultValue != null ? !defaultValue.equals( that.defaultValue ) : that.defaultValue != null )
+ {
+ return false;
+ }
+ if ( expression != null ? !expression.equals( that.expression ) : that.expression != null )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = alias != null ? alias.hashCode() : 0;
+ result = 31 * result + ( getFieldName() != null ? getFieldName().hashCode() : 0 );
+ result = 31 * result + ( expression != null ? expression.hashCode() : 0 );
+ result = 31 * result + ( defaultValue != null ? defaultValue.hashCode() : 0 );
+ result = 31 * result + ( required ? 1 : 0 );
+ result = 31 * result + ( readonly ? 1 : 0 );
+ return result;
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/DefaultMojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/DefaultMojoAnnotationsScanner.java
new file mode 100644
index 0000000..44e1788
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/DefaultMojoAnnotationsScanner.java
@@ -0,0 +1,321 @@
+package org.apache.maven.tools.plugin.annotations.scanner;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoAnnotationVisitor;
+import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoClassVisitor;
+import org.apache.maven.tools.plugin.annotations.scanner.visitors.MojoFieldVisitor;
+import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.codehaus.plexus.logging.AbstractLogEnabled;
+import org.codehaus.plexus.util.DirectoryScanner;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.reflection.Reflector;
+import org.objectweb.asm.ClassReader;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class DefaultMojoAnnotationsScanner
+ extends AbstractLogEnabled
+ implements MojoAnnotationsScanner
+{
+ private Reflector reflector = new Reflector();
+
+ public Map scan( MojoAnnotationsScannerRequest request )
+ throws ExtractionException
+ {
+ Map mojoAnnotatedClasses = new HashMap();
+ try
+ {
+
+ for ( Artifact dependency : request.getDependencies() )
+ {
+ File dependencyFile = dependency.getFile();
+ if ( dependencyFile != null && dependencyFile.exists() )
+ {
+ if ( dependencyFile.isDirectory() )
+ {
+ mojoAnnotatedClasses.putAll(
+ scanDirectory( dependencyFile, request.getIncludePatterns(), dependency, true ) );
+ }
+ else
+ {
+ mojoAnnotatedClasses.putAll(
+ scanFile( dependencyFile, request.getIncludePatterns(), dependency, true ) );
+ }
+ }
+ }
+
+ for ( File classDirectory : request.getClassesDirectories() )
+ {
+ if ( classDirectory.exists() && classDirectory.isDirectory() )
+ {
+ mojoAnnotatedClasses.putAll(
+ scanDirectory( classDirectory, request.getIncludePatterns(), request.getProject().getArtifact(),
+ false ) );
+ }
+ }
+
+ return mojoAnnotatedClasses;
+ }
+ catch ( IOException e )
+ {
+ throw new ExtractionException( e.getMessage(), e );
+ }
+ }
+
+ /**
+ * @param archiveFile
+ * @param includePatterns
+ * @param artifact
+ * @param excludeMojo for dependencies we exclude Mojo annotations found
+ * @return
+ * @throws IOException
+ * @throws ExtractionException
+ */
+ protected Map scanFile( File archiveFile, List includePatterns,
+ Artifact artifact, boolean excludeMojo )
+ throws IOException, ExtractionException
+ {
+ if ( !archiveFile.exists() )
+ {
+ return Collections.emptyMap();
+ }
+ Map mojoAnnotatedClasses = new HashMap();
+ ZipInputStream archiveStream = new ZipInputStream( new FileInputStream( archiveFile ) );
+
+ try
+ {
+ for ( ZipEntry zipEntry = archiveStream.getNextEntry(); zipEntry != null;
+ zipEntry = archiveStream.getNextEntry() )
+ {
+ if ( zipEntry.getName().endsWith( ".class" ) )
+ {
+ MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() );
+
+ ClassReader rdr = new ClassReader( archiveStream );
+ rdr.accept( mojoClassVisitor,
+ ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG );
+ analyzeVisitors( mojoClassVisitor );
+ if ( excludeMojo )
+ {
+ mojoClassVisitor.getMojoAnnotatedClass().setMojo( null );
+ }
+ if ( isMojoAnnnotatedClassCandidate( mojoClassVisitor.getMojoAnnotatedClass() ) != null )
+ {
+ getLogger().debug(
+ "found MojoAnnotatedClass:" + mojoClassVisitor.getMojoAnnotatedClass().getClassName() + ":"
+ + mojoClassVisitor.getMojoAnnotatedClass() );
+ mojoClassVisitor.getMojoAnnotatedClass().setArtifact( artifact );
+ mojoAnnotatedClasses.put( mojoClassVisitor.getMojoAnnotatedClass().getClassName(),
+ mojoClassVisitor.getMojoAnnotatedClass() );
+ }
+ }
+ }
+ }
+ finally
+ {
+ IOUtil.close( archiveStream );
+ }
+ return mojoAnnotatedClasses;
+ }
+
+ /**
+ * @param classDirectory
+ * @param includePatterns
+ * @param artifact
+ * @param excludeMojo for dependencies we exclude Mojo annotations found
+ * @return
+ * @throws IOException
+ * @throws ExtractionException
+ */
+ protected Map scanDirectory( File classDirectory, List includePatterns,
+ Artifact artifact, boolean excludeMojo )
+ throws IOException, ExtractionException
+ {
+ if ( !classDirectory.exists() )
+ {
+ return Collections.emptyMap();
+ }
+ Map mojoAnnotatedClasses = new HashMap();
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setBasedir( classDirectory );
+ scanner.addDefaultExcludes();
+ if ( includePatterns != null )
+ {
+ scanner.setIncludes( includePatterns.toArray( new String[includePatterns.size()] ) );
+ }
+ scanner.scan();
+ String[] classFiles = scanner.getIncludedFiles();
+
+ for ( String classFile : classFiles )
+ {
+ InputStream is = new BufferedInputStream( new FileInputStream( new File( classDirectory, classFile ) ) );
+ try
+ {
+
+ if ( classFile.endsWith( ".class" ) )
+ {
+ MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() );
+ ClassReader rdr = new ClassReader( is );
+ rdr.accept( mojoClassVisitor,
+ ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG );
+ analyzeVisitors( mojoClassVisitor );
+ if ( excludeMojo )
+ {
+ mojoClassVisitor.getMojoAnnotatedClass().setMojo( null );
+ }
+ if ( isMojoAnnnotatedClassCandidate( mojoClassVisitor.getMojoAnnotatedClass() ) != null )
+ {
+ getLogger().debug(
+ "found MojoAnnotatedClass:" + mojoClassVisitor.getMojoAnnotatedClass().getClassName() + ":"
+ + mojoClassVisitor.getMojoAnnotatedClass() );
+ mojoClassVisitor.getMojoAnnotatedClass().setArtifact( artifact );
+ mojoAnnotatedClasses.put( mojoClassVisitor.getMojoAnnotatedClass().getClassName(),
+ mojoClassVisitor.getMojoAnnotatedClass() );
+ }
+
+ }
+ }
+ finally
+ {
+ IOUtil.close( is );
+ }
+
+ }
+ return mojoAnnotatedClasses;
+ }
+
+ private MojoAnnotatedClass isMojoAnnnotatedClassCandidate( MojoAnnotatedClass mojoAnnotatedClass )
+ {
+ if ( mojoAnnotatedClass == null )
+ {
+ return null;
+ }
+ if ( !mojoAnnotatedClass.getComponents().isEmpty() || !mojoAnnotatedClass.getParameters().isEmpty()
+ || mojoAnnotatedClass.getExecute() != null || mojoAnnotatedClass.getMojo() != null )
+ {
+ return mojoAnnotatedClass;
+ }
+ return null;
+ }
+
+ protected void analyzeVisitors( MojoClassVisitor mojoClassVisitor )
+ throws ExtractionException
+ {
+
+ try
+ {
+ MojoAnnotationVisitor mojoAnnotationVisitor =
+ mojoClassVisitor.getAnnotationVisitorMap().get( Mojo.class.getName() );
+ if ( mojoAnnotationVisitor != null )
+ {
+ MojoAnnotationContent mojoAnnotationContent = new MojoAnnotationContent();
+ for ( Map.Entry entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() )
+ {
+ reflector.invoke( mojoAnnotationContent, entry.getKey(), new Object[]{ entry.getValue() } );
+ }
+ mojoClassVisitor.getMojoAnnotatedClass().setMojo( mojoAnnotationContent );
+ }
+
+ mojoAnnotationVisitor = mojoClassVisitor.getAnnotationVisitorMap().get( Execute.class.getName() );
+ if ( mojoAnnotationVisitor != null )
+ {
+ ExecuteAnnotationContent executeAnnotationContent = new ExecuteAnnotationContent();
+
+ for ( Map.Entry entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() )
+ {
+ reflector.invoke( executeAnnotationContent, entry.getKey(), new Object[]{ entry.getValue() } );
+ }
+ mojoClassVisitor.getMojoAnnotatedClass().setExecute( executeAnnotationContent );
+ }
+
+ List mojoFieldVisitors =
+ mojoClassVisitor.findFieldWithAnnotationClass( Parameter.class.getName() );
+
+ for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
+ {
+ ParameterAnnotationContent parameterAnnotationContent =
+ new ParameterAnnotationContent( mojoFieldVisitor.getFieldName(), mojoFieldVisitor.getClassName() );
+ if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null )
+ {
+ for ( Map.Entry entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() )
+ {
+ reflector.invoke( parameterAnnotationContent, entry.getKey(),
+ new Object[]{ entry.getValue() } );
+ }
+
+ }
+ mojoClassVisitor.getMojoAnnotatedClass().getParameters().put( parameterAnnotationContent.getFieldName(),
+ parameterAnnotationContent );
+ }
+
+ mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotationClass( Component.class.getName() );
+
+ for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
+ {
+ ComponentAnnotationContent componentAnnotationContent =
+ new ComponentAnnotationContent( mojoFieldVisitor.getFieldName() );
+
+ if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null )
+ {
+ for ( Map.Entry entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() )
+ {
+ reflector.invoke( componentAnnotationContent, entry.getKey(),
+ new Object[]{ entry.getValue() } );
+ }
+ if ( StringUtils.isEmpty( componentAnnotationContent.role() ) )
+ {
+ componentAnnotationContent.role( mojoFieldVisitor.getClassName() );
+ }
+ }
+ mojoClassVisitor.getMojoAnnotatedClass().getComponents().put( componentAnnotationContent.getFieldName(),
+ componentAnnotationContent );
+ }
+
+ }
+ catch ( Exception e )
+ {
+ throw new ExtractionException( e.getMessage(), e );
+ }
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotatedClass.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotatedClass.java
new file mode 100644
index 0000000..847634e
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotatedClass.java
@@ -0,0 +1,162 @@
+package org.apache.maven.tools.plugin.annotations.scanner;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.ExecuteAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.MojoAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class MojoAnnotatedClass
+{
+ private String className;
+
+ private String parentClassName;
+
+ private MojoAnnotationContent mojo;
+
+ private ExecuteAnnotationContent execute;
+
+ /**
+ * key is field name
+ */
+ private Map parameters;
+
+ /**
+ * key is field name
+ */
+ private Map components;
+
+ /**
+ * artifact which contains this annotation
+ */
+ private Artifact artifact;
+
+ public MojoAnnotatedClass()
+ {
+ // no op
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+ public MojoAnnotatedClass setClassName( String className )
+ {
+ this.className = className;
+ return this;
+ }
+
+ public MojoAnnotationContent getMojo()
+ {
+ return mojo;
+ }
+
+ public MojoAnnotatedClass setMojo( MojoAnnotationContent mojo )
+ {
+ this.mojo = mojo;
+ return this;
+ }
+
+ public ExecuteAnnotationContent getExecute()
+ {
+ return execute;
+ }
+
+ public MojoAnnotatedClass setExecute( ExecuteAnnotationContent execute )
+ {
+ this.execute = execute;
+ return this;
+ }
+
+ public Map getParameters()
+ {
+ if ( this.parameters == null )
+ {
+ this.parameters = new HashMap();
+ }
+ return parameters;
+ }
+
+ public MojoAnnotatedClass setParameters( Map parameters )
+ {
+ this.parameters = parameters;
+ return this;
+ }
+
+ public Map getComponents()
+ {
+ if ( this.components == null )
+ {
+ this.components = new HashMap();
+ }
+ return components;
+ }
+
+ public MojoAnnotatedClass setComponents( Map components )
+ {
+ this.components = components;
+ return this;
+ }
+
+ public String getParentClassName()
+ {
+ return parentClassName;
+ }
+
+ public MojoAnnotatedClass setParentClassName( String parentClassName )
+ {
+ this.parentClassName = parentClassName;
+ return this;
+ }
+
+ public Artifact getArtifact()
+ {
+ return artifact;
+ }
+
+ public void setArtifact( Artifact artifact )
+ {
+ this.artifact = artifact;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "MojoAnnotatedClass" );
+ sb.append( "{className='" ).append( className ).append( '\'' );
+ sb.append( ", parentClassName='" ).append( parentClassName ).append( '\'' );
+ sb.append( ", mojo=" ).append( mojo );
+ sb.append( ", execute=" ).append( execute );
+ sb.append( ", parameters=" ).append( parameters );
+ sb.append( ", components=" ).append( components );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScanner.java
new file mode 100644
index 0000000..2bf9d9a
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScanner.java
@@ -0,0 +1,47 @@
+package org.apache.maven.tools.plugin.annotations.scanner;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.tools.plugin.extractor.ExtractionException;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public interface MojoAnnotationsScanner
+{
+ String ROLE = MojoAnnotationsScanner.class.getName();
+
+ static final List acceptedClassLevelAnnotationClasses =
+ Arrays.asList( Mojo.class.getName(), Execute.class.getName() );
+
+ static final List acceptedFieldLevelAnnotationClasses =
+ Arrays.asList( Parameter.class.getName(), Component.class.getName() );
+
+ Map scan( MojoAnnotationsScannerRequest request )
+ throws ExtractionException;
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScannerRequest.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScannerRequest.java
new file mode 100644
index 0000000..af144d1
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/MojoAnnotationsScannerRequest.java
@@ -0,0 +1,102 @@
+package org.apache.maven.tools.plugin.annotations.scanner;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.artifact.ProjectArtifactMetadata;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class MojoAnnotationsScannerRequest
+{
+ private List classesDirectories = new ArrayList();
+
+ private Set dependencies = new HashSet();
+
+ private List includePatterns = Arrays.asList( "**/*.class" );
+
+ private List sourceDirectories = new ArrayList();
+
+ private MavenProject project;
+
+ public MojoAnnotationsScannerRequest()
+ {
+ // no o
+ }
+
+ public List getClassesDirectories()
+ {
+ return classesDirectories;
+ }
+
+ public void setClassesDirectories( List classesDirectories )
+ {
+ this.classesDirectories = classesDirectories;
+ }
+
+ public Set getDependencies()
+ {
+ return dependencies;
+ }
+
+ public void setDependencies( Set dependencies )
+ {
+ this.dependencies = dependencies;
+ }
+
+ public List getIncludePatterns()
+ {
+ return includePatterns;
+ }
+
+ public void setIncludePatterns( List includePatterns )
+ {
+ this.includePatterns = includePatterns;
+ }
+
+ public List getSourceDirectories()
+ {
+ return sourceDirectories;
+ }
+
+ public void setSourceDirectories( List sourceDirectories )
+ {
+ this.sourceDirectories = sourceDirectories;
+ }
+
+ public MavenProject getProject()
+ {
+ return project;
+ }
+
+ public void setProject( MavenProject project )
+ {
+ this.project = project;
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoAnnotationVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoAnnotationVisitor.java
new file mode 100644
index 0000000..1367107
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoAnnotationVisitor.java
@@ -0,0 +1,84 @@
+package org.apache.maven.tools.plugin.annotations.scanner.visitors;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.codehaus.plexus.logging.Logger;
+import org.objectweb.asm.AnnotationVisitor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class MojoAnnotationVisitor
+ implements AnnotationVisitor
+{
+ private Logger logger;
+
+ private String annotationClassName;
+
+ private Map annotationValues = new HashMap();
+
+ MojoAnnotationVisitor( Logger logger, String annotationClassName )
+ {
+ this.logger = logger;
+ this.annotationClassName = annotationClassName;
+ }
+
+ public Map getAnnotationValues()
+ {
+ return annotationValues;
+ }
+
+ public void visit( String name, Object value )
+ {
+ annotationValues.put( name, value );
+ logger.debug( "MojoAnnotationVisitor#visit:" + name + ":" + value );
+ }
+
+ public void visitEnum( String name, String desc, String value )
+ {
+ annotationValues.put( name, value );
+ logger.debug( "MojoAnnotationVisitor#visitEnum:" + name + ":" + desc + ":" + value );
+ }
+
+ public AnnotationVisitor visitAnnotation( String name, String desc )
+ {
+ logger.debug( "MojoAnnotationVisitor#visitAnnotation:" + name + ":" + desc );
+ return new MojoAnnotationVisitor( logger, this.annotationClassName );
+ }
+
+ public AnnotationVisitor visitArray( String s )
+ {
+ logger.debug( "MojoAnnotationVisitor#visitArray" );
+ return new MojoAnnotationVisitor( logger, this.annotationClassName );
+ }
+
+ public void visitEnd()
+ {
+ logger.debug( "MojoAnnotationVisitor#visitEnd" );
+ }
+
+ public String getAnnotationClassName()
+ {
+ return annotationClassName;
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoClassVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoClassVisitor.java
new file mode 100644
index 0000000..5cec4b0
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoClassVisitor.java
@@ -0,0 +1,160 @@
+package org.apache.maven.tools.plugin.annotations.scanner.visitors;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass;
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner;
+import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.util.StringUtils;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Type;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class MojoClassVisitor
+ implements ClassVisitor
+{
+ private Logger logger;
+
+ private MojoAnnotatedClass mojoAnnotatedClass;
+
+ private Map annotationVisitorMap = new HashMap();
+
+ private List fieldVisitors = new ArrayList();
+
+ public MojoClassVisitor( Logger logger )
+ {
+ this.logger = logger;
+ }
+
+ public MojoAnnotatedClass getMojoAnnotatedClass()
+ {
+ return mojoAnnotatedClass;
+ }
+
+ public void setMojoAnnotatedClass( MojoAnnotatedClass mojoAnnotatedClass )
+ {
+ this.mojoAnnotatedClass = mojoAnnotatedClass;
+ }
+
+ public Map getAnnotationVisitorMap()
+ {
+ return annotationVisitorMap;
+ }
+
+ public void setAnnotationVisitorMap( Map annotationVisitorMap )
+ {
+ this.annotationVisitorMap = annotationVisitorMap;
+ }
+
+ public List getFieldVisitors()
+ {
+ return fieldVisitors;
+ }
+
+ public void setFieldVisitors( List fieldVisitors )
+ {
+ this.fieldVisitors = fieldVisitors;
+ }
+
+ public List findFieldWithAnnotationClass( String annotationClassName )
+ {
+ List mojoFieldVisitors = new ArrayList();
+
+ for ( MojoFieldVisitor mojoFieldVisitor : this.fieldVisitors )
+ {
+ MojoAnnotationVisitor mojoAnnotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor();
+ if ( mojoAnnotationVisitor != null && StringUtils.equals( annotationClassName,
+ mojoAnnotationVisitor.getAnnotationClassName() ) )
+ {
+ mojoFieldVisitors.add( mojoFieldVisitor );
+ }
+ }
+
+ return mojoFieldVisitors;
+ }
+
+ public void visit( int version, int access, String name, String signature, String superName, String[] interfaces )
+ {
+ mojoAnnotatedClass = new MojoAnnotatedClass();
+ mojoAnnotatedClass.setClassName( Type.getObjectType( name ).getClassName() ).setParentClassName(
+ Type.getObjectType( superName ).getClassName() );
+ logger.debug( "MojoClassVisitor#visit" );
+ }
+
+ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
+ {
+ logger.debug( "MojoClassVisitor#visitAnnotation" );
+ String annotationClassName = Type.getType( desc ).getClassName();
+ if ( !MojoAnnotationsScanner.acceptedClassLevelAnnotationClasses.contains( annotationClassName ) )
+ {
+ return null;
+ }
+ MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName );
+ annotationVisitorMap.put( annotationClassName, mojoAnnotationVisitor );
+ return mojoAnnotationVisitor;
+ }
+
+ public FieldVisitor visitField( int access, String name, String desc, String signature, Object value )
+ {
+ logger.debug( "MojoClassVisitor#visitField" );
+ MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( logger, name, Type.getType( desc ).getClassName() );
+ fieldVisitors.add( mojoFieldVisitor );
+ return mojoFieldVisitor;
+ }
+
+ public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions )
+ {
+ // we don't need methods informations
+ return null;
+ }
+
+ public void visitAttribute( Attribute attr )
+ {
+ }
+
+ public void visitSource( String source, String debug )
+ {
+ }
+
+ public void visitOuterClass( String owner, String name, String desc )
+ {
+ }
+
+ public void visitInnerClass( String name, String outerName, String innerName, int access )
+ {
+ }
+
+ public void visitEnd()
+ {
+ logger.debug( "MojoClassVisitor#visitEnd" );
+ }
+
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoFieldVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoFieldVisitor.java
new file mode 100644
index 0000000..2b82907
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/annotations/scanner/visitors/MojoFieldVisitor.java
@@ -0,0 +1,91 @@
+package org.apache.maven.tools.plugin.annotations.scanner.visitors;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner;
+import org.codehaus.plexus.logging.Logger;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Type;
+
+/**
+ * @author Olivier Lamy
+ * @since 3.0
+ */
+public class MojoFieldVisitor
+ implements FieldVisitor
+{
+ private Logger logger;
+
+ private String fieldName;
+
+ private MojoAnnotationVisitor mojoAnnotationVisitor;
+
+ private String className;
+
+ MojoFieldVisitor( Logger logger, String fieldName, String className )
+ {
+ this.logger = logger;
+ this.fieldName = fieldName;
+ this.className = className;
+ }
+
+ public MojoAnnotationVisitor getMojoAnnotationVisitor()
+ {
+ return mojoAnnotationVisitor;
+ }
+
+ public String getFieldName()
+ {
+ return fieldName;
+ }
+
+ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
+ {
+ logger.debug( "MojoFieldVisitor#visitAnnotation:" + desc );
+ String annotationClassName = Type.getType( desc ).getClassName();
+ if ( !MojoAnnotationsScanner.acceptedFieldLevelAnnotationClasses.contains( annotationClassName ) )
+ {
+ return null;
+ }
+ mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName );
+ return mojoAnnotationVisitor;
+ }
+
+ public void visitAttribute( Attribute attribute )
+ {
+ logger.debug( "MojoFieldVisitor#visitAttribute" );
+ }
+
+ public void visitEnd()
+ {
+ logger.debug( "MojoFieldVisitor#visitEnd" );
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+ public void setClassName( String className )
+ {
+ this.className = className;
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/resources/META-INF/plexus/components.xml b/maven-plugin-tools-annotations/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000..9d6aa87
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+ org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor
+ java-annotations
+ org.apache.maven.tools.plugin.annotations.JavaAnnotationsMojoDescriptorExtractor
+
+
+ org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner
+
+
+ org.apache.maven.artifact.resolver.ArtifactResolver
+
+
+ org.apache.maven.artifact.factory.ArtifactFactory
+
+
+ org.codehaus.plexus.archiver.manager.ArchiverManager
+
+
+
+
+
+ org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner
+ default
+ org.apache.maven.tools.plugin.annotations.scanner.DefaultMojoAnnotationsScanner
+
+
+
+
\ No newline at end of file
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/FooMojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/FooMojo.java
new file mode 100644
index 0000000..1f9da50
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/FooMojo.java
@@ -0,0 +1,71 @@
+package org.apache.maven.tools.plugin.annotations;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.codehaus.plexus.compiler.manager.CompilerManager;
+
+/**
+ * @author Olivier Lamy
+ */
+@Mojo( name = "foo", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true )
+@Execute( goal = "compiler", lifecycle = "my-lifecycle", phase = LifecyclePhase.PACKAGE )
+public class FooMojo
+ extends AbstractMojo
+{
+ /**
+ * the cool bar to go
+ * @since 1.0
+ */
+ @Parameter( expression = "${thebar}", required = true, defaultValue = "coolbar" )
+ protected String bar;
+
+ /**
+ * beer for non french folks
+ * @deprecated wine is better
+ */
+ @Parameter( expression = "${thebeer}", defaultValue = "coolbeer" )
+ protected String beer;
+
+ /**
+ * Plexus compiler manager.
+ */
+ @Component
+ protected CompilerManager compilerManager;
+
+ /**
+ *
+ */
+ @Component( role = "org.apache.maven.artifact.metadata.ArtifactMetadataSource", roleHint = "maven" )
+ protected ArtifactMetadataSource artifactMetadataSource;
+
+ public void execute()
+ throws MojoExecutionException, MojoFailureException
+ {
+ // nothing
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/TestAnnotationsReader.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/TestAnnotationsReader.java
new file mode 100644
index 0000000..f51900f
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/annotations/TestAnnotationsReader.java
@@ -0,0 +1,89 @@
+package org.apache.maven.tools.plugin.annotations;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.tools.plugin.annotations.datamodel.ComponentAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.datamodel.ParameterAnnotationContent;
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotatedClass;
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner;
+import org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScannerRequest;
+import org.codehaus.plexus.PlexusTestCase;
+import org.fest.assertions.Assertions;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * @author Olivier Lamy
+ */
+public class TestAnnotationsReader
+ extends PlexusTestCase
+{
+ public void testReadMojoClass()
+ throws Exception
+ {
+ MojoAnnotationsScanner mojoAnnotationsScanner = (MojoAnnotationsScanner) lookup( MojoAnnotationsScanner.ROLE );
+
+ MojoAnnotationsScannerRequest request = new MojoAnnotationsScannerRequest();
+ request.setClassesDirectories( Collections.singletonList( new File( "target/test-classes" ) ) );
+ request.setIncludePatterns( Arrays.asList( "**/FooMojo.class" ) );
+ request.setProject( new MavenProject() );
+
+ Map mojoAnnotatedClasses = mojoAnnotationsScanner.scan( request );
+
+ System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses );
+
+ Assertions.assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 );
+
+ MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.values().iterator().next();
+
+ assertEquals( FooMojo.class.getName(), mojoAnnotatedClass.getClassName() );
+ assertEquals( AbstractMojo.class.getName(), mojoAnnotatedClass.getParentClassName() );
+
+ Mojo mojo = mojoAnnotatedClass.getMojo();
+
+ assertEquals( "foo", mojo.name() );
+ assertEquals( true, mojo.threadSafe() );
+ assertEquals( false, mojo.aggregator() );
+ assertEquals( LifecyclePhase.COMPILE, mojo.defaultPhase() );
+
+ Execute execute = mojoAnnotatedClass.getExecute();
+
+ assertEquals( "compiler", execute.goal() );
+ assertEquals( "my-lifecycle", execute.lifecycle() );
+ assertEquals( LifecyclePhase.PACKAGE, execute.phase() );
+
+ Collection components = mojoAnnotatedClass.getComponents().values();
+ Assertions.assertThat( components ).isNotNull().isNotEmpty().hasSize( 2 );
+
+ Collection parameters = mojoAnnotatedClass.getParameters().values();
+ Assertions.assertThat( parameters ).isNotNull().isNotEmpty().hasSize( 2 ).contains(
+ new ParameterAnnotationContent( "bar", null, "${thebar}", "coolbar", true, false, String.class.getName() ),
+ new ParameterAnnotationContent( "beer", null, "${thebeer}", "coolbeer", false, false,
+ String.class.getName() ) );
+ }
+}
diff --git a/maven-plugin-tools-ant/pom.xml b/maven-plugin-tools-ant/pom.xml
index ac1ef38..fb44f78 100644
--- a/maven-plugin-tools-ant/pom.xml
+++ b/maven-plugin-tools-ant/pom.xml
@@ -25,7 +25,7 @@
org.apache.maven.plugin-tools
maven-plugin-tools
- 2.10-SNAPSHOT
+ 3.0-SNAPSHOT
maven-plugin-tools-ant
diff --git a/maven-plugin-tools-api/pom.xml b/maven-plugin-tools-api/pom.xml
index 62e9700..6de6aa0 100644
--- a/maven-plugin-tools-api/pom.xml
+++ b/maven-plugin-tools-api/pom.xml
@@ -25,7 +25,7 @@
org.apache.maven.plugin-tools
maven-plugin-tools
- 2.10-SNAPSHOT
+ 3.0-SNAPSHOT
maven-plugin-tools-api
@@ -71,6 +71,31 @@
org.codehaus.plexus
plexus-container-default
null.
*/
String getEncoding();
/**
* Sets the file encoding of the source files.
- *
+ *
* @param encoding The file encoding of the source files, may be empty or null to use the platform's
- * default encoding.
+ * default encoding.
* @return This request.
*/
PluginToolsRequest setEncoding( String encoding );
+ /**
+ * By default an exception is throw if no mojo descriptor is found. As the maven-plugin is defined in core, the
+ * descriptor generator mojo is bound to generate-resources phase.
+ * But for annotations, the compiled classes are needed, so skip error
+ *
+ * @since 3.0
+ */
+ PluginToolsRequest setSkipErrorNoDescriptorsFound( boolean skipErrorNoDescriptorsFound );
+
+ /**
+ * @return
+ * @since 3.0
+ */
+ boolean isSkipErrorNoDescriptorsFound();
+
+ /**
+ * Returns the list of {@link Artifact} used in class path scanning for annotations
+ *
+ * @return
+ * @since 3.0
+ */
+ Setnull.
+ * @return The mojo descriptor for the generated help goal, never null.
*/
+ private MojoDescriptor makeHelpDescriptor( PluginDescriptor pluginDescriptor, String packageName )
+ {
+ MojoDescriptor descriptor = new MojoDescriptor();
+
+ descriptor.setPluginDescriptor( pluginDescriptor );
+
+ descriptor.setLanguage( "java" );
+
+ descriptor.setGoal( "help" );
+
+ if ( StringUtils.isEmpty( packageName ) )
+ {
+ packageName = discoverPackageName( pluginDescriptor );
+ }
+ if ( StringUtils.isNotEmpty( packageName ) )
+ {
+ descriptor.setImplementation( packageName + '.' + "HelpMojo" );
+ }
+ else
+ {
+ descriptor.setImplementation( "HelpMojo" );
+ }
+
+ descriptor.setDescription(
+ "Display help information on " + pluginDescriptor.getArtifactId() + ".mvn " + + descriptor.getFullGoalName() + + " -Ddetail=true -Dgoal=<goal-name>to display parameter details." ); + + try + { + Parameter param = new Parameter(); + param.setName( "detail" ); + param.setType( "boolean" ); + param.setDescription( "If
true, display all settable properties for each goal." );
+ param.setDefaultValue( "false" );
+ param.setExpression( "${detail}" );
+ descriptor.addParameter( param );
+
+ param = new Parameter();
+ param.setName( "goal" );
+ param.setType( "java.lang.String" );
+ param.setDescription(
+ "The name of the goal for which to show help." + " If unspecified, all goals will be displayed." );
+ param.setExpression( "${goal}" );
+ descriptor.addParameter( param );
+
+ param = new Parameter();
+ param.setName( "lineLength" );
+ param.setType( "int" );
+ param.setDescription( "The maximum length of a display line, should be positive." );
+ param.setDefaultValue( "80" );
+ param.setExpression( "${lineLength}" );
+ descriptor.addParameter( param );
+
+ param = new Parameter();
+ param.setName( "indentSize" );
+ param.setType( "int" );
+ param.setDescription( "The number of spaces per indentation level, should be positive." );
+ param.setDefaultValue( "2" );
+ param.setExpression( "${indentSize}" );
+ descriptor.addParameter( param );
+ }
+ catch ( Exception e )
+ {
+ throw new RuntimeException( "Failed to setup parameters for help goal", e );
+ }
+
+ return descriptor;
+ }
+
+ /**
+ * Find the best package name, based on the number of hits of actual Mojo classes.
+ *
+ * @param pluginDescriptor not null
+ * @return the best name of the package for the generated mojo
+ */
+ private static String discoverPackageName( PluginDescriptor pluginDescriptor )
+ {
+ Map packageNames = new HashMap();
+ for ( Iterator it = pluginDescriptor.getMojos().iterator(); it.hasNext(); )
+ {
+ MojoDescriptor descriptor = (MojoDescriptor) it.next();
+
+ String impl = descriptor.getImplementation();
+ if ( impl.lastIndexOf( '.' ) != -1 )
+ {
+ String name = impl.substring( 0, impl.lastIndexOf( '.' ) );
+ if ( packageNames.get( name ) != null )
+ {
+ int next = ( (Integer) packageNames.get( name ) ).intValue() + 1;
+ packageNames.put( name, new Integer( next ) );
+ }
+ else
+ {
+ packageNames.put( name, new Integer( 1 ) );
+ }
+ }
+ else
+ {
+ packageNames.put( "", new Integer( 1 ) );
+ }
+ }
+
+ String packageName = "";
+ int max = 0;
+ for ( Iterator it = packageNames.keySet().iterator(); it.hasNext(); )
+ {
+ String key = it.next().toString();
+ int value = ( (Integer) packageNames.get( key ) ).intValue();
+ if ( value > max )
+ {
+ max = value;
+ packageName = key;
+ }
+ }
+
+ return packageName;
+ }
+
protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w )
+ {
+ processMojoDescriptor( mojoDescriptor, w, false );
+ }
+
+ /**
+ * @param mojoDescriptor not null
+ * @param w not null
+ * @param cleanDescription will clean html content from description fields
+ */
+ protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w, boolean cleanDescription )
{
w.startElement( "mojo" );
@@ -152,7 +353,14 @@ public class PluginDescriptorGenerator
if ( description != null )
{
w.startElement( "description" );
- w.writeText( mojoDescriptor.getDescription() );
+ if ( cleanDescription )
+ {
+ w.writeText( PluginUtils.toText( mojoDescriptor.getDescription() ) );
+ }
+ else
+ {
+ w.writeText( mojoDescriptor.getDescription() );
+ }
w.endElement();
}
@@ -323,8 +531,7 @@ public class PluginDescriptorGenerator
// Parameters
// ----------------------------------------------------------------------
- @SuppressWarnings( "unchecked" )
- ListHelpMojo class.
@@ -56,20 +57,30 @@ public class PluginHelpGenerator
extends AbstractLogEnabled
implements Generator
{
- /** Line separator */
+ /**
+ * Line separator
+ */
private static final String LS = System.getProperty( "line.separator" );
- /** Default generated class name */
+ /**
+ * Default generated class name
+ */
private static final String HELP_MOJO_CLASS_NAME = "HelpMojo";
- /** Default goal */
+ /**
+ * Default goal
+ */
private static final String HELP_GOAL = "help";
private String helpPackageName;
-
- /** Flag to indicate if the generated help mojo should use Java 5 features */
+
+ /**
+ * Flag to indicate if the generated help mojo should use Java 5 features
+ */
private boolean useJava5;
+ private VelocityComponent velocityComponent;
+
/**
* Default constructor
*/
@@ -82,46 +93,67 @@ public class PluginHelpGenerator
// Public methods
// ----------------------------------------------------------------------
- /** {@inheritDoc} */
- public void execute( File destinationDirectory, PluginDescriptor pluginDescriptor )
- throws IOException
- {
- execute( destinationDirectory, new DefaultPluginToolsRequest( null, pluginDescriptor ) );
- }
-
- /** {@inheritDoc} */
+
+ /**
+ * {@inheritDoc}
+ */
public void execute( File destinationDirectory, PluginToolsRequest request )
- throws IOException
+ throws GeneratorException
{
PluginDescriptor pluginDescriptor = request.getPluginDescriptor();
-
- if ( pluginDescriptor.getMojos() == null || pluginDescriptor.getMojos().size() < 1 )
- {
- return;
- }
MojoDescriptor helpDescriptor = makeHelpDescriptor( pluginDescriptor );
- // Verify that no help goal already exists
- for ( @SuppressWarnings( "unchecked" )
- Iteratornull.
+ * null.
* @return The mojo descriptor for the generated help goal, never null.
*/
private MojoDescriptor makeHelpDescriptor( PluginDescriptor pluginDescriptor )
@@ -187,9 +262,10 @@ public class PluginHelpGenerator
descriptor.setImplementation( HELP_MOJO_CLASS_NAME );
}
- descriptor.setDescription( "Display help information on " + pluginDescriptor.getArtifactId()
- + ".mvn " + descriptor.getFullGoalName() - + " -Ddetail=true -Dgoal=<goal-name>to display parameter details." ); + descriptor.setDescription( + "Display help information on " + pluginDescriptor.getArtifactId() + ".
mvn " + + descriptor.getFullGoalName() + + " -Ddetail=true -Dgoal=<goal-name>to display parameter details." ); try { @@ -204,8 +280,8 @@ public class PluginHelpGenerator param = new Parameter(); param.setName( "goal" ); param.setType( "java.lang.String" ); - param.setDescription( "The name of the goal for which to show help." - + " If unspecified, all goals will be displayed." ); + param.setDescription( + "The name of the goal for which to show help." + " If unspecified, all goals will be displayed." ); param.setExpression( "${goal}" ); descriptor.addParameter( param ); @@ -239,597 +315,55 @@ public class PluginHelpGenerator * @param pluginDescriptor not null * @return the best name of the package for the generated mojo */ - private static String discoverPackageName( PluginDescriptor pluginDescriptor ) + protected static String discoverPackageName( PluginDescriptor pluginDescriptor ) { Map
HelpMojo class.
- *
- * @param writer not null
- * @param pluginDescriptor not null
- * @param helpDescriptor not null
- * @param useJava5 If the generated code should use Java5 features
- * @throws IOException if any
- */
- private static void writeClass( Writer writer, PluginDescriptor pluginDescriptor, MojoDescriptor helpDescriptor,
- boolean useJava5 )
- throws IOException
- {
- String packageName = "";
- String simpleName = helpDescriptor.getImplementation();
- int dot = simpleName.lastIndexOf( '.' );
- if ( dot >= 0 )
- {
- packageName = simpleName.substring( 0, dot );
- simpleName = simpleName.substring( dot + 1 );
- }
-
- if ( packageName.length() > 0 )
- {
- writer.write( "package " + packageName + ";" + LS );
- writer.write( LS );
- }
-
- writeImports( writer );
- writer.write( LS );
-
- writeMojoJavadoc( writer, pluginDescriptor, helpDescriptor );
-
- if ( useJava5 )
- {
- writer.write( "@SuppressWarnings( \"all\" )" + LS );
- }
-
- writer.write( "public class " + simpleName + LS );
- writer.write( " extends AbstractMojo" + LS );
- writer.write( "{" + LS );
-
- writeVariables( writer, helpDescriptor );
-
- writer.write( LS );
-
- writeExecute( writer, pluginDescriptor, helpDescriptor );
-
- writer.write( LS );
- writeUtilities( writer, useJava5 );
- writer.write( "}" + LS );
- }
-
- /**
- * @param writer not null
- * @throws IOException if any
- */
- private static void writeImports( Writer writer )
- throws IOException
- {
- writer.write( "import java.util.ArrayList;" + LS );
- writer.write( "import java.util.Iterator;" + LS );
- writer.write( "import java.util.List;" + LS );
- writer.write( LS );
- writer.write( "import org.apache.maven.plugin.AbstractMojo;" + LS );
- writer.write( "import org.apache.maven.plugin.MojoExecutionException;" + LS );
- }
-
- /**
- * @param writer not null
- * @param pluginDescriptor not null
- * @param helpDescriptor not null
- * @throws IOException if any
- */
- private static void writeMojoJavadoc( Writer writer, PluginDescriptor pluginDescriptor,
- MojoDescriptor helpDescriptor )
- throws IOException
- {
- StringBuffer author = new StringBuffer();
- author.append( PluginHelpGenerator.class.getName() );
-
- String resource = "META-INF/maven/org.apache.maven.plugin-tools/maven-plugin-tools-api/pom.properties";
- InputStream resourceAsStream = PluginHelpGenerator.class.getClassLoader().getResourceAsStream( resource );
-
- if ( resourceAsStream != null )
- {
- try
- {
- Properties properties = new Properties();
- properties.load( resourceAsStream );
-
- author.append( " (version " ).append( properties.getProperty( "version", "unknown" ) ).append( ")" );
- }
- catch ( IOException e )
- {
- // nope
- }
- finally
- {
- IOUtil.close( resourceAsStream );
- }
- }
-
- writer.write( "/**" + LS );
- writer.write( " * " + helpDescriptor.getDescription() + LS );
- writer.write( " *" + LS );
- writer.write( " * @version generated on " + new Date() + LS );
- writer.write( " * @author " + author.toString() + LS );
- writer.write( " * @goal " + helpDescriptor.getGoal() + LS );
- writer.write( " * @requiresProject false" + LS );
- writer.write( " * @threadSafe" + LS );
- writer.write( " */" + LS );
- }
-
- /**
- * @param writer not null
- * @param helpDescriptor not null
- * @throws IOException if any
- */
- private static void writeVariables( Writer writer, MojoDescriptor helpDescriptor )
- throws IOException
- {
- for ( @SuppressWarnings( "unchecked" )
- IteratorRepeat a String n times to form a new string.
repeat < 0" + LS );
- writer.write( " * @throws NullPointerException if str is null" + LS );
- writer.write( " */" + LS );
- writer.write( " private static String repeat( String str, int repeat )" + LS );
- writer.write( " {" + LS );
- writer.write( " StringBuffer buffer = new StringBuffer( repeat * str.length() );" + LS );
- writer.write( LS );
- writer.write( " for ( int i = 0; i < repeat; i++ )" + LS );
- writer.write( " {" + LS );
- writer.write( " buffer.append( str );" + LS );
- writer.write( " }" + LS );
- writer.write( LS );
- writer.write( " return buffer.toString();" + LS );
- writer.write( " }" + LS );
-
- writer.write( LS );
- writer.write( " /** " + LS );
- writer.write( " * Append a description to the buffer by respecting the indentSize and lineLength "
- + "parameters." + LS );
- writer.write( " * Note: The last character is always a new line." + LS );
- writer.write( " * " + LS );
- writer.write( " * @param sb The buffer to append the description, not null." + LS );
- writer.write( " * @param description The description, not null." + LS );
- writer.write( " * @param indent The base indentation level of each line, must not be negative." + LS );
- writer.write( " */" + LS );
- writer.write( " private void append( StringBuffer sb, String description, int indent )" + LS );
- writer.write( " {" + LS );
- writer.write( " for ( Iterator it = toLines( description, indent, indentSize, lineLength )"
- + ".iterator(); it.hasNext(); )" + LS );
- writer.write( " {" + LS );
- writer.write( " sb.append( it.next().toString() ).append( '\\n' );" + LS );
- writer.write( " }" + LS );
- writer.write( " }" + LS );
-
- writer.write( LS );
- writer.write( " /** " + LS );
- writer.write( " * Splits the specified text into lines of convenient display length." + LS );
- writer.write( " * " + LS );
- writer.write( " * @param text The text to split into lines, must not be null." + LS );
- writer.write( " * @param indent The base indentation level of each line, must not be negative." + LS );
- writer.write( " * @param indentSize The size of each indentation, must not be negative." + LS );
- writer.write( " * @param lineLength The length of the line, must not be negative." + LS );
- writer.write( " * @return The sequence of display lines, never null." + LS );
- writer.write( " * @throws NegativeArraySizeException if indent < 0" + LS );
- writer.write( " */" + LS );
- writer.write( " private static List toLines( String text, int indent, int indentSize, int lineLength )"
- + LS );
- writer.write( " {" + LS );
- if ( useJava5 )
- {
- writer.write( " Listnull." + LS );
- writer.write( " * @param line The line to add, must not be null." + LS );
- writer.write( " * @param indentSize The size of each indentation, must not be negative." + LS );
- writer.write( " * @param lineLength The length of the line, must not be negative." + LS );
- writer.write( " */" + LS );
- if ( useJava5 )
- {
- writer.write( " private static void toLines( Listnull." + LS );
- writer.write( " * @return The indentation level of the line." + LS );
- writer.write( " */" + LS );
- writer.write( " private static int getIndentLevel( String line )" + LS );
- writer.write( " {" + LS );
- writer.write( " int level = 0;" + LS );
- writer.write( " for ( int i = 0; i < line.length() && line.charAt( i ) == '\\t'; i++ )" + LS );
- writer.write( " {" + LS );
- writer.write( " level++;" + LS );
- writer.write( " }" + LS );
- writer.write( " for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )" + LS );
- writer.write( " {" + LS );
- writer.write( " if ( line.charAt( i ) == '\\t' )" + LS );
- writer.write( " {" + LS );
- writer.write( " level++;" + LS );
- writer.write( " break;" + LS );
- writer.write( " }" + LS );
- writer.write( " }" + LS );
- writer.write( " return level;" + LS );
- writer.write( " }" + LS );
- }
-
- /**
- * Gets the effective string to use for the plugin/mojo/parameter description.
- *
- * @param description The description of the element, may be null.
- * @return The effective description string, never null.
- */
- private static String toDescription( String description )
- {
- if ( StringUtils.isNotEmpty( description ) )
- {
- return StringUtils.escape( PluginUtils.toText( description ) );
- }
-
- return "(no description available)";
- }
-
- /**
- * Converts a HTML fragment as extracted from a javadoc comment to a plain text string. This method tries to retain
- * as much of the text formatting as possible by means of the following transformations:
- * null.
- * @return A string with HTML tags converted into pure text, never null.
- * @deprecated since 2.4.3, using {@link PluginUtils#toText(String)} instead of.
- */
- protected static String toText( String html )
- {
- return PluginUtils.toText( html );
- }
}
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
index 899d70e..fbd3a1c 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/generator/PluginXdocGenerator.java
@@ -19,6 +19,17 @@ package org.apache.maven.tools.plugin.generator;
* under the License.
*/
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
+import org.apache.maven.tools.plugin.PluginToolsRequest;
+import org.apache.maven.tools.plugin.util.PluginUtils;
+import org.codehaus.plexus.util.IOUtil;
+import org.codehaus.plexus.util.StringUtils;
+import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
+import org.codehaus.plexus.util.xml.XMLWriter;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -32,30 +43,21 @@ import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
-import org.apache.maven.plugin.descriptor.MojoDescriptor;
-import org.apache.maven.plugin.descriptor.Parameter;
-import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
-import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
-import org.apache.maven.tools.plugin.PluginToolsRequest;
-import org.apache.maven.tools.plugin.util.PluginUtils;
-import org.codehaus.plexus.util.IOUtil;
-import org.codehaus.plexus.util.StringUtils;
-import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
-import org.codehaus.plexus.util.xml.XMLWriter;
-
/**
- * @todo add example usage tag that can be shown in the doco
* @version $Id$
+ * @todo add example usage tag that can be shown in the doco
*/
public class PluginXdocGenerator
implements Generator
{
- /** locale */
+ /**
+ * locale
+ */
private final Locale locale;
- /** project */
+ /**
+ * project
+ */
private final MavenProject project;
/**
@@ -81,7 +83,7 @@ public class PluginXdocGenerator
/**
* @param project not null.
- * @param locale not null wanted locale.
+ * @param locale not null wanted locale.
*/
public PluginXdocGenerator( MavenProject project, Locale locale )
{
@@ -96,31 +98,35 @@ public class PluginXdocGenerator
}
}
- /** {@inheritDoc} */
- public void execute( File destinationDirectory, PluginDescriptor pluginDescriptor )
- throws IOException
- {
- execute( destinationDirectory, new DefaultPluginToolsRequest( project, pluginDescriptor ) );
- }
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public void execute( File destinationDirectory, PluginToolsRequest request )
- throws IOException
+ throws GeneratorException
{
- if ( request.getPluginDescriptor().getMojos() != null )
+ try
{
- for ( @SuppressWarnings( "unchecked" )
- Iteratortrue for required parameters, false otherwise.
+ * @param required true for required parameters, false otherwise.
* @param parameterList not null
* @return list of parameters depending the value of required
*/
@@ -792,21 +797,21 @@ public class PluginXdocGenerator
/**
* Convenience method.
*
- * @param key not null
+ * @param key not null
* @param arg1 not null
* @return Localized, formatted text identified by key.
* @see #format(String, Object[])
*/
private String format( String key, Object arg1 )
{
- return format( key, new Object[] { arg1 } );
+ return format( key, new Object[]{ arg1 } );
}
/**
* Looks up the value for key in the ResourceBundle,
* then formats that value for the specified Locale using args.
*
- * @param key not null
+ * @param key not null
* @param args not null
* @return Localized, formatted text identified by key.
*/
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java
index 1d5d8a2..05a2b1c 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java
@@ -19,11 +19,6 @@ package org.apache.maven.tools.plugin.scanner;
* under the License.
*/
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@@ -36,6 +31,11 @@ import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* @author jdcasey
*/
@@ -71,14 +71,18 @@ public class DefaultMojoScanner
// nop
}
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ */
public void populatePluginDescriptor( MavenProject project, PluginDescriptor pluginDescriptor )
throws ExtractionException, InvalidPluginDescriptorException
{
populatePluginDescriptor( new DefaultPluginToolsRequest( project, pluginDescriptor ) );
}
-
- /** {@inheritDoc} */
+
+ /**
+ * {@inheritDoc}
+ */
public void populatePluginDescriptor( PluginToolsRequest request )
throws ExtractionException, InvalidPluginDescriptorException
{
@@ -103,7 +107,7 @@ public class DefaultMojoScanner
Listmvn plugin:help -Ddetail=true -Dgoal=<goal-name>to display parameter details. + * @author + * @version + * @goal help + * @requiresProject false + * @threadSafe + */ +public class HelpMojo + extends AbstractMojo +{ + /** + * If
true, display all settable properties for each goal.
+ *
+ */
+ //@Parameter( expression = "${detail}", defaultValue = "false" )
+ //private boolean detail;
+
+ /**
+ * The name of the goal for which to show help. If unspecified, all goals will be displayed.
+ *
+ */
+ //@Parameter( expression = "${goal}" )
+ //private java.lang.String goal;
+
+ /**
+ * The maximum length of a display line, should be positive.
+ *
+ */
+ //@Parameter( expression = "${lineLength}", defaultValue = "80" )
+ //private int lineLength;
+
+ /**
+ * The number of spaces per indentation level, should be positive.
+ *
+ */
+ //@Parameter( expression = "${indentSize}", defaultValue = "2" )
+ //private int indentSize;
+
+/**
+ * If true, display all settable properties for each goal.
+ *
+ * @parameter expression="${detail}" default-value="false"
+ */
+private boolean detail;
+
+/**
+ * The name of the goal for which to show help. If unspecified, all goals will be displayed.
+ *
+ * @parameter expression="${goal}"
+ */
+private java.lang.String goal;
+
+/**
+ * The maximum length of a display line, should be positive.
+ *
+ * @parameter expression="${lineLength}" default-value="80"
+ */
+private int lineLength;
+
+/**
+ * The number of spaces per indentation level, should be positive.
+ *
+ * @parameter expression="${indentSize}" default-value="2"
+ */
+private int indentSize;
+
+ // groupId/artifactId/version
+ private String pluginDescriptorPath = "/${propertiesFilePath}";
+
+ private Xpp3Dom build()
+ throws MojoExecutionException
+ {
+ // olamy more than one pluginDescriptor in the classloader possible ?
+ getLog().debug("load pluginDescriptorPath: " + pluginDescriptorPath);
+ InputStream is = getClass().getResourceAsStream( pluginDescriptorPath );
+ try
+ {
+ return Xpp3DomBuilder.build( is, "ISO-8859-1" );
+ }
+ catch ( XmlPullParserException e )
+ {
+ throw new MojoExecutionException( e.getMessage(), e );
+ }
+ catch ( IOException e )
+ {
+ throw new MojoExecutionException( e.getMessage(), e );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void execute()
+ throws MojoExecutionException
+ {
+ if ( lineLength <= 0 )
+ {
+ getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
+ lineLength = 80;
+ }
+ if ( indentSize <= 0 )
+ {
+ getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
+ indentSize = 2;
+ }
+
+ // FIXME encoding as parameter
+ Xpp3Dom pluginElement = build();
+
+ StringBuffer sb = new StringBuffer();
+ /**
+ * Repeat a String n times to form a new string.
repeat < 0
+ * @throws NullPointerException if str is null
+ */
+ private static String repeat( String str, int repeat )
+ {
+ StringBuffer buffer = new StringBuffer( repeat * str.length() );
+
+ for ( int i = 0; i < repeat; i++ )
+ {
+ buffer.append( str );
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Append a description to the buffer by respecting the indentSize and lineLength parameters.
+ * Note: The last character is always a new line.
+ *
+ * @param sb The buffer to append the description, not null.
+ * @param description The description, not null.
+ * @param indent The base indentation level of each line, must not be negative.
+ */
+ private void append( StringBuffer sb, String description, int indent )
+ {
+ for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
+ {
+ sb.append( it.next().toString() ).append( '\n' );
+ }
+ }
+
+ /**
+ * Splits the specified text into lines of convenient display length.
+ *
+ * @param text The text to split into lines, must not be null.
+ * @param indent The base indentation level of each line, must not be negative.
+ * @param indentSize The size of each indentation, must not be negative.
+ * @param lineLength The length of the line, must not be negative.
+ * @return The sequence of display lines, never null.
+ * @throws NegativeArraySizeException if indent < 0
+ */
+ private static List toLines( String text, int indent, int indentSize, int lineLength )
+ {
+ Listnull.
+ * @param line The line to add, must not be null.
+ * @param indentSize The size of each indentation, must not be negative.
+ * @param lineLength The length of the line, must not be negative.
+ */
+ private static void toLines( Listnull.
+ * @return The indentation level of the line.
+ */
+ private static int getIndentLevel( String line )
+ {
+ int level = 0;
+ for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
+ {
+ level++;
+ }
+ for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
+ {
+ if ( line.charAt( i ) == '\t' )
+ {
+ level++;
+ break;
+ }
+ }
+ return level;
+ }
+
+
+}
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java
index e987068..0087e1c 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/AbstractGeneratorTestCase.java
@@ -19,11 +19,13 @@ package org.apache.maven.tools.plugin.generator;
* under the License.
*/
-import junit.framework.TestCase;
+import org.apache.maven.model.Build;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.Parameter;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.project.MavenProject;
import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.codehaus.plexus.PlexusTestCase;
import org.codehaus.plexus.component.repository.ComponentDependency;
import org.codehaus.plexus.util.FileUtils;
@@ -38,7 +40,7 @@ import java.util.List;
* jdcasey Exp $
*/
public abstract class AbstractGeneratorTestCase
- extends TestCase
+ extends PlexusTestCase
{
protected Generator generator;
@@ -47,6 +49,7 @@ public abstract class AbstractGeneratorTestCase
protected void setUp()
throws Exception
{
+ super.setUp();
basedir = System.getProperty( "basedir" );
}
@@ -93,7 +96,25 @@ public abstract class AbstractGeneratorTestCase
FileUtils.deleteDirectory( destinationDirectory );
destinationDirectory.mkdir();
- generator.execute( destinationDirectory, new DefaultPluginToolsRequest( null, pluginDescriptor ) );
+ MavenProject mavenProject = new MavenProject();
+ mavenProject.setGroupId( "foo" );
+ mavenProject.setArtifactId( "bar" );
+ mavenProject.setBuild( new Build()
+ {
+ @Override
+ public String getDirectory()
+ {
+ return basedir + "/target";
+ }
+
+ @Override
+ public String getOutputDirectory()
+ {
+ return basedir + "/target";
+ }
+ } );
+
+ generator.execute( destinationDirectory, new DefaultPluginToolsRequest( mavenProject, pluginDescriptor ) );
validate( destinationDirectory );
@@ -120,8 +141,8 @@ public abstract class AbstractGeneratorTestCase
catch ( Exception e )
{
throw new Exception( "Cannot find " + generatorClassName +
- "! Make sure your test case is named in the form ${generatorClassName}Test " +
- "or override the setupPlugin() method to instantiate the mojo yourself." );
+ "! Make sure your test case is named in the form ${generatorClassName}Test " +
+ "or override the setupPlugin() method to instantiate the mojo yourself." );
}
}
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java
index 78565f2..725967b 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java
@@ -19,6 +19,8 @@ package org.apache.maven.tools.plugin.generator;
* under the License.
*/
+import org.codehaus.plexus.velocity.VelocityComponent;
+
/**
* @author Vincent Siveton
* @version $Id$
@@ -27,4 +29,12 @@ public class PluginHelpGeneratorTest
extends AbstractGeneratorTestCase
{
// inherits tests from base class
+ protected void setupGenerator()
+ throws Exception
+ {
+
+ generator =
+ new PluginHelpGenerator().setVelocityComponent( (VelocityComponent) lookup( VelocityComponent.ROLE ) );
+
+ }
}
diff --git a/maven-plugin-tools-beanshell/pom.xml b/maven-plugin-tools-beanshell/pom.xml
index 27e3e0e..ebb2863 100644
--- a/maven-plugin-tools-beanshell/pom.xml
+++ b/maven-plugin-tools-beanshell/pom.xml
@@ -25,7 +25,7 @@