[MPLUGIN-189] commit some stuff on annotation scanning

git-svn-id: https://svn.apache.org/repos/asf/maven/plugin-tools/branches/MPLUGIN-189@1333835 13f79535-47bb-0310-9956-ffa450edef68
master
Olivier Lamy 2012-05-04 09:59:49 +00:00
parent 8c108af423
commit 7e10f5b09f
14 changed files with 1580 additions and 1 deletions

View File

@ -11,4 +11,44 @@
<name>Maven Plugin Tools Annotations</name>
<dependencies>
<!-- maven -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-descriptor</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-tools-api</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-commons</artifactId>
<version>3.3.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,61 @@
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.DependencyResolutionRequiredException;
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.project.MavenProject;
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.extractor.MojoDescriptorExtractor;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import java.util.List;
/**
* @author Olivier Lamy
*/
public class JavaAnnotationsMojoDescriptorExtractor
extends AbstractLogEnabled
implements MojoDescriptorExtractor
{
public List<MojoDescriptor> execute( MavenProject project, PluginDescriptor pluginDescriptor )
throws ExtractionException, InvalidPluginDescriptorException
{
return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) );
}
public List<MojoDescriptor> execute( PluginToolsRequest request )
throws ExtractionException, InvalidPluginDescriptorException
{
try
{
List<String> classpathElements = request.getProject().getCompileClasspathElements();
return null; //To change body of implemented methods use File | Settings | File Templates.
}
catch ( DependencyResolutionRequiredException e )
{
throw new ExtractionException( e.getMessage(), e );
}
}
}

View File

@ -0,0 +1,52 @@
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.
*/
/**
* @author Olivier Lamy
*/
public class AnnotatedField
{
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();
}
}

View File

@ -0,0 +1,84 @@
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.tools.plugin.annotations.Component;
import java.lang.annotation.Annotation;
/**
* @author Olivier Lamy
*/
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;
}
public void role( String role )
{
this.role = role;
}
public String roleHint()
{
return 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();
}
}

View File

