You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sj...@apache.org on 2022/07/28 16:25:34 UTC

[maven-plugin-tools] branch MPLUGIN-408 created (now 2c996dd5)

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

sjaranowski pushed a change to branch MPLUGIN-408
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git


      at 2c996dd5 [MPLUGIN-408] helpmojo improvement

This branch includes the following new commits:

     new 2c996dd5 [MPLUGIN-408] helpmojo improvement

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[maven-plugin-tools] 01/01: [MPLUGIN-408] helpmojo improvement

Posted by sj...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sjaranowski pushed a commit to branch MPLUGIN-408
in repository https://gitbox.apache.org/repos/asf/maven-plugin-tools.git

commit 2c996dd55a390579936a24ba92205ecd6f85cf77
Author: Slawomir Jaranowski <s....@gmail.com>
AuthorDate: Thu Jul 28 18:14:48 2022 +0200

    [MPLUGIN-408] helpmojo improvement
    
    - use groupId + artifactId for calculating package name
    - discover mojos only ones by descriptor mojo
    - simplify in AbstractGeneratorMojo
    - remove unneeded code
---
 maven-plugin-plugin/pom.xml                        |   2 +-
 .../verify.groovy                                  |   7 +-
 .../it/annotation-with-inheritance/verify.groovy   |   7 +-
 .../java-basic-annotations-jdk8/invoker.properties |   4 +-
 .../src/it/java-basic-annotations-jdk8/pom.xml     |   2 +-
 .../it/java-basic-annotations-jdk8/verify.groovy   |   5 +-
 .../verify.groovy                                  |   5 +-
 .../src/it/java-basic-annotations/verify.groovy    |  10 +-
 .../it/mplugin-363_help-reproducible/verify.groovy |   4 +-
 .../maven/plugin/plugin/AbstractGeneratorMojo.java | 302 +-----------------
 .../plugin/plugin/DescriptorGeneratorMojo.java     | 288 ++++++++++++++++--
 .../maven/plugin/plugin/HelpGeneratorMojo.java     |  85 ++++--
 .../maven/plugin/plugin/HelpGeneratorMojoTest.java |  63 ++++
 .../generator/PluginDescriptorGenerator.java       |  28 +-
 .../plugin/generator/PluginHelpGenerator.java      | 336 ++-------------------
 .../plugin/generator/PluginHelpGeneratorTest.java  |  46 ---
 .../javadoc/JavaMojoDescriptorExtractorTest.java   |   2 +-
 pom.xml                                            |   9 +-
 18 files changed, 463 insertions(+), 742 deletions(-)

diff --git a/maven-plugin-plugin/pom.xml b/maven-plugin-plugin/pom.xml
index 448f6bd9..5642641e 100644
--- a/maven-plugin-plugin/pom.xml
+++ b/maven-plugin-plugin/pom.xml
@@ -179,7 +179,7 @@
     <!-- tests -->
     <dependency>
       <groupId>org.junit.jupiter</groupId>
-      <artifactId>junit-jupiter-engine</artifactId>
+      <artifactId>junit-jupiter</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
index 1ef2944d..b941b803 100644
--- a/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
+++ b/maven-plugin-plugin/src/it/annotation-with-inheritance-from-deps/verify.groovy
@@ -20,11 +20,8 @@
 File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" );
 assert descriptorFile.isFile()
 
-File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" );
-assert !oldHelpClass.exists()
-
-File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" );
-assert newHelpClass.exists()
+File helpClass = new File( basedir, "target/classes/org/apache/maven/its/annotation_with_inheritance_from_deps/annotation_with_inheritance_from_deps/HelpMojo.class" );
+assert helpClass.exists()
 
 def pluginDescriptor = new XmlParser().parse( descriptorFile );
 
diff --git a/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy b/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy
index d066901a..689e0008 100644
--- a/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy
+++ b/maven-plugin-plugin/src/it/annotation-with-inheritance/verify.groovy
@@ -23,11 +23,8 @@ assert touchFile.isFile()
 File descriptorFile = new File( basedir, "target/classes/META-INF/maven/plugin.xml" );
 assert descriptorFile.isFile()
 
-File oldHelpClass = new File( basedir, "target/classes/HelpMojo.class" );
-assert !oldHelpClass.exists()
-
-File newHelpClass = new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" );
-assert newHelpClass.exists()
+File helpClass = new File( basedir, "target/classes/org/apache/maven/its/annotation_with_inheritance/annotation_with_inheritance/HelpMojo.class" );
+assert helpClass.exists()
 
 def pluginDescriptor = new XmlParser().parse( descriptorFile );
 
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties
index d0a9e140..6760204d 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/invoker.properties
@@ -16,5 +16,5 @@
 # under the License.
 
 invoker.goals.1 = clean install
-invoker.goals.2 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014
-invoker.goals.3 = org.apache.maven.its.basic-java-annotations:maven-it-basic-java-annotations:1.0-SNAPSHOT:help
+invoker.goals.2 = org.apache.maven.its.basic-java-annotations:123-maven-it-basic-java-annotations:1.0-SNAPSHOT:it0014
+invoker.goals.3 = org.apache.maven.its.basic-java-annotations:123-maven-it-basic-java-annotations:1.0-SNAPSHOT:help
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml
index 124b37cc..dda14a8a 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/pom.xml
@@ -23,7 +23,7 @@ under the License.
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>org.apache.maven.its.basic-java-annotations</groupId>
-  <artifactId>maven-it-basic-java-annotations</artifactId>
+  <artifactId>123-maven-it-basic-java-annotations</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>maven-plugin</packaging>
 
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy
index 294f5386..b130e2c5 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdk8/verify.groovy
@@ -224,8 +224,7 @@ requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "
 assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper'
 
 // check help mojo source and class
-assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile()
-assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile()
-assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile()
+assert new File( basedir, "target/classes/org/apache/maven/its/basic_java_annotations/_123_maven_it_basic_java_annotations/HelpMojo.class" ).isFile()
+assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/basic_java_annotations/_123_maven_it_basic_java_annotations/HelpMojo.java" ).isFile()
 
 return true;
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy b/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy
index 294f5386..c498a221 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy
+++ b/maven-plugin-plugin/src/it/java-basic-annotations-jdkcurrent/verify.groovy
@@ -224,8 +224,7 @@ requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "
 assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper'
 
 // check help mojo source and class
-assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile()
-assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile()
-assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile()
+assert new File( basedir, "target/classes/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.class" ).isFile()
+assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.java" ).isFile()
 
 return true;
