From d85b22ec88011ad710dca34a7f7237e553a03896 Mon Sep 17 00:00:00 2001 From: Olivier Lamy Date: Wed, 9 May 2012 16:45:26 +0000 Subject: [PATCH] [MPLUGIN-189] scan sources from dependencies if sources classifier found to get @since,@deprecated and text git-svn-id: https://svn.apache.org/repos/asf/maven/plugin-tools/branches/MPLUGIN-189@1336291 13f79535-47bb-0310-9956-ffa450edef68 --- maven-plugin-plugin/pom.xml | 5 + .../invoker.properties | 5 + .../pom.xml | 109 +++++++++++++ .../apache/maven/plugin/coreit/FirstMojo.java | 73 +++++++++ .../resources/META-INF/maven/lifecycle.xml | 17 ++ .../verify.groovy | 75 +++++++++ .../plugin/plugin/AbstractGeneratorMojo.java | 57 +++++-- maven-plugin-tools-annotations/pom.xml | 5 + ...avaAnnotationsMojoDescriptorExtractor.java | 154 ++++++++++++++++-- .../resources/META-INF/plexus/components.xml | 12 ++ .../tools/plugin/annotations/FooMojo.java | 1 - .../plugin/DefaultPluginToolsRequest.java | 28 ++++ .../tools/plugin/PluginToolsRequest.java | 35 +++- pom.xml | 5 + 14 files changed, 550 insertions(+), 31 deletions(-) create mode 100644 maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties create mode 100644 maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml create mode 100644 maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java create mode 100644 maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml create mode 100644 maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy diff --git a/maven-plugin-plugin/pom.xml b/maven-plugin-plugin/pom.xml index fb90486..1b99f8b 100644 --- a/maven-plugin-plugin/pom.xml +++ b/maven-plugin-plugin/pom.xml @@ -106,6 +106,11 @@ plexus-utils 2.0.5 + + org.codehaus.plexus + plexus-archiver + 2.1.1 + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties new file mode 100644 index 0000000..98d7b19 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/invoker.properties @@ -0,0 +1,5 @@ +invoker.goals.1 = install +invoker.goals.2 = org.apache.maven.its.annotation-with-inheritance-from-deps:annotation-with-inheritance-from-deps:1.0:first +#FIXME disabled need to find a solution for the chicken and eggs issue. +#help sources are generated @generated-sources but need descriptor which need compile phase first for classes scanning +#invoker.goals.3 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0::help diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml new file mode 100644 index 0000000..5158139 --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/pom.xml @@ -0,0 +1,109 @@ + + + + + + 4.0.0 + + org.apache.maven.its.annotation-with-inheritance-from-deps + annotation-with-inheritance-from-deps + 1.0 + maven-plugin + + Maven Integration Test :: annotation-with-inheritance-from-deps + + Test plugin-plugin, which tests maven-plugin-tools-api and + maven-plugin-tools-java. This will generate a plugin descriptor from + java-based mojo sources, install the plugin, and then use it. + + + + UTF-8 + 1.8.6 + + + + + org.apache.maven + maven-plugin-api + 2.0 + + + org.apache.maven + maven-project + @mavenVersion@ + + + org.apache.maven.plugin-tools + maven-plugin-annotations + @project.version@ + + + org.apache.maven.plugin-tools + maven-plugin-tools-annotations + @project.version@ + tests + + + org.codehaus.plexus + plexus-compiler-manager + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + org.codehaus.plexus + plexus-compiler-javac + ${plexusCompilerVersion} + + + org.codehaus.plexus + plexus-component-api + + + + + + + + + org.apache.maven.plugins + maven-plugin-plugin + @project.version@ + + true + + + + mojo-descriptor + process-classes + + descriptor + + + + + + + diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java new file mode 100644 index 0000000..167f30e --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/java/org/apache/maven/plugin/coreit/FirstMojo.java @@ -0,0 +1,73 @@ +package org.apache.maven.plugin.coreit; + +/* + * 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.MojoExecutionException; +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.apache.maven.tools.plugin.annotations.FooMojo; + +/** + * Touches a test file. + * + * @since 1.2 + * @deprecated Don't use! + */ +@Mojo( name = "first", requiresDependencyResolution = "test", defaultPhase = LifecyclePhase.INTEGRATION_TEST ) +public class FirstMojo + extends FooMojo +{ + + /** + * @since 0.1 + * @deprecated As of 0.2 + */ + @Parameter( alias = "alias" ) + private String aliasedParam; + + @Component( role = "org.apache.maven.project.MavenProjectHelper", roleHint = "default" ) + private Object projectHelper; + + public void execute() + throws MojoExecutionException + { + if (bar == null) + { + throw new MojoExecutionException( "bar == null" ); + } + if (beer == null) + { + throw new MojoExecutionException( "beer == null" ); + } + if ( projectHelper == null ) + { + throw new MojoExecutionException( "projectHelper == null" ); + } + if ( compilerManager == null ) + { + throw new MojoExecutionException( "compilerManager == null" ); + } + + } + +} diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml new file mode 100644 index 0000000..7b21d5a --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/src/main/resources/META-INF/maven/lifecycle.xml @@ -0,0 +1,17 @@ + + + my-lifecycle + + + process-classes + + + test + + ${project.build.directory}/generated-classes/cobertura + true + + + + + \ No newline at end of file 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 new file mode 100644 index 0000000..9e047fa --- /dev/null +++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy @@ -0,0 +1,75 @@ + +File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" ); +assert descriptorFile.isFile() + +def pluginDescriptor = new XmlParser().parse( descriptorFile ); + +def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first"}[0] + +assert mojo.goal.text() == 'first' +assert mojo.implementation.text() == 'org.apache.maven.plugin.coreit.FirstMojo' +assert mojo.language.text() == 'java' +assert mojo.description.text() == 'Touches a test file.' +assert mojo.deprecated.text() == "Don't use!" +assert mojo.requiresDependencyResolution.text() == 'test' +assert mojo.requiresDependencyCollection.text() == '' +assert mojo.requiresProject.text() == 'true' +assert mojo.requiresOnline.text() == 'false' +assert mojo.requiresDirectInvocation.text() == 'false' +assert mojo.aggregator.text() == 'false' +assert mojo.threadSafe.text() == 'false' +assert mojo.phase.text() == 'integration-test' +assert mojo.executePhase.text() == 'package' +assert mojo.executeLifecycle.text() == 'my-lifecycle' + +assert mojo.configuration.bar[0].text() == '${thebar}' +assert mojo.configuration.bar[0].'@implementation' == 'java.lang.String' +assert mojo.configuration.bar[0].'@default-value' == 'coolbar' + +assert mojo.configuration.beer[0].text() == '${thebeer}' +assert mojo.configuration.beer[0].'@implementation' == 'java.lang.String' +assert mojo.configuration.beer[0].'@default-value' == 'coolbeer' + +assert mojo.requirements.requirement.size() == 3 + +assert mojo.requirements.requirement[1].role.text() == 'org.codehaus.plexus.compiler.manager.CompilerManager' +assert mojo.requirements.requirement[1].'role-hint'.text() == '' +assert mojo.requirements.requirement[1].'field-name'.text() == 'compilerManager' + +assert mojo.requirements.requirement[2].role.text() == 'org.apache.maven.project.MavenProjectHelper' +assert mojo.requirements.requirement[2].'role-hint'.text() == 'default' +assert mojo.requirements.requirement[2].'field-name'.text() == 'projectHelper' + +assert mojo.parameters.parameter.size() == 3 + +def parameter = mojo.parameters.parameter.findAll{ it.name.text() == "aliasedParam"}[0] + +assert parameter.name.text() == 'aliasedParam' +assert parameter.alias.text() == 'alias' +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == 'As of 0.2' +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == '' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "beer"}[0] + +assert parameter.name.text() == 'beer' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.text() == "wine is better" +assert parameter.required.text() == 'false' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == 'beer for non french folks' + +parameter = mojo.parameters.parameter.findAll{ it.name.text() == "bar"}[0] + +assert parameter.name.text() == 'bar' +assert parameter.alias.isEmpty() +assert parameter.type.text() == 'java.lang.String' +assert parameter.deprecated.isEmpty() +assert parameter.required.text() == 'true' +assert parameter.editable.text() == 'true' +assert parameter.description.text() == 'the cool bar to go' + +return true; diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java index 085bf15..3a66ffe 100644 --- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java +++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/AbstractGeneratorMojo.java @@ -20,6 +20,7 @@ package org.apache.maven.plugin.plugin; */ import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; @@ -35,6 +36,7 @@ import org.codehaus.plexus.util.ReaderFactory; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.Set; /** @@ -42,7 +44,6 @@ import java.util.Set; * * @author Jason van Zyl * @version $Id$ - * * @threadSafe */ public abstract class AbstractGeneratorMojo @@ -67,7 +68,7 @@ public abstract class AbstractGeneratorMojo /** * The file encoding of the source files. - * + * * @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}" * @since 2.5 */ @@ -84,6 +85,7 @@ public abstract class AbstractGeneratorMojo * 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 + * * @parameter expression="${maven.plugin.skipErrorNoDescriptorsFound}" default-value="false" * @since 3.0 */ @@ -100,12 +102,12 @@ public abstract class AbstractGeneratorMojo *
      *  <!-- Use all mojo extractors -->
      *  <extractors/>