@ -0,0 +1,204 @@
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.tools.plugin.annotations.Component;
import org.apache.maven.tools.plugin.annotations.Execute;
import org.apache.maven.tools.plugin.annotations.Mojo;
import org.apache.maven.tools.plugin.annotations.Parameter;
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.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.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author Olivier Lamy
*/
public class DefaultMojoAnnotationsScanner
extends AbstractLogEnabled
implements MojoAnnotationsScanner
{
private Reflector reflector = new Reflector();
public List<MojoAnnotatedClass> scan( MojoAnnotationsScannerRequest request )
throws ExtractionException
{
List<MojoAnnotatedClass> mojoAnnotatedClasses = new ArrayList<MojoAnnotatedClass>();
try
{
for ( File classDirectory : request.getClassesDirectories() )
{
mojoAnnotatedClasses.addAll( scanDirectory( classDirectory, request.getIncludePatterns() ) );
}
return mojoAnnotatedClasses;
}
catch ( IOException e )
{
throw new ExtractionException( e.getMessage(), e );
}
}
protected List<MojoAnnotatedClass> scanDirectory( File classDirectory, List<String> includePatterns )
throws IOException, ExtractionException
{
List<MojoAnnotatedClass> mojoAnnotatedClasses = new ArrayList<MojoAnnotatedClass>();
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 ( isMojoAnnnotatedClassCandidate( mojoClassVisitor.getMojoAnnotatedClass() ) != null )
{
mojoAnnotatedClasses.add( 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
{
MojoClassVisitor.MojoAnnotationVisitor mojoAnnotationVisitor =
mojoClassVisitor.getAnnotationVisitorMap().get( Mojo.class.getName() );
if ( mojoAnnotationVisitor != null )
{
MojoClassVisitor.MojoAnnotationContent mojoAnnotationContent =
new MojoClassVisitor.MojoAnnotationContent();
Class clazz = Thread.currentThread().getContextClassLoader().loadClass(
MojoClassVisitor.MojoAnnotationContent.class.getName() );
for ( Map.Entry<String, Object> 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 )
{
MojoClassVisitor.ExecuteAnnotationContent executeAnnotationContent =
new MojoClassVisitor.ExecuteAnnotationContent();
Class clazz = Thread.currentThread().getContextClassLoader().loadClass(
MojoClassVisitor.MojoAnnotationContent.class.getName() );
for ( Map.Entry<String, Object> entry : mojoAnnotationVisitor.getAnnotationValues().entrySet() )
{
reflector.invoke( executeAnnotationContent, entry.getKey(), new Object[]{ entry.getValue() } );
}
mojoClassVisitor.getMojoAnnotatedClass().setExecute( executeAnnotationContent );
}
List<MojoClassVisitor.MojoFieldVisitor> mojoFieldVisitors =
mojoClassVisitor.findFieldWithAnnotationClass( Parameter.class.getName() );
for ( MojoClassVisitor.MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
{
ParameterAnnotationContent parameterAnnotationContent =
new ParameterAnnotationContent( mojoFieldVisitor.getFieldName() );
if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null )
{
for ( Map.Entry<String, Object> entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() )
{
reflector.invoke( parameterAnnotationContent, entry.getKey(),
new Object[]{ entry.getValue() } );
}
}
mojoClassVisitor.getMojoAnnotatedClass().getParameters().add( parameterAnnotationContent );
}
mojoFieldVisitors = mojoClassVisitor.findFieldWithAnnotationClass( Component.class.getName() );
for ( MojoClassVisitor.MojoFieldVisitor mojoFieldVisitor : mojoFieldVisitors )
{
ComponentAnnotationContent componentAnnotationContent =
new ComponentAnnotationContent( mojoFieldVisitor.getFieldName() );
if ( mojoFieldVisitor.getMojoAnnotationVisitor() != null )
{
for ( Map.Entry<String, Object> entry : mojoFieldVisitor.getMojoAnnotationVisitor().getAnnotationValues().entrySet() )
{
reflector.invoke( componentAnnotationContent, entry.getKey(),
new Object[]{ entry.getValue() } );
}
}
mojoClassVisitor.getMojoAnnotatedClass().getComponents().add( componentAnnotationContent );
}
}
catch ( Exception e )
{
throw new ExtractionException( e.getMessage(), e );
}
}
}

View File

@ -0,0 +1,138 @@
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.tools.plugin.annotations.Execute;
import org.apache.maven.tools.plugin.annotations.Mojo;
import java.util.ArrayList;
import java.util.List;
/**
* @author Olivier Lamy
*/
public class MojoAnnotatedClass
{
private String className;
private String parentClassName;
private Mojo mojo;
private Execute execute;
private List<ParameterAnnotationContent> parameters;
private List<ComponentAnnotationContent> components;
public MojoAnnotatedClass()
{
// no op
}
public String getClassName()
{
return className;
}
public MojoAnnotatedClass setClassName( String className )
{
this.className = className;
return this;
}
public Mojo getMojo()
{
return mojo;
}
public MojoAnnotatedClass setMojo( Mojo mojo )
{
this.mojo = mojo;
return this;
}
public Execute getExecute()
{
return execute;
}
public MojoAnnotatedClass setExecute( Execute execute )
{
this.execute = execute;
return this;
}
public List<ParameterAnnotationContent> getParameters()
{
if ( this.parameters == null )
{
this.parameters = new ArrayList<ParameterAnnotationContent>();
}
return parameters;
}
public MojoAnnotatedClass setParameters( List<ParameterAnnotationContent> parameters )
{
this.parameters = parameters;
return this;
}
public List<ComponentAnnotationContent> getComponents()
{
if ( this.components == null )
{
this.components = new ArrayList<ComponentAnnotationContent>();
}
return components;
}
public MojoAnnotatedClass setComponents( List<ComponentAnnotationContent> components )
{
this.components = components;
return this;
}
public String getParentClassName()
{
return parentClassName;
}
public MojoAnnotatedClass setParentClassName( String parentClassName )
{
this.parentClassName = parentClassName;
return this;
}
@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();
}
}

View File

@ -0,0 +1,45 @@
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.tools.plugin.annotations.Component;
import org.apache.maven.tools.plugin.annotations.Execute;
import org.apache.maven.tools.plugin.annotations.Mojo;
import org.apache.maven.tools.plugin.annotations.Parameter;
import org.apache.maven.tools.plugin.extractor.ExtractionException;
import java.util.Arrays;
import java.util.List;
/**
* @author Olivier Lamy
*/
public interface MojoAnnotationsScanner
{
String ROLE = MojoAnnotationsScanner.class.getName();
static final List<String> acceptedClassLevelAnnotationClasses =
Arrays.asList( Mojo.class.getName(), Execute.class.getName() );
static final List<String> acceptedFieldLevelAnnotationClasses =
Arrays.asList( Parameter.class.getName(), Component.class.getName() );
List<MojoAnnotatedClass> scan( MojoAnnotationsScannerRequest request )
throws ExtractionException;
}

View File

@ -0,0 +1,71 @@
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 java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Olivier Lamy
*/
public class MojoAnnotationsScannerRequest
{
private List<File> classesDirectories = new ArrayList<File>();
private List<File> dependencies = new ArrayList<File>();
private List<String> includePatterns = Arrays.asList( "**/*.class" );
public MojoAnnotationsScannerRequest()
{
// no o
}
public List<File> getClassesDirectories()
{
return classesDirectories;
}
public void setClassesDirectories( List<File> classesDirectories )
{
this.classesDirectories = classesDirectories;
}
public List<File> getDependencies()
{
return dependencies;
}
public void setDependencies( List<File> dependencies )
{
this.dependencies = dependencies;
}
public List<String> getIncludePatterns()
{
return includePatterns;
}
public void setIncludePatterns( List<String> includePatterns )
{
this.includePatterns = includePatterns;
}
}

View File

@ -0,0 +1,524 @@
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.tools.plugin.annotations.Execute;
import org.apache.maven.tools.plugin.annotations.LifecyclePhase;
import org.apache.maven.tools.plugin.annotations.Mojo;
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.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Olivier Lamy
*/
public class MojoClassVisitor
implements ClassVisitor
{
private Logger logger;
private MojoAnnotatedClass mojoAnnotatedClass;
private Map<String, MojoAnnotationVisitor> annotationVisitorMap = new HashMap<String, MojoAnnotationVisitor>();
private List<MojoFieldVisitor> fieldVisitors = new ArrayList<MojoFieldVisitor>();
public MojoClassVisitor( Logger logger )
{
this.logger = logger;
}
public MojoAnnotatedClass getMojoAnnotatedClass()
{
return mojoAnnotatedClass;
}
public void setMojoAnnotatedClass( MojoAnnotatedClass mojoAnnotatedClass )
{
this.mojoAnnotatedClass = mojoAnnotatedClass;
}
public Map<String, MojoAnnotationVisitor> getAnnotationVisitorMap()
{
return annotationVisitorMap;
}
public void setAnnotationVisitorMap( Map<String, MojoAnnotationVisitor> annotationVisitorMap )
{
this.annotationVisitorMap = annotationVisitorMap;
}
public List<MojoFieldVisitor> getFieldVisitors()
{
return fieldVisitors;
}
public void setFieldVisitors( List<MojoFieldVisitor> fieldVisitors )
{
this.fieldVisitors = fieldVisitors;
}
public List<MojoFieldVisitor> findFieldWithAnnotationClass( String annotationClassName )
{
List<MojoFieldVisitor> mojoFieldVisitors = new ArrayList<MojoFieldVisitor>();
for ( MojoFieldVisitor mojoFieldVisitor : this.fieldVisitors )
{
MojoAnnotationVisitor mojoAnnotationVisitor = mojoFieldVisitor.getMojoAnnotationVisitor();
if ( mojoAnnotationVisitor != null && StringUtils.equals( annotationClassName,
mojoAnnotationVisitor.annotationClassName ) )
{
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 )
{
// Type.getType( desc ).getClassName()
logger.debug( "MojoClassVisitor#visitField" );
MojoFieldVisitor mojoFieldVisitor = new MojoFieldVisitor( logger, name );
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" );
}
public static class MojoAnnotationContent
implements Mojo
{
private String name;
private LifecyclePhase defaultPhase = LifecyclePhase.NONE;
private String requiresDependencyResolution = "runtime";
private String requiresDependencyCollection = "runtime";
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;
}
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();
}
}
public static 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();
}
}
//-------------------------------------
// internal classes
//-------------------------------------
static class MojoAnnotationVisitor
implements AnnotationVisitor
{
private Logger logger;
private String annotationClassName;
private Map<String, Object> annotationValues = new HashMap<String, Object>();
MojoAnnotationVisitor( Logger logger, String annotationClassName )
{
this.logger = logger;
this.annotationClassName = annotationClassName;
}
public Map<String, Object> 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" );
}
}
static class MojoFieldVisitor
implements FieldVisitor
{
private Logger logger;
private String fieldName;
private MojoAnnotationVisitor mojoAnnotationVisitor;
MojoFieldVisitor( Logger logger, String fieldName )
{
this.logger = logger;
this.fieldName = fieldName;
}
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" );
}
}
}