diff --git a/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy b/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
index 0541a8f1..4315bef7 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
+++ b/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
@@ -224,9 +224,13 @@ requirement = mojo.requirements.requirement.findAll{ it.'field-name'.text() == "
 assert requirement.role.text() == 'org.apache.maven.project.MavenProjectHelper'
 
 // check help mojo source and class
-assert new File( basedir, "target/classes/org/apache/maven/plugin/coreit/HelpMojo.class" ).isFile()
-assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/plugin/coreit/HelpMojo.java" ).isFile()
-assert !new File( basedir, "target/generated-sources/plugin/HelpMojo.java" ).isFile()
+assert new File( basedir, "target/classes/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.class" ).isFile()
+assert new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/basic_java_annotations/maven_it_basic_java_annotations/HelpMojo.java" ).isFile()
+
+mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "help"}[0]
+assert mojo.goal.text() == 'help'
+assert mojo.implementation.text() == 'org.apache.maven.its.basic_java_annotations.maven_it_basic_java_annotations.HelpMojo'
+assert mojo.language.text() == 'java'
 
 // check values set by deprecated annotation only
 mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "mplugin-396"}[0]
diff --git a/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy b/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy
index b64de436..b47f8a9d 100644
--- a/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy
+++ b/maven-plugin-plugin/src/it/mplugin-363_help-reproducible/verify.groovy
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-firstRun = new File( basedir, "target/generated-sources-run1/plugin/test/HelpMojo.java" ).text;
-secondRun = new File( basedir, "target/generated-sources/plugin/test/HelpMojo.java" ).text;
+firstRun = new File( basedir, "target/generated-sources-run1/plugin/org/apache/maven/its/plugin/help/HelpMojo.java" ).text;
+secondRun = new File( basedir, "target/generated-sources/plugin/org/apache/maven/its/plugin/help/HelpMojo.java" ).text;
 
 assert firstRun == secondRun;
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 bd1354d5..a62d923f 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
@@ -19,34 +19,14 @@ package org.apache.maven.plugin.plugin;
  * under the License.
  */
 
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
-import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Parameter;
 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.generator.Generator;
-import org.apache.maven.tools.plugin.generator.GeneratorException;
-import org.apache.maven.tools.plugin.generator.GeneratorUtils;
-import org.apache.maven.tools.plugin.scanner.MojoScanner;
-import org.codehaus.plexus.component.repository.ComponentDependency;
-import org.codehaus.plexus.util.ReaderFactory;
-import org.sonatype.plexus.build.incremental.BuildContext;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
 
 /**
  * Abstract class for this Plugin.
@@ -63,100 +43,19 @@ public abstract class AbstractGeneratorMojo
     @Parameter( defaultValue = "${project}", readonly = true )
     protected MavenProject project;
 
-    /**
-     * The component used for scanning the source tree for mojos.
-     */
-    @Component
-    protected MojoScanner mojoScanner;
-
-    @Component
-    protected BuildContext buildContext;
-
-    /**
-     * The file encoding of the source files.
-     *
-     * @since 2.5
-     */
-    @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
-    protected String encoding;
-
     /**
      * The goal prefix that will appear before the ":".
      */
     @Parameter
     protected String goalPrefix;
 
-    /**
-     * 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
-     *
-     * @since 3.0
-     */
-    @Parameter( property = "maven.plugin.skipErrorNoDescriptorsFound", defaultValue = "false" )
-    protected boolean skipErrorNoDescriptorsFound;
-
-    /**
-     * <p>
-     * The role names of mojo extractors to use.
-     * </p>
-     * <p>
-     * If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors
-     * will be used.
-     * </p>
-     * Example:
-     * <pre>
-     *  &lt;!-- Use all mojo extractors --&gt;
-     *  &lt;extractors/&gt;
-     *
-     *  &lt;!-- Use no mojo extractors --&gt;
-     *  &lt;extractors&gt;
-     *      &lt;extractor/&gt;
-     *  &lt;/extractors&gt;
-     *
-     *  &lt;!-- Use only bsh mojo extractor --&gt;
-     *  &lt;extractors&gt;
-     *      &lt;extractor&gt;bsh&lt;/extractor&gt;
-     *  &lt;/extractors&gt;
-     * </pre>
-     */
-    @Parameter
-    protected Set<String> extractors;
-
     /**
      * Set this to "true" to skip invoking any goals or reports of the plugin.
      *
      * @since 2.8
      */
     @Parameter( defaultValue = "false", property = "maven.plugin.skip" )
-    protected boolean skip;
-
-    /**
-     * Specify the dependencies as {@code groupId:artifactId} containing (abstract) Mojos, to filter
-     * dependencies scanned at runtime and focus on dependencies that are really useful to Mojo analysis.
-     * By default, the value is {@code null} and all dependencies are scanned (as before this parameter was added).
-     * If specified in the configuration with no children, no dependencies are scanned.
-     * 
-     * @since 3.5
-     */
-    @Parameter
-    private List<String> mojoDependencies = null;
-
-    /**
-     * List of Remote Repositories used by the resolver
-     *
-     * @since 3.0
-     */
-    @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
-    protected List<ArtifactRepository> remoteRepos;
-
-    /**
-     * Location of the local repository.
-     *
-     * @since 3.0
-     */
-    @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
-    protected ArtifactRepository local;
+    private boolean skip;
 
     /**
      * Maven plugin packaging types. Default is single "maven-plugin".
@@ -164,55 +63,15 @@ public abstract class AbstractGeneratorMojo
      * @since 3.3
      */
     @Parameter
-    protected List<String> packagingTypes = Collections.singletonList( "maven-plugin" );
-
-    /**
-     * Flag controlling is "expected dependencies in provided scope" check to be performed or not. Default value:
-     * {@code true}.
-     *
-     * @since 3.6.3
-     */
-    @Parameter( defaultValue = "true", property = "maven.plugin.checkExpectedProvidedScope" )
-    private boolean checkExpectedProvidedScope = true;
-
-    /**
-     * List of {@code groupId} strings of artifact coordinates that are expected to be in "provided" scope. Default
-     * value: {@code ["org.apache.maven"]}.
-     *
-     * @since 3.6.3
-     */
-    @Parameter
-    private List<String> expectedProvidedScopeGroupIds = Collections.singletonList( "org.apache.maven" );
-
-    /**
-     * List of {@code groupId:artifactId} strings of artifact coordinates that are to be excluded from "expected
-     * provided scope" check. Default value: {@code ["org.apache.maven:maven-archiver", "org.apache.maven:maven-jxr"]}.
-     *
-     * @since 3.6.3
-     */
-    @Parameter
-    private List<String> expectedProvidedScopeExclusions = Arrays.asList(
-            "org.apache.maven:maven-archiver",
-            "org.apache.maven:maven-jxr" );
-
-    /**
-     * @return the output directory where files will be generated.
-     */
-    protected abstract File getOutputDirectory();
-
-    /**
-     * @return the wanted <code>Generator</code> implementation.
-     */
-    protected abstract Generator createGenerator();
+    private List<String> packagingTypes = Collections.singletonList( "maven-plugin" );
 
     /**
      * System/OS line separator: used to format console messages.
      */
-    private static final String LS = System.lineSeparator();
+    protected static final String LS = System.lineSeparator();
+
+    protected abstract void generate() throws MojoExecutionException;
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     public void execute()
         throws MojoExecutionException
@@ -222,6 +81,7 @@ public abstract class AbstractGeneratorMojo
             getLog().info( "Unsupported packaging type " + project.getPackaging() + ", execution skipped" );
             return;
         }
