diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java
index 0e643d6b2..f9eda41ee 100644
--- a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java
+++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Parameter.java
@@ -40,7 +40,7 @@
*/
@Documented
@Retention( RetentionPolicy.CLASS )
-@Target( { ElementType.FIELD } )
+@Target( { ElementType.FIELD, ElementType.METHOD } )
@Inherited
public @interface Parameter
{
diff --git a/maven-plugin-plugin/pom.xml b/maven-plugin-plugin/pom.xml
index e15da895b..b06d58522 100644
--- a/maven-plugin-plugin/pom.xml
+++ b/maven-plugin-plugin/pom.xml
@@ -312,6 +312,7 @@
src/it/settings.xml
true
true
+ true
3.12.1
3.4.1
diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
index b941b803f..90b4b6920 100644
--- a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
+++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
@@ -61,7 +61,7 @@ assert mojo.requirements.requirement[1].role.text() == 'org.apache.maven.project
assert mojo.requirements.requirement[1].'role-hint'.text() == ''
assert mojo.requirements.requirement[1].'field-name'.text() == 'projectHelper'
-assert mojo.parameters.parameter.size() == 4
+assert mojo.parameters.parameter.size() == 7
def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0]
@@ -107,4 +107,37 @@ assert parameter.required.text() == 'false'
assert parameter.editable.text() == 'true'
assert parameter.description.text() == 'Interface type as parameter.'
+parameter = mojo.parameters.parameter.findAll{ it.name.text() == "paramFromSetter"}[0]
+
+assert parameter.name.text() == 'paramFromSetter'
+assert parameter.alias.isEmpty()
+assert parameter.type.text() == 'java.lang.String'
+assert parameter.implementation.isEmpty()
+assert parameter.deprecated.isEmpty()
+assert parameter.required.text() == 'false'
+assert parameter.editable.text() == 'true'
+assert parameter.description.text() == 'setter as parameter.'
+
+parameter = mojo.parameters.parameter.findAll{ it.name.text() == "paramFromAdd"}[0]
+
+assert parameter.name.text() == 'paramFromAdd'
+assert parameter.alias.isEmpty()
+assert parameter.type.text() == 'java.lang.String'
+assert parameter.implementation.isEmpty()
+assert parameter.deprecated.isEmpty()
+assert parameter.required.text() == 'false'
+assert parameter.editable.text() == 'true'
+assert parameter.description.text() == 'add method as parameter.'
+
+parameter = mojo.parameters.parameter.findAll{ it.name.text() == "paramFromSetterDeprecated"}[0]
+
+assert parameter.name.text() == 'paramFromSetterDeprecated'
+assert parameter.alias.isEmpty()
+assert parameter.type.text() == 'java.util.List'
+assert parameter.implementation.isEmpty()
+assert parameter.deprecated.text() == 'reason of deprecation'
+assert parameter.required.text() == 'false'
+assert parameter.editable.text() == 'true'
+assert parameter.description.text() == 'deprecated setter as parameter.'
+
return true;
diff --git a/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm b/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm
index 11785c4f4..a8d9784b4 100644
--- a/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm
+++ b/maven-plugin-plugin/src/site/apt/examples/using-annotations.apt.vm
@@ -41,7 +41,7 @@ Using Plugin Tools Java Annotations
Information for plugin descriptor generation is specified using 4 annotations:
- * 2 class-level annotations:
+ * 2 class level annotations:
* <<<@Mojo>>>: This annotation will mark your class as a Mojo,
@@ -49,10 +49,14 @@ Using Plugin Tools Java Annotations
[]
- * 2 field-level annotations:
+ * 1 field or method level annotations:
* <<<@Parameter>>>: Used to configure your Mojo parameters,
+ []
+
+ * 1 field level annotations:
+
* <<<@Component>>>: Used to configure injection of Plexus components or Maven context components.
[]
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java
index 16210b024..c2d839ca4 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor.java
@@ -46,6 +46,8 @@
import com.thoughtworks.qdox.model.JavaAnnotatedElement;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
+import com.thoughtworks.qdox.model.JavaMember;
+import com.thoughtworks.qdox.model.JavaMethod;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
@@ -63,8 +65,8 @@
import org.apache.maven.tools.plugin.extractor.GroupKey;
import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
import org.apache.maven.tools.plugin.extractor.annotations.converter.ConverterContext;
-import org.apache.maven.tools.plugin.extractor.annotations.converter.JavadocBlockTagsToXhtmlConverter;
import org.apache.maven.tools.plugin.extractor.annotations.converter.JavaClassConverterContext;
+import org.apache.maven.tools.plugin.extractor.annotations.converter.JavadocBlockTagsToXhtmlConverter;
import org.apache.maven.tools.plugin.extractor.annotations.converter.JavadocInlineTagsToXhtmlConverter;
import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent;
@@ -141,7 +143,7 @@ public List execute( PluginToolsRequest request )
JavaProjectBuilder builder = scanJavadoc( request, mojoAnnotatedClasses.values() );
Map javaClassesMap = discoverClasses( builder );
-
+
JavadocLinkGenerator linkGenerator = new JavadocLinkGenerator( request.getInternalJavadocBaseUrl(),
request.getInternalJavadocVersion(),
request.getExternalJavadocBaseUrls(),
@@ -176,11 +178,11 @@ private JavaProjectBuilder scanJavadoc( PluginToolsRequest request,
// if we need to scan sources from external artifacts
Set externalArtifacts = new HashSet<>();
-
+
JavaProjectBuilder builder = new JavaProjectBuilder( new SortedClassLibraryBuilder( ) );
builder.setEncoding( request.getEncoding() );
extendJavaProjectBuilder( builder, request.getProject() );
-
+
for ( MojoAnnotatedClass mojoAnnotatedClass : mojoAnnotatedClasses )
{
if ( Objects.equals( mojoAnnotatedClass.getArtifact().getArtifactId(),
@@ -244,7 +246,7 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
Map javaClassesMap,
JavadocLinkGenerator linkGenerator )
{
-
+
for ( Map.Entry entry : mojoAnnotatedClasses.entrySet() )
{
JavaClass javaClass = javaClassesMap.get( entry.getKey() );
@@ -256,11 +258,11 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
MojoAnnotationContent mojoAnnotationContent = entry.getValue().getMojo();
if ( mojoAnnotationContent != null )
{
- JavaClassConverterContext context =
+ JavaClassConverterContext context =
new JavaClassConverterContext( javaClass, javaProjectBuilder,
- mojoAnnotatedClasses, linkGenerator,
+ mojoAnnotatedClasses, linkGenerator,
javaClass.getLineNumber() );
- mojoAnnotationContent.setDescription(
+ mojoAnnotationContent.setDescription(
getDescriptionFromElement( javaClass, context ) );
DocletTag since = findInClassHierarchy( javaClass, "since" );
@@ -276,7 +278,7 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
}
}
- Map fieldsMap = extractFieldParameterTags( javaClass, javaClassesMap );
+ Map elementMap = extractParameterAnnotations( javaClass, javaClassesMap );
// populate parameters
Map parameters =
@@ -284,27 +286,27 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
parameters = new TreeMap<>( parameters );
for ( Map.Entry parameter : parameters.entrySet() )
{
- JavaField javaField = fieldsMap.get( parameter.getKey() );
- if ( javaField == null )
+ JavaAnnotatedElement element = elementMap.get( parameter.getKey() );
+ if ( element == null )
{
continue;
}
- JavaClassConverterContext context =
- new JavaClassConverterContext( javaClass, javaField.getDeclaringClass(),
- javaProjectBuilder, mojoAnnotatedClasses,
- linkGenerator, javaField.getLineNumber() );
+ JavaClassConverterContext context =
+ new JavaClassConverterContext( javaClass, ( (JavaMember) element ).getDeclaringClass(),
+ javaProjectBuilder, mojoAnnotatedClasses,
+ linkGenerator, element.getLineNumber() );
ParameterAnnotationContent parameterAnnotationContent = parameter.getValue();
- parameterAnnotationContent.setDescription(
- getDescriptionFromElement( javaField, context ) );
+ parameterAnnotationContent.setDescription(
+ getDescriptionFromElement( element, context ) );
- DocletTag deprecated = javaField.getTagByName( "deprecated" );
+ DocletTag deprecated = element.getTagByName( "deprecated" );
if ( deprecated != null )
{
parameterAnnotationContent.setDeprecated( getRawValueFromTaglet ( deprecated, context ) );
}
- DocletTag since = javaField.getTagByName( "since" );
+ DocletTag since = element.getTagByName( "since" );
if ( since != null )
{
parameterAnnotationContent.setSince( getRawValueFromTaglet ( since, context ) );
@@ -315,27 +317,27 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
Map components = entry.getValue().getComponents();
for ( Map.Entry component : components.entrySet() )
{
- JavaField javaField = fieldsMap.get( component.getKey() );
- if ( javaField == null )
+ JavaAnnotatedElement element = elementMap.get( component.getKey() );
+ if ( element == null )
{
continue;
}
- JavaClassConverterContext context =
- new JavaClassConverterContext( javaClass, javaField.getDeclaringClass(),
- javaProjectBuilder, mojoAnnotatedClasses,
- linkGenerator, javaClass.getLineNumber() );
+ JavaClassConverterContext context =
+ new JavaClassConverterContext( javaClass, ( (JavaMember) element ).getDeclaringClass(),
+ javaProjectBuilder, mojoAnnotatedClasses,
+ linkGenerator, javaClass.getLineNumber() );
ComponentAnnotationContent componentAnnotationContent = component.getValue();
- componentAnnotationContent.setDescription(
- getDescriptionFromElement( javaField, context ) );
+ componentAnnotationContent.setDescription(
+ getDescriptionFromElement( element, context ) );
- DocletTag deprecated = javaField.getTagByName( "deprecated" );
+ DocletTag deprecated = element.getTagByName( "deprecated" );
if ( deprecated != null )
{
componentAnnotationContent.setDeprecated( getRawValueFromTaglet ( deprecated, context ) );
}
- DocletTag since = javaField.getTagByName( "since" );
+ DocletTag since = element.getTagByName( "since" );
if ( since != null )
{
componentAnnotationContent.setSince( getRawValueFromTaglet ( since, context ) );
@@ -355,7 +357,7 @@ protected void populateDataFromJavadoc( JavaProjectBuilder javaProjectBuilder,
*/
String getDescriptionFromElement( JavaAnnotatedElement element, JavaClassConverterContext context )
{
-
+
String comment = element.getComment();
if ( comment == null )
{
@@ -411,16 +413,17 @@ private DocletTag findInClassHierarchy( JavaClass javaClass, String tagName )
/**
* extract fields that are either parameters or components.
+ * Also extract methods that are parameters
*
* @param javaClass not null
* @return map with Mojo parameters names as keys
*/
- private Map extractFieldParameterTags( JavaClass javaClass,
- Map javaClassesMap )
+ private Map extractParameterAnnotations( JavaClass javaClass,
+ Map javaClassesMap )
{
try
{
- Map rawParams = new TreeMap<>();
+ 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...
@@ -428,15 +431,15 @@ private Map extractFieldParameterTags( JavaClass javaClass,
if ( superClass != null )
{
- if ( superClass.getFields().size() > 0 )
+ if ( !superClass.getFields().isEmpty() || !superClass.getMethods().isEmpty() )
{
- rawParams = extractFieldParameterTags( superClass, javaClassesMap );
+ rawParams = extractParameterAnnotations( superClass, javaClassesMap );
}
// maybe sources comes from scan of sources artifact
superClass = javaClassesMap.get( superClass.getFullyQualifiedName() );
- if ( superClass != null )
+ if ( superClass != null && ( !superClass.getFields().isEmpty() || !superClass.getMethods().isEmpty() ) )
{
- rawParams = extractFieldParameterTags( superClass, javaClassesMap );
+ rawParams = extractParameterAnnotations( superClass, javaClassesMap );
}
}
else
@@ -450,6 +453,15 @@ private Map extractFieldParameterTags( JavaClass javaClass,
rawParams.put( field.getName(), field );
}
+ for ( JavaMethod method : javaClass.getMethods() )
+ {
+ if ( isPublicSetterMethod( method ) )
+ {
+ rawParams.put(
+ StringUtils.lowercaseFirstLetter( method.getName().substring( 3 ) ), method );
+ }
+ }
+
return rawParams;
}
catch ( NoClassDefFoundError e )
@@ -459,6 +471,16 @@ private Map extractFieldParameterTags( JavaClass javaClass,
}
}
+ private boolean isPublicSetterMethod( JavaMethod method )
+ {
+ return method.isPublic()
+ && !method.isStatic()
+ && method.getName().length() > 3
+ && ( method.getName().startsWith( "add" ) || method.getName().startsWith( "set" ) )
+ && "void".equals( method.getReturnType().getValue() )
+ && method.getParameters().size() == 1;
+ }
+
protected Map discoverClasses( JavaProjectBuilder builder )
{
Collection javaClasses = builder.getClasses();
@@ -477,7 +499,7 @@ protected Map discoverClasses( JavaProjectBuilder builder )
return javaClassMap;
}
-
+
protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builder,
Artifact artifact, PluginToolsRequest request,
String classifier )
@@ -488,7 +510,7 @@ protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builde
Artifact sourcesArtifact =
repositorySystem.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(),
artifact.getVersion(), artifact.getType(), classifier );
-
+
ArtifactResolutionRequest req = new ArtifactResolutionRequest();
req.setArtifact( sourcesArtifact );
req.setLocalRepository( request.getLocal() );
@@ -501,25 +523,25 @@ protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builde
+ artifact.getVersion() + ". Some javadoc tags (@since, @deprecated and comments) won't be used" );
return;
}
-
+
if ( sourcesArtifact.getFile() == null || !sourcesArtifact.getFile().exists() )
{
// could not get artifact sources
return;
}
-
+
// extract sources to target/maven-plugin-plugin-sources/${groupId}/${artifact}/sources
File extractDirectory = new File( request.getProject().getBuild().getDirectory(),
"maven-plugin-plugin-sources/" + sourcesArtifact.getGroupId() + "/"
+ sourcesArtifact.getArtifactId() + "/" + sourcesArtifact.getVersion()
+ "/" + sourcesArtifact.getClassifier() );
extractDirectory.mkdirs();
-
+
UnArchiver unArchiver = archiverManager.getUnArchiver( "jar" );
unArchiver.setSourceFile( sourcesArtifact.getFile() );
unArchiver.setDestDirectory( extractDirectory );
unArchiver.extract();
-
+
extendJavaProjectBuilder( builder,
Arrays.asList( extractDirectory ),
request.getDependencies() );
@@ -530,7 +552,7 @@ protected void extendJavaProjectBuilderWithSourcesJar( JavaProjectBuilder builde
}
}
- private void extendJavaProjectBuilder( JavaProjectBuilder builder,
+ private void extendJavaProjectBuilder( JavaProjectBuilder builder,
final MavenProject project )
{
List sources = new ArrayList<>();
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
index 0407b8ea1..2b441751c 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
@@ -35,6 +35,7 @@
import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoAnnotationVisitor;
import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoClassVisitor;
import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoFieldVisitor;
+import org.apache.maven.tools.plugin.extractor.annotations.scanner.visitors.MojoParameterVisitor;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.StringUtils;
@@ -56,6 +57,8 @@
import java.util.zip.ZipInputStream;
/**
+ * Mojo scanner with java annotations.
+ *
* @author Olivier Lamy
* @since 3.0
*/
@@ -206,7 +209,7 @@ private void analyzeClassStream( Map mojoAnnotatedCl
Artifact artifact, boolean excludeMojo, String source, String file )
throws IOException, ExtractionException
{
- MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( getLogger() );
+ MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( );
try
{
@@ -295,13 +298,13 @@ protected void analyzeVisitors( MojoClassVisitor mojoClassVisitor )
}
// @Parameter annotations
- List mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation( Parameter.class );
- for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
+ List mojoParameterVisitors = mojoClassVisitor.findParameterVisitors();
+ for ( MojoParameterVisitor parameterVisitor : mojoParameterVisitors )
{
ParameterAnnotationContent parameterAnnotationContent =
- new ParameterAnnotationContent( mojoFieldVisitor.getFieldName(), mojoFieldVisitor.getClassName() );
+ new ParameterAnnotationContent( parameterVisitor.getFieldName(), parameterVisitor.getClassName() );
- Map annotationVisitorMap = mojoFieldVisitor.getAnnotationVisitorMap();
+ Map annotationVisitorMap = parameterVisitor.getAnnotationVisitorMap();
MojoAnnotationVisitor fieldAnnotationVisitor = annotationVisitorMap.get( Parameter.class.getName() );
populateAnnotationContent( parameterAnnotationContent, fieldAnnotationVisitor );
@@ -316,7 +319,7 @@ protected void analyzeVisitors( MojoClassVisitor mojoClassVisitor )
}
// @Component annotations
- mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation( Component.class );
+ List mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotation( Component.class );
for ( MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
{
ComponentAnnotationContent componentAnnotationContent =
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java
index a4e76199c..e1eb5f357 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScanner.java
@@ -45,6 +45,9 @@ public interface MojoAnnotationsScanner
Component.class.getName(),
Deprecated.class.getName() );
+ List METHOD_LEVEL_ANNOTATIONS = Arrays.asList( Parameter.class.getName(),
+ Deprecated.class.getName() );
+
/**
* Scan classes for mojo annotations.
*
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java
index 296cc01a2..225053c12 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoAnnotationVisitor.java
@@ -22,27 +22,25 @@
import java.util.HashMap;
import java.util.Map;
-import org.codehaus.plexus.logging.Logger;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Opcodes;
/**
+ * Visitor for annotations.
+ *
* @author Olivier Lamy
* @since 3.0
*/
public class MojoAnnotationVisitor
extends AnnotationVisitor
{
- private Logger logger;
-
private String annotationClassName;
private Map annotationValues = new HashMap<>();
- MojoAnnotationVisitor( Logger logger, String annotationClassName )
+ MojoAnnotationVisitor( String annotationClassName )
{
super( Opcodes.ASM9 );
- this.logger = logger;
this.annotationClassName = annotationClassName;
}
@@ -66,23 +64,12 @@ public void visitEnum( String name, String desc, String value )
@Override
public AnnotationVisitor visitAnnotation( String name, String desc )
{
- return new MojoAnnotationVisitor( logger, this.annotationClassName );
+ return new MojoAnnotationVisitor( this.annotationClassName );
}
@Override
public AnnotationVisitor visitArray( String s )
{
- return new MojoAnnotationVisitor( logger, this.annotationClassName );
- }
-
- @Override
- public void visitEnd()
- {
- // no op
- }
-
- public String getAnnotationClassName()
- {
- return annotationClassName;
+ return new MojoAnnotationVisitor( this.annotationClassName );
}
}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
index 401203474..9376564d5 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
@@ -19,41 +19,44 @@
* under the License.
*/
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass;
import org.apache.maven.tools.plugin.extractor.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.Opcodes;
import org.objectweb.asm.Type;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
/**
+ * Visitor for Mojo classes.
+ *
* @author Olivier Lamy
* @since 3.0
*/
public class MojoClassVisitor
extends ClassVisitor
{
- private Logger logger;
-
private MojoAnnotatedClass mojoAnnotatedClass;
private Map annotationVisitorMap = new HashMap<>();
private List fieldVisitors = new ArrayList<>();
- public MojoClassVisitor( Logger logger )
+ private List methodVisitors = new ArrayList<>();
+
+ public MojoClassVisitor()
{
super( Opcodes.ASM9 );
- this.logger = logger;
}
public MojoAnnotatedClass getMojoAnnotatedClass()
@@ -61,53 +64,30 @@ public MojoAnnotatedClass getMojoAnnotatedClass()
return mojoAnnotatedClass;
}
- public void setMojoAnnotatedClass( MojoAnnotatedClass mojoAnnotatedClass )
- {
- this.mojoAnnotatedClass = mojoAnnotatedClass;
- }
-
- public Map getAnnotationVisitorMap()
- {
- return annotationVisitorMap;
- }
-
public MojoAnnotationVisitor getAnnotationVisitor( Class> annotation )
{
return annotationVisitorMap.get( annotation.getName() );
}
- public void setAnnotationVisitorMap( Map annotationVisitorMap )
- {
- this.annotationVisitorMap = annotationVisitorMap;
- }
-
- public List getFieldVisitors()
- {
- return fieldVisitors;
- }
-
- public void setFieldVisitors( List fieldVisitors )
- {
- this.fieldVisitors = fieldVisitors;
- }
-
public List findFieldWithAnnotation( Class> annotation )
{
String annotationClassName = annotation.getName();
- List mojoFieldVisitors = new ArrayList<>();
-
- for ( MojoFieldVisitor mojoFieldVisitor : this.fieldVisitors )
- {
- Map filedVisitorMap = mojoFieldVisitor.getAnnotationVisitorMap();
+ return fieldVisitors.stream()
+ .filter( field -> field.getAnnotationVisitorMap().containsKey( annotationClassName ) )
+ .collect( Collectors.toList() );
+ }
- if ( filedVisitorMap.containsKey( annotationClassName ) )
- {
- mojoFieldVisitors.add( mojoFieldVisitor );
- }
- }
+ public List findParameterVisitors()
+ {
+ String annotationClassName = Parameter.class.getName();
- return mojoFieldVisitors;
+ return Stream
+ .concat(
+ findFieldWithAnnotation( Parameter.class ).stream(),
+ methodVisitors.stream()
+ .filter( method -> method.getAnnotationVisitorMap().containsKey( annotationClassName ) ) )
+ .collect( Collectors.toList() );
}
@Override
@@ -129,7 +109,7 @@ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
{
return null;
}
- MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName );
+ MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( annotationClassName );
annotationVisitorMap.put( annotationClassName, mojoAnnotationVisitor );
return mojoAnnotationVisitor;
}
@@ -137,7 +117,7 @@ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
@Override
public FieldVisitor visitField( int access, String name, String desc, String signature, Object value )
{
- MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( logger, name, Type.getType( desc ).getClassName() );
+ MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( name, Type.getType( desc ).getClassName() );
fieldVisitors.add( mojoFieldVisitor );
return mojoFieldVisitor;
}
@@ -145,38 +125,29 @@ public FieldVisitor visitField( int access, String name, String desc, String sig
@Override
public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions )
{
- // we don't need methods informations
- return null;
- }
+ if ( ( access & Opcodes.ACC_PUBLIC ) != Opcodes.ACC_PUBLIC
+ || ( access & Opcodes.ACC_STATIC ) == Opcodes.ACC_STATIC )
+ {
+ return null;
+ }
- @Override
- public void visitAttribute( Attribute attr )
- {
- // no op
- }
+ if ( name.length() < 4 || !( name.startsWith( "add" ) || name.startsWith( "set" ) ) )
+ {
+ return null;
+ }
- @Override
- public void visitSource( String source, String debug )
- {
- // no op
- }
+ Type type = Type.getType( desc );
- @Override
- public void visitOuterClass( String owner, String name, String desc )
- {
- // no op
- }
+ if ( "void".equals( type.getReturnType().getClassName() ) && type.getArgumentTypes().length == 1 )
+ {
+ String fieldName = StringUtils.lowercaseFirstLetter( name.substring( 3 ) );
+ String className = type.getArgumentTypes()[0].getClassName();
- @Override
- public void visitInnerClass( String name, String outerName, String innerName, int access )
- {
- // no op
- }
+ MojoMethodVisitor mojoMethodVisitor = new MojoMethodVisitor( fieldName, className );
+ methodVisitors.add( mojoMethodVisitor );
+ return mojoMethodVisitor;
+ }
- @Override
- public void visitEnd()
- {
- // no op
+ return null;
}
-
}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java
index f69ae0605..550bd579d 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoFieldVisitor.java
@@ -23,41 +23,40 @@
import java.util.Map;
import org.apache.maven.tools.plugin.extractor.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.Opcodes;
import org.objectweb.asm.Type;
/**
+ * Visitors for fields.
+ *
* @author Olivier Lamy
* @since 3.0
*/
public class MojoFieldVisitor
- extends FieldVisitor
+ extends FieldVisitor implements MojoParameterVisitor
{
- private Logger logger;
-
private String fieldName;
private Map annotationVisitorMap = new HashMap<>();
private String className;
- MojoFieldVisitor( Logger logger, String fieldName, String className )
+ MojoFieldVisitor( String fieldName, String className )
{
super( Opcodes.ASM9 );
- this.logger = logger;
this.fieldName = fieldName;
this.className = className;
}
+ @Override
public Map getAnnotationVisitorMap()
{
return annotationVisitorMap;
}
+ @Override
public String getFieldName()
{
return fieldName;
@@ -71,30 +70,14 @@ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
{
return null;
}
- MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( logger, annotationClassName );
+ MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( annotationClassName );
annotationVisitorMap.put( annotationClassName, mojoAnnotationVisitor );
return mojoAnnotationVisitor;
}
@Override
- public void visitAttribute( Attribute attribute )
- {
- // no op
- }
-
- @Override
- public void visitEnd()
- {
- // no op
- }
-
public String getClassName()
{
return className;
}
-
- public void setClassName( String className )
- {
- this.className = className;
- }
}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoMethodVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoMethodVisitor.java
new file mode 100644
index 000000000..448bb7880
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoMethodVisitor.java
@@ -0,0 +1,81 @@
+package org.apache.maven.tools.plugin.extractor.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 java.util.HashMap;
+import java.util.Map;
+
+import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+/**
+ * Method visitor.
+ *
+ * @author Slawomir Jaranowski
+ */
+public class MojoMethodVisitor extends MethodVisitor implements MojoParameterVisitor
+{
+ private final String className;
+ private final String fieldName;
+
+ private Map annotationVisitorMap = new HashMap<>();
+
+ public MojoMethodVisitor( String fieldName, String className )
+ {
+ super( Opcodes.ASM9 );
+ this.fieldName = fieldName;
+ this.className = className;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation( String desc, boolean visible )
+ {
+ String annotationClassName = Type.getType( desc ).getClassName();
+ if ( !MojoAnnotationsScanner.METHOD_LEVEL_ANNOTATIONS.contains( annotationClassName ) )
+ {
+ return null;
+ }
+
+ MojoAnnotationVisitor mojoAnnotationVisitor = new MojoAnnotationVisitor( annotationClassName );
+ annotationVisitorMap.put( annotationClassName, mojoAnnotationVisitor );
+ return mojoAnnotationVisitor;
+ }
+
+ @Override
+ public String getFieldName()
+ {
+ return fieldName;
+ }
+
+ @Override
+ public String getClassName()
+ {
+ return className;
+ }
+
+ @Override
+ public Map getAnnotationVisitorMap()
+ {
+ return annotationVisitorMap;
+ }
+}
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoParameterVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoParameterVisitor.java
new file mode 100644
index 000000000..c95ac05c2
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoParameterVisitor.java
@@ -0,0 +1,36 @@
+package org.apache.maven.tools.plugin.extractor.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 java.util.Map;
+
+/**
+ * Common interface for field and method visitors.
+ *
+ * @author Slawomir Jaranowski
+ */
+public interface MojoParameterVisitor
+{
+ String getFieldName();
+
+ String getClassName();
+
+ Map getAnnotationVisitorMap();
+}
diff --git a/maven-plugin-tools-annotations/src/site/apt/index.apt b/maven-plugin-tools-annotations/src/site/apt/index.apt
index 7f86885b9..a46c37101 100644
--- a/maven-plugin-tools-annotations/src/site/apt/index.apt
+++ b/maven-plugin-tools-annotations/src/site/apt/index.apt
@@ -118,6 +118,15 @@ public class MyMojo
@Parameter( defaultValue = "${project.build.directory}", readonly = true )
private File target;
+ /**
+ * @Parameter for methods can be used only with public setter methods
+ */
+ @Parameter( ... )
+ public setOutput( File output )
+ {
+ ...
+ }
+
public void execute()
{
...
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java
index 36dd97379..c044d161e 100644
--- a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/FooMojo.java
@@ -19,6 +19,8 @@
* under the License.
*/
+import java.util.List;
+
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
@@ -57,6 +59,45 @@ public class FooMojo
@Parameter( property = "thebeer", defaultValue = "coolbeer" )
protected String beer;
+ /**
+ * setter as parameter.
+ */
+ @Parameter( property = "props.paramFromSetter" )
+ public void setParamFromSetter(String value)
+ {
+ // empty
+ }
+
+ /**
+ * add method as parameter.
+ */
+ @Parameter( property = "props.paramFromAdd" )
+ public void addParamFromAdd(String value)
+ {
+ // empty
+ }
+
+ /**
+ * deprecated setter as parameter.
+ *
+ * @deprecated reason of deprecation
+ */
+ @Deprecated
+ @Parameter( property = "props.paramFromSetterDeprecated" )
+ public void setParamFromSetterDeprecated( List value)
+ {
+ // empty
+ }
+
+ /**
+ * Static methods should be excluded.
+ */
+ @Parameter
+ public static void setStaticMethod( String value )
+ {
+ // empty
+ }
+
/**
*
*/
@@ -69,4 +110,10 @@ public void execute()
{
// nothing
}
+
+ @Deprecated
+ public void deprecatedMethod(String value)
+ {
+
+ }
}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java
index 797f46e7b..81796881c 100644
--- a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java
@@ -25,6 +25,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import org.apache.maven.plugins.annotations.Execute;
@@ -94,8 +95,8 @@ void testReadMojoClass()
Collection parameters = mojoAnnotatedClass.getParameters().values();
assertThat( parameters ).isNotNull()
.isNotEmpty()
- .hasSize( 3 )
- .contains(
+ .hasSize( 6 )
+ .containsExactlyInAnyOrder(
new ParameterAnnotationContent( "bar", null, "thebar", "coolbar", null, true, false,
String.class.getName() ),
new ParameterAnnotationContent( "beer", null, "thebeer", "coolbeer", null, false, false,
@@ -103,7 +104,19 @@ void testReadMojoClass()
new ParameterAnnotationContent( "fooInterface", null, "fooInterface", null,
FooInterfaceImpl.class,
false,
- false, FooInterface.class.getName() )
+ false, FooInterface.class.getName() ),
+ new ParameterAnnotationContent( "paramFromSetter", null, "props.paramFromSetter", null,
+ null,
+ false,
+ false, String.class.getName() ),
+ new ParameterAnnotationContent( "paramFromAdd", null, "props.paramFromAdd", null,
+ null,
+ false,
+ false, String.class.getName() ),
+ new ParameterAnnotationContent( "paramFromSetterDeprecated", null, "props.paramFromSetterDeprecated", null,
+ null,
+ false,
+ false, List.class.getName() )
);
}
}