-     *  
+     *
      *  <!-- Use no mojo extractors -->
      *  <extractors>
      *      <extractor/>
      *  </extractors>
-     *  
+     *
      *  <!-- Use only bsh mojo extractor -->
      *  <extractors>
      *      <extractor>bsh</extractor>
@@ -134,6 +136,26 @@ public abstract class AbstractGeneratorMojo
      */
     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.
      */
@@ -144,7 +166,9 @@ public abstract class AbstractGeneratorMojo
      */
     protected abstract Generator createGenerator();
 
-    /** {@inheritDoc} */
+    /**
+     * {@inheritDoc}
+     */
     public void execute()
         throws MojoExecutionException
     {
@@ -158,11 +182,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" );
@@ -176,8 +200,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 );
@@ -200,21 +224,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 );
 
@@ -239,7 +265,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-tools-annotations/pom.xml b/maven-plugin-tools-annotations/pom.xml
index b8d8705..c2fdcf8 100644
--- a/maven-plugin-tools-annotations/pom.xml
+++ b/maven-plugin-tools-annotations/pom.xml
@@ -72,6 +72,11 @@
       3.3.1
     
 
+    
+      org.codehaus.plexus
+      plexus-archiver
+    
+
     
       com.thoughtworks.qdox
       qdox
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
index 48a7d1b..3ec1c72 100644
--- 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
@@ -23,6 +23,10 @@ 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;
@@ -41,6 +45,9 @@ 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;
 
