You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2021/10/22 08:33:54 UTC

[maven-plugin-tools] 01/01: [MPLUGIN-373] Group extractors and improve their selection

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

cstamas pushed a commit to branch MPLUGIN-373-group-extractors
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git

commit 66baeb9b1a763738df5baa811a85936a44e5bcd9
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Fri Oct 22 10:26:46 2021 +0200

    [MPLUGIN-373] Group extractors and improve their selection
    
    The issue describes following situation: developer uses
    modern Java level and uses Mojo annotations to create a
    maven plugin. Everything works (compile), but maven-plugin-plugin
    fails to extract the mojo descriptors.
    
    Reason is simple: javadoc extractor (powered by QDox) chokes on
    same modern Java language features (like record is in issue).
    
    So, proposal:
    
    Extend extractors iface with following fields:
    * getName() -- just to simplify their handling in code (no need to hold on map).
    * isDeprecated() -- IMO, we should deprecate Javadoc mojo descriptor extraction, and
      if used, Maven should WARN to migrate to Annotations.
    * getGroupKey() -- this defines "extractor" groups and ordering within it
    
    Currently we have two extractors in same group "java": the annotation extractor
    and javadoc/qdox extractor. Their run order is _undefined currently_.
    
    This proposal implements following changes:
    * extractors are SORTED by groupKey before being used (so defined exectution ordering)
    * extractors of same group are ordered (annotations then javadoc)
    * javadoc extractor is DEPRECATED (isDeprecated returns true)
    * MojoScanner is modified, that IF a deprecated extractor is on turn, but there ARE
      discovered components in same group, it is skipped.
    
    This may look as tailored to java case, but is actually future proof. This
    will fix out of the box the MPLUGIN-373 for example, where legacy bits
    within maven-plugin-plugin prevents user to use modern Java and modern tools.
    
    On the other hand, this may need more, things like:
    * allow run of deprecated extractors?
---
 .../JavaAnnotationsMojoDescriptorExtractor.java    | 25 +++++-
 .../AbstractScriptedMojoDescriptorExtractor.java   |  6 ++
 .../maven/tools/plugin/extractor/GroupKey.java     | 83 ++++++++++++++++++++
 .../plugin/extractor/MojoDescriptorExtractor.java  | 20 +++++
 .../tools/plugin/scanner/DefaultMojoScanner.java   | 89 +++++++++++++++++-----
 .../tools/plugin/scanner/ScannerTestExtractor.java | 23 +++++-
 .../maven/tools/plugin/scanner/TestExtractor.java  | 22 +++++-
 .../JavaJavadocMojoDescriptorExtractor.java        | 26 ++++++-
 .../extractor/ant/AntMojoDescriptorExtractor.java  | 21 ++++-
 .../BeanshellMojoDescriptorExtractor.java          | 17 +++++
 10 files changed, 309 insertions(+), 23 deletions(-)

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 ca68e32..6e5361f 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
@@ -50,6 +50,7 @@ import org.apache.maven.repository.RepositorySystem;
 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.GroupKey;
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent;
@@ -80,11 +81,14 @@ import com.thoughtworks.qdox.model.JavaField;
  * @author Olivier Lamy
  * @since 3.0
  */
