You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kw...@apache.org on 2022/11/01 13:35:04 UTC

[maven-plugin-tools] 01/01: [MPLUGIN-439] Support custom phases in Execute annotation

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/allow-custom-phase-id
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git

commit 1e00a49bd72b66ff9b831e4519de1e9538c99bc9
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Tue Nov 1 14:34:55 2022 +0100

    [MPLUGIN-439] Support custom phases in Execute annotation
    
    Add Unit test for JavaAnnotationsMojoDescriptorExtractor
---
 .../apache/maven/plugins/annotations/Execute.java  |  17 ++-
 .../JavaAnnotationsMojoDescriptorExtractor.java    |   6 +-
 .../datamodel/ExecuteAnnotationContent.java        |  17 ++-
 .../plugin/extractor/annotations/Execute2Mojo.java |  40 +++++++
 .../plugin/extractor/annotations/ExecuteMojo.java  |  39 +++++++
 ...JavaAnnotationsMojoDescriptorExtractorTest.java |  79 ++++++++++++++
 .../annotations/TestAnnotationsReader.java         | 115 ---------------------
 .../scanner/DefaultMojoAnnotationsScannerTest.java |  73 +++++++++++++
 8 files changed, 266 insertions(+), 120 deletions(-)

diff --git a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java
index 1482d04e..59325027 100644
--- a/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java
+++ b/maven-plugin-annotations/src/main/java/org/apache/maven/plugins/annotations/Execute.java
@@ -39,20 +39,31 @@ import java.lang.annotation.Target;
 public @interface Execute
 {
     /**
-     * lifecycle phase to fork. Note that specifying a phase overrides specifying a goal.
+     * Lifecycle phase to fork. Note that specifying a phase overrides specifying a goal.
+     * For custom lifecycle phase ids use {@link #customPhase()} instead.
+     * This value takes precedence over the {@link #customPhase()}.
      * @return the phase
      */
     LifecyclePhase phase() default LifecyclePhase.NONE;
 
     /**
-     * goal to fork. Note that specifying a phase overrides specifying a goal. The specified <code>goal</code> must be
+     * Custom lifecycle phase to fork. Note that specifying a {@link #phase} overrides the specified custom phase.
+     * Also specifying a custom phase overrides specifying a goal.
+     * This element should only be used for non-standard phases. For standard phases rather use {@link #phase()}.
+     * 
+     * @since 3.8.0
+     */
+    String customPhase() default "";
+
+    /**
+     * Goal to fork. Note that specifying a phase overrides specifying a goal. The specified <code>goal</code> must be
      * another goal of the same plugin.
      * @return the goal
      */
     String goal() default "";
 
     /**
-     * lifecycle id of the lifecycle that defines {@link #phase()}. Only valid in combination with {@link #phase()}. If
+     * Lifecycle id of the lifecycle that defines {@link #phase()}. Only valid in combination with {@link #phase()}. If
      * not specified, Maven will use the lifecycle of the current build.
      *
      * @see <a href="https://maven.apache.org/maven-plugin-api/lifecycle-mappings.html">Lifecycle Mappings</a>
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 facfe4a4..5e337f49 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
@@ -103,7 +103,7 @@ public class JavaAnnotationsMojoDescriptorExtractor
     private static final GroupKey GROUP_KEY = new GroupKey( GroupKey.JAVA_GROUP, 100 );
 
     @Inject
-    private MojoAnnotationsScanner mojoAnnotationsScanner;
+    MojoAnnotationsScanner mojoAnnotationsScanner;
 
     @Inject
     private RepositorySystem repositorySystem;
@@ -724,6 +724,10 @@ public class JavaAnnotationsMojoDescriptorExtractor
                 {
                     mojoDescriptor.setExecutePhase( execute.phase().id() );
                 }
+                else if ( StringUtils.isNotEmpty( execute.customPhase() ) )
+                {
+                    mojoDescriptor.setExecutePhase( execute.customPhase() );
+                }
             }
 
             mojoDescriptor.setExecutionStrategy( mojo.executionStrategy() );
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
index 14b6b4ef..c5201923 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/datamodel/ExecuteAnnotationContent.java
@@ -37,12 +37,20 @@ public class ExecuteAnnotationContent
 
     private LifecyclePhase phase;
 
+    private String customPhase;
+
     @Override
     public LifecyclePhase phase()
     {
         return this.phase;
     }
 
+    @Override
+    public String customPhase()
+    {
+        return customPhase;
+    }
+
     @Override
     public String goal()
     {
@@ -55,12 +63,16 @@ public class ExecuteAnnotationContent
         return this.lifecycle;
     }
 
-
     public void phase( String phase )
     {
         this.phase = LifecyclePhase.valueOf( phase );
     }
 
+    public void customPhase( String customPhase )
+    {
+        this.customPhase = customPhase;
+    }
+
     public void goal( String goal )
     {
         this.goal = goal;
@@ -86,7 +98,10 @@ public class ExecuteAnnotationContent
         sb.append( "{goal='" ).append( goal ).append( '\'' );
         sb.append( ", lifecycle='" ).append( lifecycle ).append( '\'' );
         sb.append( ", phase=" ).append( phase );
+        sb.append( ", customPhase=" ).append( customPhase );
         sb.append( '}' );
         return sb.toString();
     }
+
+    
 }
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/Execute2Mojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/Execute2Mojo.java
new file mode 100644
index 00000000..556751ed
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/Execute2Mojo.java
@@ -0,0 +1,40 @@
+package org.apache.maven.tools.plugin.extractor.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;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+
+@Mojo( name = "execute2" )
+@Execute( goal = "compiler", lifecycle = "my-lifecycle", customPhase = "my-phase-id", phase = LifecyclePhase.GENERATE_RESOURCES )
+public class Execute2Mojo extends AbstractMojo
+{
+
+    @Override
+    public void execute()
+        throws MojoExecutionException, MojoFailureException
+    {
+    }
+
+}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ExecuteMojo.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ExecuteMojo.java
new file mode 100644
index 00000000..7e55a14f
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ExecuteMojo.java
@@ -0,0 +1,39 @@
+package org.apache.maven.tools.plugin.extractor.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;
+import org.apache.maven.plugins.annotations.Execute;
+import org.apache.maven.plugins.annotations.Mojo;
+
+@Mojo( name = "execute" )
+@Execute( goal = "compiler", lifecycle = "my-lifecycle", customPhase = "my-phase-id" )
+public class ExecuteMojo extends AbstractMojo
+{
+
+    @Override
+    public void execute()
+        throws MojoExecutionException, MojoFailureException
+    {
+    }
+
+}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractorTest.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractorTest.java
new file mode 100644
index 00000000..25fd7acd
--- /dev/null
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/JavaAnnotationsMojoDescriptorExtractorTest.java
@@ -0,0 +1,79 @@
+package org.apache.maven.tools.plugin.extractor.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 java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+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.plugins.annotations.LifecyclePhase;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.annotations.scanner.DefaultMojoAnnotationsScanner;
+import org.codehaus.plexus.logging.Logger;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+
+class JavaAnnotationsMojoDescriptorExtractorTest
+{
+
+    @Test
+    void testExecute() throws InvalidPluginDescriptorException, ExtractionException
+    {
+        JavaAnnotationsMojoDescriptorExtractor mojoDescriptorExtractor = new JavaAnnotationsMojoDescriptorExtractor();
+        DefaultMojoAnnotationsScanner scanner = new DefaultMojoAnnotationsScanner();
+        scanner.enableLogging( mock( Logger.class ) );
+        mojoDescriptorExtractor.mojoAnnotationsScanner = scanner;
+        PluginDescriptor pluginDescriptor = new PluginDescriptor();
+        MavenProject mavenProject = new MavenProject();
+        File directoryToScan = new File( FooMojo.class.getResource( "" ).getFile() );
+        Artifact artifact = new DefaultArtifact("groupId", "artifactId", "1.0.0", null, "jar", "classifier", null);
+        mavenProject.setArtifact( artifact );
+        mavenProject.getBuild().setOutputDirectory( directoryToScan.toString() );
+        List<MojoDescriptor> mojoDescriptors = mojoDescriptorExtractor.execute( new DefaultPluginToolsRequest( mavenProject, pluginDescriptor ) );
+        assertEquals( 6, mojoDescriptors.size() );
+        Map<String, MojoDescriptor> descriptorsMap = mojoDescriptors.stream().collect( Collectors.toMap( MojoDescriptor::getGoal, Function.<MojoDescriptor>identity() ) );
+        assertExecuteMojo( descriptorsMap.get( "execute" ) );
+        assertExecute2Mojo( descriptorsMap.get( "execute2" ) );
+    }
+
+    private void assertExecuteMojo( MojoDescriptor mojoDescriptor )
+    {
+        assertEquals( "my-phase-id", mojoDescriptor.getExecutePhase() );
+        assertEquals( "compiler", mojoDescriptor.getExecuteGoal() );
+        assertEquals( "my-lifecyle", mojoDescriptor.getExecuteLifecycle() );
+    }
+    
+    private void assertExecute2Mojo( MojoDescriptor mojoDescriptor )
+    {
+        // standard phase overrides custom phase
+        assertEquals( LifecyclePhase.GENERATE_RESOURCES.id(), mojoDescriptor.getExecutePhase() );
+    }
+}
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
deleted file mode 100644
index e1ea1543..00000000
--- a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/TestAnnotationsReader.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.apache.maven.tools.plugin.extractor.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 javax.inject.Inject;
-
-import java.io.File;
-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;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
-import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent;
-import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotatedClass;
-import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScanner;
-import org.apache.maven.tools.plugin.extractor.annotations.scanner.MojoAnnotationsScannerRequest;
-import org.codehaus.plexus.testing.PlexusTest;
-import org.junit.jupiter.api.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.codehaus.plexus.testing.PlexusExtension.getBasedir;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-/**
- * @author Olivier Lamy
- */
-@PlexusTest
-class TestAnnotationsReader
-{
-
-    @Inject
-    MojoAnnotationsScanner mojoAnnotationsScanner;
-
-    @Test
-    void testReadMojoClass()
-        throws Exception
-    {
-        MojoAnnotationsScannerRequest request = new MojoAnnotationsScannerRequest();
-        request.setClassesDirectories( Collections.singletonList( new File( getBasedir(), "target/test-classes" ) ) );
-        request.setIncludePatterns( Arrays.asList( "**/FooMojo.class" ) );
-        request.setProject( new MavenProject() );
-
-        Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = mojoAnnotationsScanner.scan( request );
-
-        System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses );
-
-        assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 );
-
-        MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.values().iterator().next();
-
-        assertEquals( FooMojo.class.getName(), mojoAnnotatedClass.getClassName() );
-        assertEquals( AbstractFooMojo.class.getName(), mojoAnnotatedClass.getParentClassName() );
-
-        Mojo mojo = mojoAnnotatedClass.getMojo();
-
-        assertEquals( "foo", mojo.name() );
-        assertTrue( mojo.threadSafe() );
-        assertFalse( mojo.aggregator() );
-        assertEquals( LifecyclePhase.COMPILE, mojo.defaultPhase() );
-
-        Execute execute = mojoAnnotatedClass.getExecute();
-
-        assertEquals( "compiler", execute.goal() );
-        assertEquals( "my-lifecycle", execute.lifecycle() );
-        assertEquals( LifecyclePhase.PACKAGE, execute.phase() );
-
-        Collection<ComponentAnnotationContent> components = mojoAnnotatedClass.getComponents().values();
-        assertThat( components ).isNotNull().isNotEmpty().hasSize( 1 );
-
-        Collection<ParameterAnnotationContent> parameters = mojoAnnotatedClass.getParameters().values();
-        assertThat( parameters ).isNotNull()
-            .isNotEmpty()
-            .hasSize( 5 )
-            .containsExactlyInAnyOrder(
-                new ParameterAnnotationContent( "bar", null, "thebar", "coolbar", true, false,
-                                                String.class.getName(), Collections.emptyList(), false ),
-                new ParameterAnnotationContent( "beer", null, "thebeer", "coolbeer", false, false,
-                                                String.class.getName(), Collections.emptyList(), false ),
-                new ParameterAnnotationContent( "paramFromSetter", null, "props.paramFromSetter", null,
-                                                false,
-                                                false, String.class.getName(), Collections.emptyList(), true ),
-                new ParameterAnnotationContent( "paramFromAdd", null, "props.paramFromAdd", null,
-                                                false,
-                                                false, String.class.getName(), Collections.emptyList(), true ),
-                new ParameterAnnotationContent( "paramFromSetterDeprecated", null, "props.paramFromSetterDeprecated", null,
-                                                false,
-                                                false, List.class.getName(), Collections.singletonList("java.lang.String"), true )
-            );
-    }
-}
diff --git a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
index 9c8f0b8d..83d25b53 100644
--- a/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScannerTest.java
@@ -21,21 +21,35 @@ package org.apache.maven.tools.plugin.extractor.annotations.scanner;
 
 import java.io.File;
 import java.io.IOException;