View File

@ -0,0 +1,184 @@
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.tools.plugin.annotations.Parameter;
import java.lang.annotation.Annotation;
/**
* @author Olivier Lamy
*/
public class ParameterAnnotationContent
extends AnnotatedField
implements Parameter
{
private String alias;
private String expression;
private String defaultValue;
private boolean required = false;
private boolean readonly = false;
public ParameterAnnotationContent( String fieldName )
{
super( fieldName );
}
public ParameterAnnotationContent( String fieldName, String alias, String expression, String defaultValue,
boolean required, boolean readonly )
{
this( fieldName );
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;
}
@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;
}
}

View File

@ -0,0 +1,42 @@
<!--
~ 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.
-->
<component-set>
<components>
<!--
|
| JavaMojoDescriptorExtractor, a MojoDescriptor extractor to read
| descriptors from java classes with annotations.
|
-->
<component>
<role>org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor</role>
<role-hint>java-annotations</role-hint>
<implementation>org.apache.maven.tools.plugin.annotations.JavaAnnotationsMojoDescriptorExtractor</implementation>
</component>
<component>
<role>org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.tools.plugin.annotations.scanner.DefaultMojoAnnotationsScanner</implementation>
</component>
</components>
</component-set>

View File

@ -0,0 +1,50 @@
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.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
* @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
{
@Parameter( expression = "${thebar}" )
private String bar;
@Parameter( expression = "${thebeer}" )
private String beer;
@Component( role = "wine", roleHint = "bordeaux" )
private Mojo wine;
@Component( role = "wine", roleHint = "foo" )
private Mojo foo;
public void execute()
throws MojoExecutionException, MojoFailureException
{
// nothing
}
}

View File

@ -0,0 +1,78 @@
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.tools.plugin.annotations.scanner.ComponentAnnotationContent;
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.annotations.scanner.ParameterAnnotationContent;
import org.codehaus.plexus.PlexusTestCase;
import org.fest.assertions.Assertions;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @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" ) );
List<MojoAnnotatedClass> mojoAnnotatedClasses = mojoAnnotationsScanner.scan( request );
System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses );
Assertions.assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 );
MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.get( 0 );
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() );
List<ComponentAnnotationContent> components = mojoAnnotatedClass.getComponents();
Assertions.assertThat( components ).isNotNull().isNotEmpty().hasSize( 2 );
List<ParameterAnnotationContent> parameters = mojoAnnotatedClass.getParameters();
Assertions.assertThat( parameters ).isNotNull().isNotEmpty().hasSize( 2 ).contains(
new ParameterAnnotationContent( "bar", null, "${thebar}", null, false, false ),
new ParameterAnnotationContent( "beer", null, "${thebeer}", null, false, false ) );
}
}

View File

@ -215,7 +215,7 @@
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>2.0.5</version>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
@ -239,6 +239,12 @@
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>