-@Component( role = MojoDescriptorExtractor.class, hint = "java-annotations" )
+@Component( role = MojoDescriptorExtractor.class, hint = JavaAnnotationsMojoDescriptorExtractor.NAME )
 public class JavaAnnotationsMojoDescriptorExtractor
     extends AbstractLogEnabled
     implements MojoDescriptorExtractor
 {
+    public static final String NAME = "java-annotations";
+
+    private static final GroupKey GROUP_KEY = new GroupKey( GroupKey.JAVA_GROUP, 100 );
 
     @org.codehaus.plexus.component.annotations.Requirement
     private MojoAnnotationsScanner mojoAnnotationsScanner;
@@ -96,6 +100,25 @@ public class JavaAnnotationsMojoDescriptorExtractor
     private ArchiverManager archiverManager;
 
     @Override
+    public String getName()
+    {
+        return NAME;
+    }
+
+    @Override
+    public boolean isDeprecated()
+    {
+        return false; // this is the "current way" to write Java Mojos
+    }
+
+    @Override
+    @SuppressWarnings( "checkstyle:magicnumber" )
+    public GroupKey getGroupKey()
+    {
+        return GROUP_KEY;
+    }
+
+    @Override
     public List<MojoDescriptor> execute( PluginToolsRequest request )
         throws ExtractionException, InvalidPluginDescriptorException
     {
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java
index 8955ffb..8beaa7f 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/AbstractScriptedMojoDescriptorExtractor.java
@@ -43,6 +43,12 @@ public abstract class AbstractScriptedMojoDescriptorExtractor
     extends AbstractLogEnabled
     implements MojoDescriptorExtractor
 {
+    @Override
+    public boolean isDeprecated()
+    {
+        return false;
+    }
+
     /** {@inheritDoc} */
     @Override
     public List<MojoDescriptor> execute( PluginToolsRequest request )
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/GroupKey.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/GroupKey.java
new file mode 100644
index 0000000..8afd85b
--- /dev/null
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/GroupKey.java
@@ -0,0 +1,83 @@
+package org.apache.maven.tools.plugin.extractor;
+
+/*
+ * 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.
+ */
+
+/**
+ * Group key: defines "grouping" for descriptor (based on source of extraction) and rank within
+ * group.
+ */
+public final class GroupKey
+    implements Comparable<GroupKey>
+{
+    /**
+     * Java group is handled a bit special: is always first to be scanned.
+     */
+    public static final String JAVA_GROUP = "java";
+
+    private final String group;
+
+    private final int order;
+
+    public GroupKey( final String group, final int order )
+    {
+        if ( group == null )
+        {
+            throw new NullPointerException( "GroupKey.group null" );
+        }
+        this.group = group;
+        this.order = order;
+    }
+
+    /**
+     * Returns the group this key belongs to, never {@code null}.
+     */
+    public String getGroup()
+    {
+        return group;
+    }
+
+    /**
+     * Returns the order within same group of this key. Returns int should be used for ordering only.
+     */
+    public int getOrder()
+    {
+        return order;
+    }
+
+    /**
+     * Compares by group then by order.
+     */
+    @Override
+    public int compareTo( final GroupKey o )
+    {
+        int result = this.group.compareTo( o.group );
+        if ( result != 0 )
+        {
+            return result;
+        }
+        return Integer.compare( this.order, o.order );
+    }
+
+    @Override
+    public String toString()
+    {
+        return group + ":" + order;
+    }
+}
\ No newline at end of file
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java
index ec3625f..29ea5f3 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/extractor/MojoDescriptorExtractor.java
@@ -34,6 +34,26 @@ public interface MojoDescriptorExtractor
     String ROLE = MojoDescriptorExtractor.class.getName();
 
     /**
+     * Returns the "name" (id) of the extractor.
+     */
+    String getName();
+
+    /**
+     * Returns {@code true} if extractor is deprecated.
+     *
+     * @since TBD
+     */
+    boolean isDeprecated();
+
+    /**
+     * Returns the {@link GroupKey} of extractor, as {@link org.apache.maven.tools.plugin.scanner.MojoScanner} will
+     * execute them grouped, and ordered within groups. Must never return {@code null}.
+     *
+     * @since TBD
+     */
+    GroupKey getGroupKey();
+
+    /**
      * Execute the mojo extraction.
      *
      * @param request The {@link PluginToolsRequest} containing information for the extraction process.
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java
index 67dc5dc..1318886 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/scanner/DefaultMojoScanner.java
@@ -23,12 +23,17 @@ import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.GroupKey;
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.logging.console.ConsoleLogger;
 import org.codehaus.plexus.util.StringUtils;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -77,29 +82,60 @@ public class DefaultMojoScanner
         throws ExtractionException, InvalidPluginDescriptorException
     {
         Logger logger = getLogger();
-        Set<String> activeExtractorsInternal = getActiveExtractors();
-
-        logger.debug( "Using " + activeExtractorsInternal.size() + " mojo extractors." );
 
         int numMojoDescriptors = 0;
 
-        for ( String extractorId : activeExtractorsInternal )
+        List<MojoDescriptorExtractor> orderedExtractors = getOrderedExtractors();
+
+        logger.debug( "Using " + orderedExtractors.size() + " mojo extractors." );
+
+        HashMap<String, Integer> groupStats = new HashMap<>();
+
+        for ( MojoDescriptorExtractor extractor : orderedExtractors )
         {
-            MojoDescriptorExtractor extractor = mojoDescriptorExtractors.get( extractorId );
+            GroupKey groupKey = extractor.getGroupKey();
+            String extractorId = extractor.getName();
 
-            if ( extractor == null )
+            if ( extractor.isDeprecated() )
             {
-                throw new ExtractionException( "No mojo extractor with '" + extractorId + "' id." );
+                if ( groupStats.containsKey( groupKey.getGroup() )
+                      && groupStats.get( groupKey.getGroup() ) != 0 )
+                {
+                    logger.debug( "Skipping " + extractorId + " mojo extractor; group '"
+                        + groupKey.getGroup() + "' already have " + groupStats.get( groupKey.getGroup() )
+                        + " discovered descriptors" );
+                    continue; // if same group already found descriptors, skip rest of the group
+                }
             }
 
             logger.debug( "Applying " + extractorId + " mojo extractor" );
 
             List<MojoDescriptor> extractorDescriptors = extractor.execute( request );
 
+            int extractorDescriptorsCount = extractorDescriptors.size();
+
             logger.info( extractorId + " mojo extractor found " + extractorDescriptors.size()
                              + " mojo descriptor" + ( extractorDescriptors.size() > 1 ? "s" : "" ) + "." );
             numMojoDescriptors += extractorDescriptors.size();
 
+            if ( extractor.isDeprecated() &&  extractorDescriptorsCount > 0 )
+            {
+                logger.warn( "" );
+                logger.warn( "Deprecated extractor extracted descriptors. Upgrade your Mojo definitions." );
+                logger.warn( "" );
+            }
+
+            if ( groupStats.containsKey( groupKey.getGroup() ) )
+            {
+                groupStats.put( groupKey.getGroup(),
+                    groupStats.get( groupKey.getGroup() ) + extractorDescriptorsCount );
+            }
+            else
+            {
+                groupStats.put( groupKey.getGroup(),
+                    extractorDescriptorsCount );
+            }
+
             for ( MojoDescriptor descriptor : extractorDescriptors )
             {
                 logger.debug( "Adding mojo: " + descriptor + " to plugin descriptor." );
@@ -110,6 +146,8 @@ public class DefaultMojoScanner
             }
         }
 
+        logger.debug( "Discovered descriptors by groups: " + groupStats );
+
         if ( numMojoDescriptors == 0 && !request.isSkipErrorNoDescriptorsFound() )
         {
             throw new InvalidPluginDescriptorException(
@@ -118,21 +156,38 @@ public class DefaultMojoScanner
         }
     }
 
-    /**
-     * Gets the name of the active extractors.
-     *
-     * @return A Set containing the names of the active extractors.
-     */
-    protected Set<String> getActiveExtractors()
+    private List<MojoDescriptorExtractor> getOrderedExtractors() throws ExtractionException
     {
-        Set<String> result = activeExtractors;
+        Set<String> extractors = activeExtractors;
 
-        if ( result == null )
+        if ( extractors == null )
         {
-            result = new HashSet<>( mojoDescriptorExtractors.keySet() );
+            extractors = new HashSet<>( mojoDescriptorExtractors.keySet() );
+        }
+
+        ArrayList<MojoDescriptorExtractor> orderedExtractors = new ArrayList<>();
+        for ( String extractorId : extractors )
+        {
+            MojoDescriptorExtractor extractor = mojoDescriptorExtractors.get( extractorId );
+
+            if ( extractor == null )
+            {
+                throw new ExtractionException( "No mojo extractor with '" + extractorId + "' id." );
+            }
+
+            orderedExtractors.add( extractor );
         }
 
-        return result;
+        Collections.sort( orderedExtractors, new Comparator<MojoDescriptorExtractor>()
+        {
+            @Override
+            public int compare( final MojoDescriptorExtractor o1, final MojoDescriptorExtractor o2 )
+            {
+                return o1.getGroupKey().compareTo( o2.getGroupKey() );
+            }
+        } );
+
+        return orderedExtractors;
     }
 
     @Override
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java
index a46104f..56d938d 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/ScannerTestExtractor.java
@@ -26,6 +26,7 @@ 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.GroupKey;
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 
 import java.util.Collections;
@@ -37,6 +38,8 @@ import java.util.List;
 public class ScannerTestExtractor
     implements MojoDescriptorExtractor
 {
+    private static final GroupKey GROUP_KEY = new GroupKey( "test", 100 );
+
     private final String goal;
 
     public ScannerTestExtractor( String goal )
@@ -44,7 +47,25 @@ public class ScannerTestExtractor
         this.goal = goal;
     }
 
-    public List<MojoDescriptor> execute( MavenProject project, PluginDescriptor pluginDescriptor )
+    @Override
+    public String getName()
+    {
+      return "scanner-test";
+    }
+
+    @Override
+    public boolean isDeprecated()
+    {
+      return false;
+    }
+
+    @Override
+    public GroupKey getGroupKey()
+    {
+      return GROUP_KEY;
+    }
+
+    public List<MojoDescriptor> execute(MavenProject project, PluginDescriptor pluginDescriptor )
         throws InvalidPluginDescriptorException, ExtractionException
     {
         return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) );
diff --git a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java
index 46bff95..4b32bf5 100644
--- a/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java
+++ b/maven-plugin-tools-api/src/test/java/org/apache/maven/tools/plugin/scanner/TestExtractor.java
@@ -24,6 +24,7 @@ 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.GroupKey;
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 
 import java.util.Collections;
@@ -35,8 +36,27 @@ import java.util.List;
 public class TestExtractor
     implements MojoDescriptorExtractor
 {
+    private static final GroupKey GROUP_KEY = new GroupKey( "test", 100 );
 
-    public List<MojoDescriptor> execute( MavenProject project, PluginDescriptor pluginDescriptor )
+    @Override
+    public String getName()
+    {
+        return "test";
+    }
+
+    @Override
+    public boolean isDeprecated()
+    {
+        return false;
+    }
+
+    @Override
+    public GroupKey getGroupKey()
+    {
+        return GROUP_KEY;
+    }
+
+    public List<MojoDescriptor> execute(MavenProject project, PluginDescriptor pluginDescriptor )
     {
         return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) );
     }
diff --git a/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java b/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java
index a441888..e148aba 100644
--- a/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java
+++ b/maven-plugin-tools-java/src/main/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaJavadocMojoDescriptorExtractor.java
@@ -39,6 +39,7 @@ import org.apache.maven.project.MavenProject;
 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.GroupKey;
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 import org.apache.maven.tools.plugin.util.PluginUtils;
 import org.codehaus.plexus.component.annotations.Component;
@@ -62,11 +63,34 @@ import com.thoughtworks.qdox.model.JavaType;
  *
  * @see org.apache.maven.plugin.descriptor.MojoDescriptor
  */
-@Component( role = MojoDescriptorExtractor.class, hint = "java-javadoc" )
+@Component( role = MojoDescriptorExtractor.class, hint = JavaJavadocMojoDescriptorExtractor.NAME )
 public class JavaJavadocMojoDescriptorExtractor
     extends AbstractLogEnabled
     implements MojoDescriptorExtractor, JavadocMojoAnnotation
 {
+    public static final String NAME = "java-javadoc";
+
+    private static final GroupKey GROUP_KEY = new GroupKey( GroupKey.JAVA_GROUP, 200 );
+
+    @Override
+    public String getName()
+    {
+        return NAME;
+    }
+
+    @Override
+    public boolean isDeprecated()
+    {
+        return true; // one should use Java5 annotations instead
+    }
+
+    @Override
+    @SuppressWarnings( "checkstyle:magicnumber" )
+    public GroupKey getGroupKey()
+    {
+        return GROUP_KEY;
+    }
+
     /**
      * @param parameter not null
      * @param i positive number
diff --git a/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java b/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java
index acd08a1..8da3eb6 100644
--- a/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java
+++ b/maven-script/maven-plugin-tools-ant/src/main/java/org/apache/maven/tools/plugin/extractor/ant/AntMojoDescriptorExtractor.java
@@ -34,6 +34,7 @@ import org.apache.maven.project.path.PathTranslator;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.GroupKey;
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException;
 import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser;
@@ -45,17 +46,33 @@ import org.codehaus.plexus.util.StringUtils;
  * Extracts Mojo descriptors from <a href="http://ant.apache.org">Ant</a> sources.
  *
  */
-@Component( role = MojoDescriptorExtractor.class, hint = "ant" )
+@Component( role = MojoDescriptorExtractor.class, hint = AntMojoDescriptorExtractor.NAME )
 public class AntMojoDescriptorExtractor
     extends AbstractScriptedMojoDescriptorExtractor
     implements MojoDescriptorExtractor
 {
+    public static final String NAME = "ant";
+
+    private static final GroupKey GROUP_KEY = new GroupKey( "ant", 100 );
+
     /** Default metadata file extension */
     private static final String METADATA_FILE_EXTENSION = ".mojos.xml";
 
     /** Default Ant build file extension */
     private static final String SCRIPT_FILE_EXTENSION = ".build.xml";
-    
+
+    @Override
+    public String getName()
+    {
+        return NAME;
+    }
+
+    @Override
+    public GroupKey getGroupKey()
+    {
+        return GROUP_KEY;
+    }
+
     /** {@inheritDoc} */
     @Override
     protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata(
diff --git a/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java b/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java
index 14ba47d..075b4da 100644
--- a/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java
+++ b/maven-script/maven-plugin-tools-beanshell/src/main/java/org/apache/maven/tools/plugin/extractor/beanshell/BeanshellMojoDescriptorExtractor.java
@@ -28,6 +28,7 @@ import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
+import org.apache.maven.tools.plugin.extractor.GroupKey;
 import org.apache.maven.tools.plugin.extractor.MojoDescriptorExtractor;
 import org.codehaus.plexus.component.annotations.Component;
 
@@ -47,6 +48,22 @@ public class BeanshellMojoDescriptorExtractor
     extends AbstractScriptedMojoDescriptorExtractor
     implements MojoDescriptorExtractor
 {
+    public static final String NAME = "bsh";
+
+    private static final GroupKey GROUP_KEY = new GroupKey( "bsh", 100 );
+
+    @Override
+    public String getName()
+    {
+        return NAME;
+    }
+
+    @Override
+    public GroupKey getGroupKey()
+    {
+        return GROUP_KEY;
+    }
+
     /**
      * {@inheritDoc}
      */