@@ -50,8 +57,10 @@ 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;
 
@@ -69,6 +78,21 @@ public class JavaAnnotationsMojoDescriptorExtractor
      */
     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
     {
@@ -95,6 +119,9 @@ public class JavaAnnotationsMojoDescriptorExtractor
         // 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(),
@@ -106,11 +133,31 @@ public class JavaAnnotationsMojoDescriptorExtractor
                 {
                     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 ) );
@@ -120,10 +167,59 @@ public class JavaAnnotationsMojoDescriptorExtractor
 
         populateDataFromJavadoc( mojoAnnotatedClasses, javaClassesMap );
 
-        return toMojoDescriptors( mojoAnnotatedClasses, request );
+        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() );
+        }
+        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.
      *
@@ -155,8 +251,13 @@ public class JavaAnnotationsMojoDescriptorExtractor
                         mojoAnnotationContent.setDeprecated( deprecated.getValue() );
                     }
                 }
-                Map fieldsMap = extractFieldParameterTags( javaClass );
-                for ( Map.Entry parameter : entry.getValue().getParameters().entrySet() )
+                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 )
@@ -206,7 +307,7 @@ public class JavaAnnotationsMojoDescriptorExtractor
      * @param tagName   not null
      * @return docletTag instance
      */
-    private static DocletTag findInClassHierarchy( JavaClass javaClass, String tagName )
+    private DocletTag findInClassHierarchy( JavaClass javaClass, String tagName )
     {
         DocletTag tag = javaClass.getTagByName( tagName );
 
@@ -229,9 +330,11 @@ public class JavaAnnotationsMojoDescriptorExtractor
      * @param javaClass not null
      * @return map with Mojo parameters names as keys
      */
-    private Map extractFieldParameterTags( JavaClass javaClass )
+    private Map extractFieldParameterTags( JavaClass javaClass,
+                                                              Map javaClassesMap,
+                                                              Map mojoAnnotatedClasses )
     {
-        Map rawParams;
+        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...
@@ -239,10 +342,20 @@ public class JavaAnnotationsMojoDescriptorExtractor
 
         if ( superClass != null )
         {
-            rawParams = extractFieldParameterTags( superClass );
+            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();
         }
 
@@ -265,12 +378,11 @@ public class JavaAnnotationsMojoDescriptorExtractor
 
     protected Map discoverClasses( final String encoding, final MavenProject project )
     {
-        JavaDocBuilder builder = new JavaDocBuilder();
-        builder.setEncoding( encoding );
+        List sources = new ArrayList();
 
         for ( String source : (List) project.getCompileSourceRoots() )
         {
-            builder.addSourceTree( new File( source ) );
+            sources.add( new File( source ) );
         }
 
         // TODO be more dynamic
@@ -278,7 +390,20 @@ public class JavaAnnotationsMojoDescriptorExtractor
         if ( !project.getCompileSourceRoots().contains( generatedPlugin.getAbsolutePath() )
             && generatedPlugin.exists() )
         {
-            builder.addSourceTree( generatedPlugin );
+            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();
@@ -298,9 +423,8 @@ public class JavaAnnotationsMojoDescriptorExtractor
         return javaClassMap;
     }
 
-
     private List toMojoDescriptors( Map mojoAnnotatedClasses,
-                                                    PluginToolsRequest request )
+                                                    PluginToolsRequest request, Map javaClassesMap )
         throws DuplicateParameterException
     {
         List mojoDescriptors = new ArrayList( mojoAnnotatedClasses.size() );
@@ -367,6 +491,7 @@ public class JavaAnnotationsMojoDescriptorExtractor
                 parameter.setEditable( !parameterAnnotationContent.readonly() );
                 parameter.setExpression( parameterAnnotationContent.expression() );
                 parameter.setType( parameterAnnotationContent.getClassName() );
+                parameter.setSince( parameterAnnotationContent.getSince() );
                 parameter.setRequired( parameterAnnotationContent.required() );
 
                 mojoDescriptor.addParameter( parameter );
@@ -385,7 +510,8 @@ public class JavaAnnotationsMojoDescriptorExtractor
                 parameter.setRequirement(
                     new Requirement( componentAnnotationContent.role(), componentAnnotationContent.roleHint() ) );
                 parameter.setEditable( false );
-
+                parameter.setDeprecated( componentAnnotationContent.getDeprecated() );
+                parameter.setSince( componentAnnotationContent.getSince() );
                 mojoDescriptor.addParameter( parameter );
             }
 
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
index 91df740..18fb315 100644
--- 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
@@ -35,6 +35,18 @@
           org.apache.maven.tools.plugin.annotations.scanner.MojoAnnotationsScanner
           default
         
+        
+          org.apache.maven.artifact.resolver.ArtifactResolver
+          default
+        
+        
+          org.apache.maven.artifact.factory.ArtifactFactory
+          default
+        
+        
+          org.codehaus.plexus.archiver.manager.ArchiverManager
+          default
+        
       
     
 
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
index 68021ae..1f9da50 100644
--- 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
@@ -40,7 +40,6 @@ public class FooMojo
     /**
      * the cool bar to go
      * @since 1.0
-     *
      */
     @Parameter( expression = "${thebar}", required = true, defaultValue = "coolbar" )
     protected String bar;
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java
index 73ef0fc..9c70400 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java
@@ -20,6 +20,7 @@ package org.apache.maven.tools.plugin;
  */
 
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.project.MavenProject;
@@ -27,6 +28,7 @@ import org.codehaus.plexus.util.ReaderFactory;
 import org.codehaus.plexus.util.StringUtils;
 
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -52,6 +54,10 @@ public class DefaultPluginToolsRequest
 
     private Set dependencies;
 
+    private List remoteRepos;
+
+    private ArtifactRepository local;
+
     public DefaultPluginToolsRequest( MavenProject project, PluginDescriptor pluginDescriptor )
     {
         this.project = project;
@@ -148,4 +154,26 @@ public class DefaultPluginToolsRequest
         this.dependencies = dependencies;
         return this;
     }
+
+    public List getRemoteRepos()
+    {
+        return remoteRepos;
+    }
+
+    public PluginToolsRequest setRemoteRepos( List remoteRepos )
+    {
+        this.remoteRepos = remoteRepos;
+        return this;
+    }
+
+    public ArtifactRepository getLocal()
+    {
+        return local;
+    }
+
+    public PluginToolsRequest setLocal( ArtifactRepository local )
+    {
+        this.local = local;
+        return this;
+    }
 }
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java
index 0cdf998..03fe386 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java
@@ -20,10 +20,12 @@ package org.apache.maven.tools.plugin;
  */
 
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.project.MavenProject;
 
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -90,16 +92,47 @@ public interface PluginToolsRequest
 
     /**
      * Returns the list of {@link Artifact} used in class path scanning for annotations
+     *
      * @return
      * @since 3.0
      */
     Set getDependencies();
 
     /**
-     *
      * @param dependencies
      * @return
+     * @since 3.0
      */
     PluginToolsRequest setDependencies( Set dependencies );
 
+    /**
+     *
+     * @return
+     * @since 3.0
+     */
+    List getRemoteRepos();
+
+    /**
+     *
+     * @param remoteRepos
+     * @return
+     * @since 3.0
+     */
+    PluginToolsRequest setRemoteRepos( List remoteRepos );
+
+    /**
+     *
+     * @return
+     * @since 3.0
+     */
+    ArtifactRepository getLocal();
+
+    /**
+     *
+     * @param local
+     * @return
+     * @since 3.0
+     */
+    PluginToolsRequest setLocal( ArtifactRepository local );
+
 }
diff --git a/pom.xml b/pom.xml
index 6dec851..d603983 100644
--- a/pom.xml
+++ b/pom.xml
@@ -228,6 +228,11 @@
         plexus-container-default
         1.0-alpha-9-stable-1
       
+      
+        org.codehaus.plexus
+        plexus-archiver
+        2.1.1
+      
 
       
         com.thoughtworks.qdox