+
         if ( skip )
         {
             getLog().warn( "Execution skipped" );
@@ -230,7 +90,7 @@ public abstract class AbstractGeneratorMojo
 
         if ( !"maven-plugin".equalsIgnoreCase( project.getArtifactId() )
             && project.getArtifactId().toLowerCase().startsWith( "maven-" )
-            && project.getArtifactId().toLowerCase().endsWith( "-plugin" ) 
+            && project.getArtifactId().toLowerCase().endsWith( "-plugin" )
             && !"org.apache.maven.plugins".equals( project.getGroupId() ) )
         {
             getLog().error( LS + LS + "Artifact Ids of the format maven-___-plugin are reserved for" + LS
@@ -239,29 +99,8 @@ public abstract class AbstractGeneratorMojo
                                 + "In the future this error will break the build." + LS + LS );
         }
 
-        if ( checkExpectedProvidedScope )
-        {
-            Set<Artifact> wrongScopedArtifacts = dependenciesNotInProvidedScope();
-            if ( !wrongScopedArtifacts.isEmpty() )
-            {
-                StringBuilder errorMessage = new StringBuilder(
-                        LS + LS + "Some dependencies of Maven Plugins are expected to be in provided scope." + LS
-                        + "Please make sure that dependencies listed below declared in POM" + LS
-                        + "have set '<scope>provided</scope>' as well." + LS + LS
-                        + "The following dependencies are in wrong scope:" + LS
-                );
-                for ( Artifact artifact : wrongScopedArtifacts )
-                {
-                    errorMessage.append( " * " ).append( artifact ).append( LS );
-                }
-                errorMessage.append( LS ).append( LS );
-
-                getLog().error( errorMessage.toString() );
-            }
-        }
-
         String defaultGoalPrefix = getDefaultGoalPrefix( project );
-          
+
         if ( goalPrefix == null )
         {
             goalPrefix = defaultGoalPrefix;
@@ -273,67 +112,7 @@ public abstract class AbstractGeneratorMojo
                     + defaultGoalPrefix + "'." + LS );
         }
 
-        mojoScanner.setActiveExtractors( extractors );
-
-        // TODO: could use this more, eg in the writing of the plugin descriptor!
-        PluginDescriptor pluginDescriptor = new PluginDescriptor();
-
-        pluginDescriptor.setGroupId( project.getGroupId() );
-
-        pluginDescriptor.setArtifactId( project.getArtifactId() );
-
-        pluginDescriptor.setVersion( project.getVersion() );
-
-        pluginDescriptor.setGoalPrefix( goalPrefix );
-
-        pluginDescriptor.setName( project.getName() );
-
-        pluginDescriptor.setDescription( project.getDescription() );
-
-        if ( encoding == null || encoding.length() < 1 )
-        {
-            getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
-                               + " actually) to read mojo source files, i.e. build is platform dependent!" );
-        }
-        else
-        {
-            getLog().info( "Using '" + encoding + "' encoding to read mojo source files." );
-        }
-
-        try
-        {
-            List<ComponentDependency> deps = GeneratorUtils.toComponentDependencies( project.getArtifacts() );
-            pluginDescriptor.setDependencies( deps );
-
-            PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
-            request.setEncoding( encoding );
-            request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
-            request.setDependencies( filterMojoDependencies() );
-            request.setLocal( this.local );
-            request.setRemoteRepos( this.remoteRepos );
-
-            mojoScanner.populatePluginDescriptor( request );
-
-            File outputDirectory = getOutputDirectory();
-            outputDirectory.mkdirs();
-
-            createGenerator().execute( outputDirectory, request );
-            buildContext.refresh( outputDirectory );
-        }
-        catch ( GeneratorException e )
-        {
-            throw new MojoExecutionException( "Error writing plugin descriptor", e );
-        }
-        catch ( InvalidPluginDescriptorException | ExtractionException e )
-        {
-            throw new MojoExecutionException( "Error extracting plugin descriptor: '" + e.getLocalizedMessage() + "'",
-                                              e );
-        }
-        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 );
-        }
+        generate();
     }
 
     static String getDefaultGoalPrefix( MavenProject project )
@@ -349,61 +128,4 @@ public abstract class AbstractGeneratorMojo
         }
         return defaultGoalPrefix;
     }
-
-    /**
-     * Collects all dependencies expected to be in "provided" scope but are NOT in "provided" scope.
-     */
-    private Set<Artifact> dependenciesNotInProvidedScope()
-    {
-        LinkedHashSet<Artifact> wrongScopedDependencies = new LinkedHashSet<>();
-
-        for ( Artifact dependency : project.getArtifacts() )
-        {
-            String ga = dependency.getGroupId() + ":" + dependency.getArtifactId();
-            if ( expectedProvidedScopeGroupIds.contains( dependency.getGroupId() )
-                && !expectedProvidedScopeExclusions.contains( ga )
-                && !Artifact.SCOPE_PROVIDED.equals( dependency.getScope() ) )
-            {
-                wrongScopedDependencies.add( dependency );
-            }
-        }
-
-        return wrongScopedDependencies;
-    }
-
-    /**
-     * Get dependencies filtered with mojoDependencies configuration.
-     * 
-     * @return eventually filtered dependencies, or even <code>null</code> if configured with empty mojoDependencies
-     * list
-     * @see #mojoDependencies
-     */
-    private Set<Artifact> filterMojoDependencies()
-    {
-        Set<Artifact> filteredArtifacts;
-        if ( mojoDependencies == null )
-        {
-            filteredArtifacts = new LinkedHashSet<>( project.getArtifacts() );
-        }
-        else if ( mojoDependencies.size() == 0 )
-        {
-            filteredArtifacts = null;
-        }
-        else
-        {
-            filteredArtifacts = new LinkedHashSet<>();
-            
-            ArtifactFilter filter = new IncludesArtifactFilter( mojoDependencies );
-
-            for ( Artifact artifact : project.getArtifacts() )
-            {
-                if ( filter.include( artifact ) )
-                {
-                    filteredArtifacts.add( artifact );
-                }
-            }
-        }
-
-        return filteredArtifacts;
-    }
 }
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java
index 9827a77f..1a6f3298 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/DescriptorGeneratorMojo.java
@@ -20,13 +20,34 @@ package org.apache.maven.plugin.plugin;
  */
 
 import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.resolver.filter.IncludesArtifactFilter;
 import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugins.annotations.Component;
 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.plugins.annotations.ResolutionScope;
-import org.apache.maven.tools.plugin.generator.Generator;
+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.generator.GeneratorException;
+import org.apache.maven.tools.plugin.generator.GeneratorUtils;
 import org.apache.maven.tools.plugin.generator.PluginDescriptorGenerator;
+import org.apache.maven.tools.plugin.scanner.MojoScanner;
+import org.codehaus.plexus.component.repository.ComponentDependency;
+import org.codehaus.plexus.util.ReaderFactory;
+import org.sonatype.plexus.build.incremental.BuildContext;
 
 /**
  * <p>
@@ -51,7 +72,15 @@ public class DescriptorGeneratorMojo
      * The directory where the generated <code>plugin.xml</code> file will be put.
      */
     @Parameter( defaultValue = "${project.build.outputDirectory}/META-INF/maven", readonly = true )