+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;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.project.MavenProject;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.annotations.AbstractFooMojo;
 import org.apache.maven.tools.plugin.extractor.annotations.DeprecatedMojo;
+import org.apache.maven.tools.plugin.extractor.annotations.FooMojo;
 import org.apache.maven.tools.plugin.extractor.annotations.ParametersWithGenericsMojo;
+import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent;
 import org.codehaus.plexus.logging.Logger;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.codehaus.plexus.testing.PlexusExtension.getBasedir;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 
+// TODO: merge with {@link TestAnnotationsReader}
 class DefaultMojoAnnotationsScannerTest
 {
     private DefaultMojoAnnotationsScanner scanner = new DefaultMojoAnnotationsScanner();
@@ -124,4 +138,63 @@ class DefaultMojoAnnotationsScannerTest
         assertEquals( "java.util.List", parameter.getClassName() );
         assertThat( parameter.getTypeParameters() ).containsExactly( "java.lang.Number" );
     }
+
+    @Test
+    void scanFooMojoClass()
+        throws Exception
+    {
+        MojoAnnotationsScannerRequest request = new MojoAnnotationsScannerRequest();
+        request.setClassesDirectories( Collections.singletonList( new File( getBasedir(), "target/test-classes" ) ) );
+        request.setIncludePatterns( Arrays.asList( "**/FooMojo.class" ) );
+        request.setProject( new MavenProject() );
+
+        scanner.enableLogging( mock( Logger.class ) );
+        Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = scanner.scan( request );
+
+        System.out.println( "mojoAnnotatedClasses:" + mojoAnnotatedClasses );
+
+        assertThat( mojoAnnotatedClasses ).isNotNull().isNotEmpty().hasSize( 1 );
+
+        MojoAnnotatedClass mojoAnnotatedClass = mojoAnnotatedClasses.values().iterator().next();
+
+        assertEquals( FooMojo.class.getName(), mojoAnnotatedClass.getClassName() );
+        assertEquals( AbstractFooMojo.class.getName(), mojoAnnotatedClass.getParentClassName() );
+
+        Mojo mojo = mojoAnnotatedClass.getMojo();
+
+        assertEquals( "foo", mojo.name() );
+        assertTrue( mojo.threadSafe() );
+        assertFalse( 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() );
+        assertEquals( "my-phase-id", execute.customPhase() );
+
+        Collection<ComponentAnnotationContent> components = mojoAnnotatedClass.getComponents().values();
+        assertThat( components ).isNotNull().isNotEmpty().hasSize( 1 );
+
+        Collection<ParameterAnnotationContent> parameters = mojoAnnotatedClass.getParameters().values();
+        assertThat( parameters ).isNotNull()
+            .isNotEmpty()
+            .hasSize( 5 )
+            .containsExactlyInAnyOrder(
+                new ParameterAnnotationContent( "bar", null, "thebar", "coolbar", true, false,
+                                                String.class.getName(), Collections.emptyList(), false ),
+                new ParameterAnnotationContent( "beer", null, "thebeer", "coolbeer", false, false,
+                                                String.class.getName(), Collections.emptyList(), false ),
+                new ParameterAnnotationContent( "paramFromSetter", null, "props.paramFromSetter", null,
+                                                false,
+                                                false, String.class.getName(), Collections.emptyList(), true ),
+                new ParameterAnnotationContent( "paramFromAdd", null, "props.paramFromAdd", null,
+                                                false,
+                                                false, String.class.getName(), Collections.emptyList(), true ),
+                new ParameterAnnotationContent( "paramFromSetterDeprecated", null, "props.paramFromSetterDeprecated", null,
+                                                false,
+                                                false, List.class.getName(), Collections.singletonList("java.lang.String"), true )
+            );
+    }
 }