-    protected File outputDirectory;
+    private File outputDirectory;
+
+    /**
+     * The file encoding of the source files.
+     *
+     * @since 2.5
+     */
+    @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
+    private String encoding;
 
     /**
      * A flag to disable generation of the <code>plugin.xml</code> in favor of a hand authored plugin descriptor.
@@ -62,36 +91,259 @@ public class DescriptorGeneratorMojo
     private boolean skipDescriptor;
 
     /**
-     * {@inheritDoc}
+     * <p>
+     * The role names of mojo extractors to use.
+     * </p>
+     * <p>
+     * If not set, all mojo extractors will be used. If set to an empty extractor name, no mojo extractors
+     * will be used.
+     * </p>
+     * Example:
+     * <pre>
+     *  &lt;!-- Use all mojo extractors --&gt;
+     *  &lt;extractors/&gt;
+     *
+     *  &lt;!-- Use no mojo extractors --&gt;
+     *  &lt;extractors&gt;
+     *      &lt;extractor/&gt;
+     *  &lt;/extractors&gt;
+     *
+     *  &lt;!-- Use only bsh mojo extractor --&gt;
+     *  &lt;extractors&gt;
+     *      &lt;extractor&gt;bsh&lt;/extractor&gt;
+     *  &lt;/extractors&gt;
+     * </pre>
      */
-    @Override
-    protected File getOutputDirectory()
-    {
-        return outputDirectory;
-    }
+    @Parameter
+    private Set<String> extractors;
+
 
     /**
-     * {@inheritDoc}
+     * 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
+     *
+     * @since 3.0
      */
-    @Override
-    protected Generator createGenerator()
-    {
-        return new PluginDescriptorGenerator( getLog() );
-    }
+    @Parameter( property = "maven.plugin.skipErrorNoDescriptorsFound", defaultValue = "false" )
+    private boolean skipErrorNoDescriptorsFound;
+
+    /**
+     * Flag controlling is "expected dependencies in provided scope" check to be performed or not. Default value:
+     * {@code true}.
+     *
+     * @since 3.6.3
+     */
+    @Parameter( defaultValue = "true", property = "maven.plugin.checkExpectedProvidedScope" )
+    private boolean checkExpectedProvidedScope = true;
+
+    /**
+     * List of {@code groupId} strings of artifact coordinates that are expected to be in "provided" scope. Default
+     * value: {@code ["org.apache.maven"]}.
+     *
+     * @since 3.6.3
+     */
+    @Parameter
+    private List<String> expectedProvidedScopeGroupIds = Collections.singletonList( "org.apache.maven" );
 
     /**
-     * {@inheritDoc}
+     * List of {@code groupId:artifactId} strings of artifact coordinates that are to be excluded from "expected
+     * provided scope" check. Default value: {@code ["org.apache.maven:maven-archiver", "org.apache.maven:maven-jxr"]}.
+     *
+     * @since 3.6.3
      */
-    @Override
-    public void execute()
+    @Parameter
+    private List<String> expectedProvidedScopeExclusions = Arrays.asList(
+        "org.apache.maven:maven-archiver",
+        "org.apache.maven:maven-jxr" );
+
+    /**
+     * Specify the dependencies as {@code groupId:artifactId} containing (abstract) Mojos, to filter
+     * dependencies scanned at runtime and focus on dependencies that are really useful to Mojo analysis.
+     * By default, the value is {@code null} and all dependencies are scanned (as before this parameter was added).
+     * If specified in the configuration with no children, no dependencies are scanned.
+     *
+     * @since 3.5
+     */
+    @Parameter
+    private List<String> mojoDependencies = null;
+
+    /**
+     * List of Remote Repositories used by the resolver
+     *
+     * @since 3.0
+     */
+    @Parameter( defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true )
+    private List<ArtifactRepository> remoteRepos;
+
+    /**
+     * Location of the local repository.
+     *
+     * @since 3.0
+     */
+    @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
+    private ArtifactRepository local;
+
+    /**
+     * The component used for scanning the source tree for mojos.
+     */
+    @Component
+    private MojoScanner mojoScanner;
+
+    @Component
+    protected BuildContext buildContext;
+
+    public void generate()
         throws MojoExecutionException
     {
+
         if ( skipDescriptor )
         {
+            getLog().warn( "Execution skipped" );
             return;
         }
 
-        super.execute();
+        if ( checkExpectedProvidedScope )
+        {
+            Set<Artifact> wrongScopedArtifacts = dependenciesNotInProvidedScope();
+            if ( !wrongScopedArtifacts.isEmpty() )
+            {
+                StringBuilder errorMessage = new StringBuilder(
+                    LS + LS + "Some dependencies of Maven Plugins are expected to be in provided scope." + LS
+                        + "Please make sure that dependencies listed below declared in POM" + LS
+                        + "have set '<scope>provided</scope>' as well." + LS + LS
+                        + "The following dependencies are in wrong scope:" + LS
+                );
+                for ( Artifact artifact : wrongScopedArtifacts )
+                {
+                    errorMessage.append( " * " ).append( artifact ).append( LS );
+                }
+                errorMessage.append( LS ).append( LS );
+
+                getLog().error( errorMessage.toString() );
+            }
+        }
+
+        mojoScanner.setActiveExtractors( extractors );
+
+        // TODO: could use this more, eg in the writing of the plugin descriptor!
+        PluginDescriptor pluginDescriptor = new PluginDescriptor();
+
+        pluginDescriptor.setGroupId( project.getGroupId() );
+
+        pluginDescriptor.setArtifactId( project.getArtifactId() );
+
+        pluginDescriptor.setVersion( project.getVersion() );
+
+        pluginDescriptor.setGoalPrefix( goalPrefix );
+
+        pluginDescriptor.setName( project.getName() );
+
+        pluginDescriptor.setDescription( project.getDescription() );
+
+        if ( encoding == null || encoding.length() < 1 )
+        {
+            getLog().warn( "Using platform encoding (" + ReaderFactory.FILE_ENCODING
+                               + " actually) to read mojo source files, i.e. build is platform dependent!" );
+        }
+        else
+        {
+            getLog().info( "Using '" + encoding + "' encoding to read mojo source files." );
+        }
+
+        try
+        {
+            List<ComponentDependency> deps = GeneratorUtils.toComponentDependencies( project.getArtifacts() );
+            pluginDescriptor.setDependencies( deps );
+
+            PluginToolsRequest request = new DefaultPluginToolsRequest( project, pluginDescriptor );
+            request.setEncoding( encoding );
+            request.setSkipErrorNoDescriptorsFound( skipErrorNoDescriptorsFound );
+            request.setDependencies( filterMojoDependencies() );
+            request.setLocal( this.local );
+            request.setRemoteRepos( this.remoteRepos );
+
+            mojoScanner.populatePluginDescriptor( request );
+
+            outputDirectory.mkdirs();
+
+            PluginDescriptorGenerator pluginDescriptorGenerator = new PluginDescriptorGenerator();
+            pluginDescriptorGenerator.execute( outputDirectory, request );
+
+            buildContext.refresh( outputDirectory );
+        }
+        catch ( GeneratorException e )
+        {
+            throw new MojoExecutionException( "Error writing plugin descriptor", e );
+        }
+        catch ( InvalidPluginDescriptorException | ExtractionException e )
+        {
+            throw new MojoExecutionException( "Error extracting plugin descriptor: '" + e.getLocalizedMessage() + "'",
+                                              e );
+        }
+        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 );
+        }
     }
 
+    /**
+     * Collects all dependencies expected to be in "provided" scope but are NOT in "provided" scope.
+     */
+    private Set<Artifact> dependenciesNotInProvidedScope()
+    {
+        LinkedHashSet<Artifact> wrongScopedDependencies = new LinkedHashSet<>();
+
+        for ( Artifact dependency : project.getArtifacts() )
+        {
+            String ga = dependency.getGroupId() + ":" + dependency.getArtifactId();
+            if ( expectedProvidedScopeGroupIds.contains( dependency.getGroupId() )
+                && !expectedProvidedScopeExclusions.contains( ga )
+                && !Artifact.SCOPE_PROVIDED.equals( dependency.getScope() ) )
+            {
+                wrongScopedDependencies.add( dependency );
+            }
+        }
+
+        return wrongScopedDependencies;
+    }
+
+    /**
+     * Get dependencies filtered with mojoDependencies configuration.
+     *
+     * @return eventually filtered dependencies, or even <code>null</code> if configured with empty mojoDependencies
+     * list
+     * @see #mojoDependencies
+     */
+    private Set<Artifact> filterMojoDependencies()
+    {
+        Set<Artifact> filteredArtifacts;
+        if ( mojoDependencies == null )
+        {
+            filteredArtifacts = new LinkedHashSet<>( project.getArtifacts() );
+        }
+        else if ( mojoDependencies.isEmpty() )
+        {
+            filteredArtifacts = null;
+        }
+        else
+        {
+            filteredArtifacts = new LinkedHashSet<>();
+
+            ArtifactFilter filter = new IncludesArtifactFilter( mojoDependencies );
+
+            for ( Artifact artifact : project.getArtifacts() )
+            {
+                if ( filter.include( artifact ) )
+                {
+                    filteredArtifacts.add( artifact );
+                }
+            }
+        }
+
+        return filteredArtifacts;
+    }
 }
diff --git a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
index 7cc472e5..2d8a2913 100644
--- a/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
+++ b/maven-plugin-plugin/src/main/java/org/apache/maven/plugin/plugin/HelpGeneratorMojo.java
@@ -19,7 +19,11 @@ package org.apache.maven.plugin.plugin;
  * under the License.
  */
 
+import javax.lang.model.SourceVersion;
+
 import java.io.File;
+import java.util.Arrays;
+import java.util.stream.Collectors;
 
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugins.annotations.Component;
@@ -27,19 +31,19 @@ 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.plugins.annotations.ResolutionScope;
-import org.apache.maven.tools.plugin.generator.Generator;
+import org.apache.maven.tools.plugin.generator.GeneratorException;
 import org.apache.maven.tools.plugin.generator.PluginHelpGenerator;
+import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.velocity.VelocityComponent;
 
 /**
  * Generates a <code>HelpMojo</code> class.
- * 
- * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
  *
+ * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
  * @since 2.4
  */
 @Mojo( name = "helpmojo", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true,
-                requiresDependencyResolution = ResolutionScope.COMPILE )
+       requiresDependencyResolution = ResolutionScope.COMPILE )
 public class HelpGeneratorMojo
     extends AbstractGeneratorMojo
 {
@@ -50,9 +54,14 @@ public class HelpGeneratorMojo
     protected File outputDirectory;
 
     /**
-     * The name of the package for the generated <code>HelpMojo</code>. By default, the package will be calculated based
-     * on the packages of the other plugin goals.
-     * 
+     * The name of the package for the generated <code>HelpMojo</code>.
+     * <p>
+     * By default, the package name will be calculated as <code>groupId + "." + artifactId</code> with additional
+     * <ul>
+     * <li><code>-</code> (dashes) will be replaced by <code>_</code> (underscores)</li>
+     * <li><code>_</code> (underscore) will be added before each number or Java keyword at the beginning of name</li>
+     * </ul>
+     *
      * @since 2.6
      */
     @Parameter
@@ -64,41 +73,59 @@ public class HelpGeneratorMojo
     @Component
     private VelocityComponent velocity;
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected File getOutputDirectory()
+    String getHelpPackageName()
     {
-        return outputDirectory;
+        String packageName = null;
+        if ( StringUtils.isNotBlank( helpPackageName ) )
+        {
+            packageName = helpPackageName;
+        }
+
+        if ( packageName == null )
+        {
+            packageName = project.getGroupId() + "." + project.getArtifactId();
+            packageName = packageName.replace( "-", "_" );
+
+            String[] packageItems = packageName.split( "\\." );
+            packageName = Arrays.stream( packageItems )
+                .map( this::prefixSpecialCase )
+                .collect( Collectors.joining( "." ) );
+        }
+
+        return packageName;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    protected Generator createGenerator()
+    private String prefixSpecialCase( String name )
     {
-        return new PluginHelpGenerator().setHelpPackageName( helpPackageName ).setVelocityComponent( this.velocity );
+        if ( SourceVersion.isKeyword( name ) || !Character.isJavaIdentifierStart( name.charAt( 0 ) ) )
+        {
+            name = "_" + name;
+        }
+        return name;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void execute()
-        throws MojoExecutionException
+    protected void generate() throws MojoExecutionException
     {
-        // force value for this plugin
-        skipErrorNoDescriptorsFound = true;
+        PluginHelpGenerator pluginHelpGenerator = new PluginHelpGenerator()
+            .setMavenProject( project )
+            .setHelpPackageName( getHelpPackageName() )
+            .setGoalPrefix( goalPrefix )
+            .setVelocityComponent( velocity );
 
-        super.execute();
+        try
+        {
+            pluginHelpGenerator.execute( outputDirectory );
+        }
+        catch ( GeneratorException e )
+        {
+            throw new MojoExecutionException( e.getMessage(), e );
+        }
 
-        if ( !project.getCompileSourceRoots().contains( outputDirectory.getAbsolutePath() ) && !skip )
+        if ( !project.getCompileSourceRoots().contains( outputDirectory.getAbsolutePath() ) )
         {
             project.addCompileSourceRoot( outputDirectory.getAbsolutePath() );
         }
-
     }
 
 }
diff --git a/maven-plugin-plugin/src/test/java/org/apache/maven/plugin/plugin/HelpGeneratorMojoTest.java b/maven-plugin-plugin/src/test/java/org/apache/maven/plugin/plugin/HelpGeneratorMojoTest.java
new file mode 100644
index 00000000..5d657091
--- /dev/null
+++ b/maven-plugin-plugin/src/test/java/org/apache/maven/plugin/plugin/HelpGeneratorMojoTest.java
@@ -0,0 +1,63 @@
+package org.apache.maven.plugin.plugin;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.stream.Stream;
+
+import org.apache.maven.project.MavenProject;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class HelpGeneratorMojoTest
+{
+
+    public static Stream<Arguments> packageNameShouldBeCorrect()
+    {
+        return Stream.of(
+            Arguments.of( aProject( "groupId", "artifactId" ), "groupId.artifactId" ),
+            Arguments.of( aProject( "groupId", "123-artifactId" ), "groupId._123_artifactId" ),
+            Arguments.of( aProject( "group-Id", "artifact-Id" ), "group_Id.artifact_Id" ),
+            Arguments.of( aProject( "group-Id", "int" ), "group_Id._int" )
+        );
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void packageNameShouldBeCorrect( MavenProject project, String expectedPackageName )
+    {
+        HelpGeneratorMojo mojo = new HelpGeneratorMojo();
+        mojo.project = project;
+
+        String packageName = mojo.getHelpPackageName();
+        assertEquals( expectedPackageName, packageName );
+    }
+
+    private static MavenProject aProject( String groupId, String artifactId )
+    {
+
+        MavenProject mavenProject = new MavenProject();
+        mavenProject.setGroupId( groupId );
+        mavenProject.setArtifactId( artifactId );
+        return mavenProject;
+    }
+}
diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java
index 6e777c08..70581131 100644
--- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java
+++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorGenerator.java
@@ -19,8 +19,6 @@ package org.apache.maven.tools.plugin.generator;
  * under the License.
  */
 
-import static java.nio.charset.StandardCharsets.UTF_8;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -31,12 +29,11 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException;
+
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.Parameter;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.plugin.descriptor.Requirement;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
@@ -45,6 +42,8 @@ import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
 import org.codehaus.plexus.util.xml.XMLWriter;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 /**
  * Generate a <a href="/ref/current/maven-plugin-api/plugin.html">Maven Plugin Descriptor XML file</a> and
  * corresponding <code>plugin-help.xml</code> help content for {@link PluginHelpGenerator}.
@@ -54,20 +53,10 @@ public class PluginDescriptorGenerator
     implements Generator
 {
 
-    private final Log log;
-
-    public PluginDescriptorGenerator( Log log )
-    {
-        this.log = log;
-    }
-
     @Override
     public void execute( File destinationDirectory, PluginToolsRequest request )
         throws GeneratorException
     {
-        // eventually rewrite help mojo class to match actual package name
-        PluginHelpGenerator.rewriteHelpMojo( request, log );
-
         try
         {
             // write complete plugin.xml descriptor
@@ -86,10 +75,6 @@ public class PluginDescriptorGenerator
         {
             throw new GeneratorException( e.getMessage(), e );
         }
-        catch ( DuplicateMojoDescriptorException e )
-        {
-            throw new GeneratorException( e.getMessage(), e );
-        }
     }
 
     private String getVersion()
@@ -100,7 +85,7 @@ public class PluginDescriptorGenerator
     }
 
     public void writeDescriptor( File destinationFile, PluginToolsRequest request, boolean helpDescriptor )
-        throws IOException, DuplicateMojoDescriptorException
+        throws IOException
     {
         PluginDescriptor pluginDescriptor = request.getPluginDescriptor();
 
@@ -169,11 +154,6 @@ public class PluginDescriptorGenerator
         }
     }
 
-    protected void processMojoDescriptor( MojoDescriptor mojoDescriptor, XMLWriter w )
-    {
-        processMojoDescriptor( mojoDescriptor, w, false );
-    }
-
     /**
      * @param mojoDescriptor not null
      * @param w              not null
diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java
index d430e5a0..9149712c 100644
--- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java
+++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginHelpGenerator.java
@@ -19,79 +19,42 @@ package org.apache.maven.tools.plugin.generator;
  * under the License.
  */
 
-import static java.nio.charset.StandardCharsets.UTF_8;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
 
-import org.apache.maven.plugin.descriptor.MojoDescriptor;
-import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
-import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.velocity.VelocityContext;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.logging.console.ConsoleLogger;
 import org.codehaus.plexus.util.FileUtils;
-import org.codehaus.plexus.util.IOUtil;
-import org.codehaus.plexus.util.PropertyUtils;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.velocity.VelocityComponent;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.commons.ClassRemapper;
-import org.objectweb.asm.commons.Remapper;
-import org.objectweb.asm.commons.SimpleRemapper;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.Properties;
+import static java.nio.charset.StandardCharsets.UTF_8;
 
 /**
  * Generates an <code>HelpMojo</code> class from <code>help-class-source.vm</code> template.
  * The generated mojo reads help content from <code>META-INF/maven/${groupId}/${artifactId}/plugin-help.xml</code>
  * resource, which is generated by this {@link PluginDescriptorGenerator}.
- * <p>Notice that the help mojo source needs to be generated before compilation, but when Java annotations are used,
- * plugin descriptor content is available only after compilation (detecting annotations in .class files):
- * help mojo source can be generated with empty package only (and no plugin descriptor available yet), then needs
- * to be updated after compilation - through {@link #rewriteHelpMojo(PluginToolsRequest, Log)} which is called from
- * plugin descriptor XML generation.</p>
  *
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
  * @since 2.4
  */
 public class PluginHelpGenerator
     extends AbstractLogEnabled
-    implements Generator
 {
     /**
      * Default generated class name
      */
     private static final String HELP_MOJO_CLASS_NAME = "HelpMojo";
 
-    /**
-     * Help properties file, to store data about generated source.
-     */
-    private static final String HELP_PROPERTIES_FILENAME = "maven-plugin-help.properties";
-
-    /**
-     * Default goal
-     */
-    private static final String HELP_GOAL = "help";
-
     private String helpPackageName;
-
-    private boolean useAnnotations;
-
+    private String goalPrefix;
+    private MavenProject mavenProject;
     private VelocityComponent velocityComponent;
 
     /**
@@ -106,41 +69,10 @@ public class PluginHelpGenerator
     // Public methods
     // ----------------------------------------------------------------------
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void execute( File destinationDirectory, PluginToolsRequest request )
+    public void execute( File destinationDirectory )
         throws GeneratorException
     {
-        PluginDescriptor pluginDescriptor = request.getPluginDescriptor();
-
-        String helpImplementation = getImplementation( pluginDescriptor );
-
-        List<MojoDescriptor> mojoDescriptors = pluginDescriptor.getMojos();
-
-        if ( mojoDescriptors != null )
-        {
-            // Verify that no help goal already exists
-            MojoDescriptor descriptor = pluginDescriptor.getMojo( HELP_GOAL );
-
-            if ( ( descriptor != null ) && !descriptor.getImplementation().equals( helpImplementation ) )
-            {
-                if ( getLogger().isWarnEnabled() )
-                {
-                    getLogger().warn( "\n\nA help goal (" + descriptor.getImplementation()
-                                          + ") already exists in this plugin. SKIPPED THE " + helpImplementation
-                                          + " GENERATION.\n" );
-                }
-
-                return;
-            }
-        }
-
-        writeHelpPropertiesFile( request, destinationDirectory );
-
-        useAnnotations = request.getProject().getArtifactMap().containsKey(
-            "org.apache.maven.plugin-tools:maven-plugin-annotations" );
+        String helpImplementation = getImplementation();
 
         try
         {
@@ -150,9 +82,9 @@ public class PluginHelpGenerator
             helpClass.getParentFile().mkdirs();
 
             String helpClassSources =
-                getHelpClassSources( getPluginHelpPath( request.getProject() ), pluginDescriptor );
+                getHelpClassSources( getPluginHelpPath( mavenProject ) );
 
-            FileUtils.fileWrite( helpClass, request.getEncoding(), helpClassSources );
+            FileUtils.fileWrite( helpClass, UTF_8.name(), helpClassSources );
         }
         catch ( IOException e )
         {
@@ -166,14 +98,21 @@ public class PluginHelpGenerator
         return this;
     }
 
-    public VelocityComponent getVelocityComponent()
+    public PluginHelpGenerator setVelocityComponent( VelocityComponent velocityComponent )
     {
-        return velocityComponent;
+        this.velocityComponent = velocityComponent;
+        return this;
     }
 
-    public PluginHelpGenerator setVelocityComponent( VelocityComponent velocityComponent )
+    public PluginHelpGenerator setGoalPrefix( String goalPrefix )
     {
-        this.velocityComponent = velocityComponent;
+        this.goalPrefix = goalPrefix;
+        return this;
+    }
+
+    public PluginHelpGenerator setMavenProject( MavenProject mavenProject )
+    {
+        this.mavenProject = mavenProject;
         return this;
     }
 
@@ -181,21 +120,17 @@ public class PluginHelpGenerator
     // Private methods
     // ----------------------------------------------------------------------
 
-    private String getHelpClassSources( String pluginHelpPath, PluginDescriptor pluginDescriptor )
+    private String getHelpClassSources( String pluginHelpPath )
         throws IOException
     {
         VelocityContext context = new VelocityContext();
-        if ( this.helpPackageName != null )
-        {
-            context.put( "helpPackageName", this.helpPackageName );
-        }
-        else
-        {
-            context.put( "helpPackageName", "" );
-        }
+        boolean useAnnotations = mavenProject.getArtifactMap().containsKey(
+            "org.apache.maven.plugin-tools:maven-plugin-annotations" );
+
+        context.put( "helpPackageName", helpPackageName );
         context.put( "pluginHelpPath", pluginHelpPath );
-        context.put( "artifactId", pluginDescriptor.getArtifactId() );
-        context.put( "goalPrefix", pluginDescriptor.getGoalPrefix() );
+        context.put( "artifactId", mavenProject.getArtifactId() );
+        context.put( "goalPrefix", goalPrefix );
         context.put( "useAnnotations", useAnnotations );
 
         StringWriter stringWriter = new StringWriter();
@@ -214,226 +149,17 @@ public class PluginHelpGenerator
     }
 
     /**
-     * @param pluginDescriptor The descriptor of the plugin for which to generate a help goal, must not be
-     *                         <code>null</code>.
      * @return The implementation.
      */
-    private String getImplementation( PluginDescriptor pluginDescriptor )
+    private String getImplementation( )
     {
-        if ( StringUtils.isEmpty( helpPackageName ) )
-        {
-            helpPackageName = GeneratorUtils.discoverPackageName( pluginDescriptor );
-        }
-
         return StringUtils.isEmpty( helpPackageName )
             ? HELP_MOJO_CLASS_NAME
             : helpPackageName + '.' + HELP_MOJO_CLASS_NAME;
     }
 
-    /**
-     * Write help properties files for later use to eventually rewrite Help Mojo.
-     *
-     * @param request
-     * @throws GeneratorException
-     * @see {@link #rewriteHelpMojo(PluginToolsRequest, Log)}
-     */
-    private void writeHelpPropertiesFile( PluginToolsRequest request, File destinationDirectory )
-        throws GeneratorException
-    {
-        Properties properties = new Properties();
-        properties.put( "helpPackageName", helpPackageName == null ? "" : helpPackageName );
-        properties.put( "destinationDirectory", destinationDirectory.getAbsolutePath() );
-
-        File tmpPropertiesFile = new File( request.getProject().getBuild().getDirectory(), HELP_PROPERTIES_FILENAME );
-
-        if ( tmpPropertiesFile.exists() )
-        {
-            tmpPropertiesFile.delete();
-        }
-        else if ( !tmpPropertiesFile.getParentFile().exists() )
-        {
-            tmpPropertiesFile.getParentFile().mkdirs();
-        }
-
-        try ( FileOutputStream fos = new FileOutputStream( tmpPropertiesFile ) )
-        {
-            properties.store( fos, "maven plugin help mojo generation informations" );
-        }
-        catch ( IOException e )
-        {
-            throw new GeneratorException( e.getMessage(), e );
-        }
-    }
-
     static String getPluginHelpPath( MavenProject mavenProject )
     {
         return mavenProject.getGroupId() + "/" + mavenProject.getArtifactId() + "/plugin-help.xml";
     }
-
-    /**
-     * Rewrite Help Mojo to match actual Mojos package name if it was not available at source generation
-     * time. This is used at descriptor generation time.
-     *
-     * @param request
-     * @throws GeneratorException
-     */
-    static void rewriteHelpMojo( PluginToolsRequest request, Log log )
-        throws GeneratorException
-    {
-        File tmpPropertiesFile = new File( request.getProject().getBuild().getDirectory(), HELP_PROPERTIES_FILENAME );
-
-        if ( !tmpPropertiesFile.exists() )
-        {
-            return;
-        }
-
-        Properties properties;
-        try
-        {
-            properties = PropertyUtils.loadProperties( tmpPropertiesFile );
-        }
-        catch ( IOException e )
-        {
-            throw new GeneratorException( e.getMessage(), e );
-        }
-
-        String helpPackageName = properties.getProperty( "helpPackageName" );
-
-        // if helpPackageName property is empty, we have to rewrite the class with a better package name than empty
-        if ( StringUtils.isEmpty( helpPackageName ) )
-        {
-            String destDir = properties.getProperty( "destinationDirectory" );
-            File destinationDirectory;
-            if ( StringUtils.isEmpty( destDir ) )
-            {
-                // writeHelpPropertiesFile() creates 2 properties: find one without the other should not be possible
-                log.warn( "\n\nUnexpected situation: destinationDirectory not defined in " + HELP_PROPERTIES_FILENAME
-                              + " during help mojo source generation but expected during XML descriptor generation." );
-                log.warn( "Please check helpmojo goal version used in previous build phase." );
-                log.warn( "If you just upgraded to plugin-tools >= 3.2 you must run a clean build at least once." );
-                destinationDirectory = new File( "target/generated-sources/plugin" );
-                log.warn( "Trying default location: " + destinationDirectory );
-            }
-            else
-            {
-                destinationDirectory = new File( destDir );
-            }
-            String helpMojoImplementation = rewriteHelpClassToMojoPackage( request, destinationDirectory, log );
-
-            if ( helpMojoImplementation != null )
-            {
-                // rewrite plugin descriptor with new HelpMojo implementation class
-                updateHelpMojoDescriptor( request.getPluginDescriptor(), helpMojoImplementation );
-            }
-        }
-    }
-
-    private static String rewriteHelpClassToMojoPackage( PluginToolsRequest request, File destinationDirectory,
-                                                         Log log )
-        throws GeneratorException
-    {
-        String destinationPackage = GeneratorUtils.discoverPackageName( request.getPluginDescriptor() );
-        if ( StringUtils.isEmpty( destinationPackage ) )
-        {
-            return null;
-        }
-        String packageAsDirectory = StringUtils.replace( destinationPackage, '.', '/' );
-
-        String outputDirectory = request.getProject().getBuild().getOutputDirectory();
-        File helpClassFile = new File( outputDirectory, HELP_MOJO_CLASS_NAME + ".class" );
-        if ( !helpClassFile.exists() )
-        {
-            return null;
-        }
-
-        // rewrite help mojo source
-        File helpSourceFile = new File( destinationDirectory, HELP_MOJO_CLASS_NAME + ".java" );
-        if ( !helpSourceFile.exists() )
-        {
-            log.warn( "HelpMojo.java not found in default location: " + helpSourceFile.getAbsolutePath() );
-            log.warn( "Help goal source won't be moved to package: " + destinationPackage );
-        }
-        else
-        {
-            File helpSourceFileNew =
-                new File( destinationDirectory, packageAsDirectory + '/' + HELP_MOJO_CLASS_NAME + ".java" );
-            if ( !helpSourceFileNew.getParentFile().exists() )
-            {
-                helpSourceFileNew.getParentFile().mkdirs();
-            }
-            Charset encoding = Charset.forName( request.getEncoding() );
-            try ( Reader sourceReader = new InputStreamReader( new FileInputStream( helpSourceFile ), //
-                                                              encoding ); //
-                 PrintWriter sourceWriter = new PrintWriter(
-                     new OutputStreamWriter( new FileOutputStream( helpSourceFileNew ), //
-                                             encoding ) ) )
-            {
-                sourceWriter.println( "package " + destinationPackage + ";" );
-                IOUtil.copy( sourceReader, sourceWriter );
-            }
-            catch ( IOException e )
-            {
-                throw new GeneratorException( e.getMessage(), e );
-            }
-            helpSourceFileNew.setLastModified( helpSourceFile.lastModified() );
-            helpSourceFile.delete();
-        }
-
-        // rewrite help mojo .class
-        File rewriteHelpClassFile =
-            new File( outputDirectory + '/' + packageAsDirectory, HELP_MOJO_CLASS_NAME + ".class" );
-        if ( !rewriteHelpClassFile.getParentFile().exists() )
-        {
-            rewriteHelpClassFile.getParentFile().mkdirs();
-        }
-
-        ClassReader cr;
-        try ( FileInputStream fileInputStream = new FileInputStream( helpClassFile ) )
-        {
-            cr = new ClassReader( fileInputStream );
-        }
-        catch ( IOException e )
-        {
-            throw new GeneratorException( e.getMessage(), e );
-        }
-
-        ClassWriter cw = new ClassWriter( 0 );
-
-        Remapper packageRemapper =
-            new SimpleRemapper( HELP_MOJO_CLASS_NAME, packageAsDirectory + '/' + HELP_MOJO_CLASS_NAME );
-        ClassVisitor cv = new ClassRemapper( cw, packageRemapper );
-
-        try
-        {
-            cr.accept( cv, ClassReader.EXPAND_FRAMES );
-        }
-        catch ( Throwable e )
-        {
-            throw new GeneratorException( "ASM issue processing class-file " + helpClassFile.getPath(), e );
-        }
-
-        byte[] renamedClass = cw.toByteArray();
-        try ( FileOutputStream fos = new FileOutputStream( rewriteHelpClassFile ) )
-        {
-            fos.write( renamedClass );
-        }
-        catch ( IOException e )
-        {
-            throw new GeneratorException( "Error rewriting help class: " + e.getMessage(), e );
-        }
-
-        helpClassFile.delete();
-
-        return destinationPackage + ".HelpMojo";
-    }
-
-    private static void updateHelpMojoDescriptor( PluginDescriptor pluginDescriptor, String helpMojoImplementation )
-    {
-        MojoDescriptor mojoDescriptor = pluginDescriptor.getMojo( HELP_GOAL );
-
-        if ( mojoDescriptor != null )
-        {
-            mojoDescriptor.setImplementation( helpMojoImplementation );
-        }
-    }
 }
diff --git a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java b/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java
deleted file mode 100644
index e82453d0..00000000
--- a/maven-plugin-tools-generators/src/test/java/org/apache/maven/tools/plugin/generator/PluginHelpGeneratorTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.apache.maven.tools.plugin.generator;
-
-/*
- * 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 org.codehaus.plexus.testing.PlexusTest;
-import org.codehaus.plexus.velocity.VelocityComponent;
-
-/**
- * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
- */
-@PlexusTest
-public class PluginHelpGeneratorTest
-    extends AbstractGeneratorTestCase
-{
-
-    @Inject
-    VelocityComponent velocityComponent;
-
-    // inherits tests from base class
-    @Override
-    protected void setupGenerator()
-        throws Exception
-    {
-        generator = new PluginHelpGenerator().setVelocityComponent( velocityComponent );
-
-    }
-}
diff --git a/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java b/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java
index b804d2f8..e734dc7f 100644
--- a/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java
+++ b/maven-plugin-tools-java/src/test/java/org/apache/maven/tools/plugin/extractor/javadoc/JavaMojoDescriptorExtractorTest.java
@@ -128,7 +128,7 @@ public class JavaMojoDescriptorExtractorTest
             request.getPluginDescriptor().addMojo( mojoDescriptor );
         }
 
-        Generator descriptorGenerator = new PluginDescriptorGenerator( new SystemStreamLog() );
+        Generator descriptorGenerator = new PluginDescriptorGenerator();
 
         descriptorGenerator.execute( new File( root, directory ), request );
 
diff --git a/pom.xml b/pom.xml
index c1ea31da..943f5cc4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
   </distributionManagement>
 
   <properties>
-    <surefire.version>2.22.2</surefire.version>
+    <surefire.version>3.0.0-M7</surefire.version>
     <javaVersion>8</javaVersion>
     <pluginTestingHarnessVersion>3.3.0</pluginTestingHarnessVersion>
     <mavenVersion>3.2.5</mavenVersion>
@@ -247,10 +247,11 @@
         <scope>test</scope>
       </dependency>
       <dependency>
-        <groupId>org.junit.jupiter</groupId>
-        <artifactId>junit-jupiter-engine</artifactId>
+        <groupId>org.junit</groupId>
+        <artifactId>junit-bom</artifactId>
         <version>5.8.2</version>
-        <scope>test</scope>
+        <type>pom</type>
+        <scope>import</scope>
       </dependency>
       <dependency>
         <groupId>org.codehaus.plexus</groupId>