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

[maven-plugin-tools] branch master updated: [MPLUGIN-425] Add required Java and Maven version to the generated plugin descriptor (#171)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new b9f7c23c [MPLUGIN-425] Add required Java and Maven version to the generated plugin descriptor (#171)
b9f7c23c is described below

commit b9f7c23c6235766d07d1d735b355b96193e242d5
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Wed Nov 9 10:52:43 2022 +0100

    [MPLUGIN-425] Add required Java and Maven version to the generated plugin descriptor (#171)
    
    Consider Java and Maven Prerequisites from plugin descriptor in plugin overview page
---
 .../src/it/java-basic-annotations/verify.groovy    |   3 +
 .../plugin/plugin/DescriptorGeneratorMojo.java     |  88 +++++++
 .../src/it/plugin-info-jdk-default-version/pom.xml |   5 +
 .../src/it/plugin-report/pom.xml                   |   2 +-
 .../src/it/plugin-report/verify.groovy             |   5 +-
 maven-plugin-report-plugin/src/it/settings.xml     |  12 +-
 .../maven/plugin/plugin/report/PluginReport.java   |  42 ++-
 .../EnhancedPluginDescriptorBuilder.java           |  29 ++-
 .../JavaAnnotationsMojoDescriptorExtractor.java    |  72 +++++-
 .../scanner/DefaultMojoAnnotationsScanner.java     |  33 ++-
 .../annotations/scanner/MojoAnnotatedClass.java    |  21 +-
 .../scanner/MojoAnnotationsScannerRequest.java     |  12 +
 .../scanner/visitors/MojoClassVisitor.java         |   8 +
 .../annotations/ClassVersionComparatorTest.java    |  26 +-
 .../tools/plugin/DefaultPluginToolsRequest.java    |  36 ++-
 .../maven/tools/plugin/ExtendedMojoDescriptor.java |  61 ++---
 .../tools/plugin/ExtendedPluginDescriptor.java     | 282 +++++++++++++++++++++
 .../maven/tools/plugin/PluginToolsRequest.java     |  30 +++
 .../plugin/extractor/MojoDescriptorExtractor.java  |  17 +-
 .../generator/PluginDescriptorFilesGenerator.java  |  15 ++
 pom.xml                                            |   3 +
 21 files changed, 723 insertions(+), 79 deletions(-)

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 4315bef7..b3f34ed8 100644
--- a/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
+++ b/maven-plugin-plugin/src/it/java-basic-annotations/verify.groovy
@@ -25,6 +25,9 @@ assert descriptorFile.isFile()
 
 def pluginDescriptor = new XmlParser().parse( descriptorFile );
 
+assert pluginDescriptor.requiredJavaVersion.text() == '1.8'
+assert pluginDescriptor.requiredMavenVersion.text() == '3.2.5'
+
 def mojo = pluginDescriptor.mojos.mojo.findAll{ it.goal.text() == "first" }[0]
 
 assert mojo.goal.text() == 'first'
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 0954a727..8adfd7ee 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
@@ -41,6 +41,7 @@ import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.settings.Settings;
 import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.apache.maven.tools.plugin.ExtendedPluginDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.extractor.ExtractionException;
 import org.apache.maven.tools.plugin.generator.GeneratorException;
@@ -70,6 +71,8 @@ import org.sonatype.plexus.build.incremental.BuildContext;
 public class DescriptorGeneratorMojo
     extends AbstractGeneratorMojo
 {
+    private static final String VALUE_AUTO = "auto";
+
     /**
      * The directory where the generated <code>plugin.xml</code> file will be put.
      */
@@ -235,6 +238,42 @@ public class DescriptorGeneratorMojo
     @Parameter( defaultValue = "${localRepository}", required = true, readonly = true )
     private ArtifactRepository local;
 
+    /**
+     * The required Java version to set in the plugin descriptor. This is evaluated by Maven 4 and ignored by earlier
+     * Maven versions. Can be either one of the following formats:
+     * 
+     * <ul>
+     * <li>One of the values as for <a href="https://maven.apache.org/pom.html#Activation">POM profile activation
+     * element {@code jdk}</a>, i.e. version ranges, version prefixes
+     * and negated version prefixes (starting with '!').</li>
+     * <li>{@code "auto"} to determine the minimum Java version from the binary class version being generated during
+     * compilation (determined by the extractor).</li>
+     * </ul>
+     * 
+     * @since 3.8.0
+     */
+    @Parameter( defaultValue = VALUE_AUTO )
+    String requiredJavaVersion;
+
+    /**
+     * The required Maven version to set in the plugin descriptor. This is evaluated by Maven 4 and ignored by earlier
+     * Maven versions. Can be either one of the following formats:
+     * 
+     * <ul>
+     * <li>A version range which specifies the supported Maven versions. It can either use the usual mathematical
+     * syntax like {@code "[2.0.10,2.1.0),[3.0,)"} or use a single version like {@code "2.2.1"}. The latter is a short
+     * form for {@code "[2.2.1,)"}, i.e. denotes the minimum version required.</li>
+     * <li>{@code "auto"} to determine the minimum Maven version from the POM's Maven prerequisite, or if not set the
+     * referenced Maven Plugin API version.</li>
+     * </ul>
+     * This value takes precedence over the 
+     * <a href="https://maven.apache.org/pom.html#Prerequisites">POM's Maven prerequisite</a> in Maven 4.
+     * 
+     * @since 3.8.0
+     */
+    @Parameter( defaultValue = VALUE_AUTO )
+    String requiredMavenVersion;
+
     /**
      * The component used for scanning the source tree for mojos.
      */
@@ -335,6 +374,7 @@ public class DescriptorGeneratorMojo
             request.setSettings( settings );
 
             mojoScanner.populatePluginDescriptor( request );
+            request.setPluginDescriptor( extendPluginDescriptor( request ) );
 
             outputDirectory.mkdirs();
 
@@ -361,6 +401,54 @@ public class DescriptorGeneratorMojo
         }
     }
 
+    private PluginDescriptor extendPluginDescriptor( PluginToolsRequest request )
+    {
+        ExtendedPluginDescriptor extendedPluginDescriptor = 
+                        new ExtendedPluginDescriptor( request.getPluginDescriptor() );
+        extendedPluginDescriptor.setRequiredJavaVersion( getRequiredJavaVersion( request ) );
+        extendedPluginDescriptor.setRequiredMavenVersion( getRequiredMavenVersion( request ) );
+        return extendedPluginDescriptor;
+    }
+
+    private String getRequiredMavenVersion( PluginToolsRequest request )
+    {
+        if ( !VALUE_AUTO.equals( requiredMavenVersion ) )
+        {
+            return requiredMavenVersion;
+        }
+        getLog().debug( "Trying to derive Maven version automatically from project prerequisites..." );
+        String requiredMavenVersion = project.getPrerequisites() != null ? project.getPrerequisites().getMaven()
+                                        : null;
+        if ( requiredMavenVersion == null )
+        {
+            getLog().debug( "Trying to derive Maven version automatically from referenced Maven Plugin API artifact "
+                            + "version..." );
+            requiredMavenVersion = request.getUsedMavenApiVersion();
+        }
+        if ( requiredMavenVersion == null )
+        {
+            getLog().warn( "Cannot determine the required Maven version automatically, it is recommended to "
+                + "configure some explicit value manually." );
+        }
+        return requiredMavenVersion;
+    }
+
+    private String getRequiredJavaVersion( PluginToolsRequest request )
+    {
+        if ( !VALUE_AUTO.equals( requiredJavaVersion ) )
+        {
+            return requiredJavaVersion;
+        }
+        String requiredJavaVersion = request.getRequiredJavaVersion();
+        if ( requiredJavaVersion == null )
+        {
+            getLog().warn( "Cannot determine the required Java version automatically, it is recommended to "
+                            + "configure some explicit value manually." );
+        }
+        
+        return requiredJavaVersion;
+    }
+
     /**
      * Collects all dependencies expected to be in "provided" scope but are NOT in "provided" scope.
      */
diff --git a/maven-plugin-report-plugin/src/it/plugin-info-jdk-default-version/pom.xml b/maven-plugin-report-plugin/src/it/plugin-info-jdk-default-version/pom.xml
index b78d1993..cf148d40 100644
--- a/maven-plugin-report-plugin/src/it/plugin-info-jdk-default-version/pom.xml
+++ b/maven-plugin-report-plugin/src/it/plugin-info-jdk-default-version/pom.xml
@@ -53,6 +53,11 @@ under the License.
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-plugin-plugin</artifactId>
           <version>@project.version@</version>
+          <configuration>
+            <extractors>
+              <extractor>java-javadoc</extractor><!-- this extractor does not generate automatic JDK/Maven requirements -->
+            </extractors>
+          </configuration>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
diff --git a/maven-plugin-report-plugin/src/it/plugin-report/pom.xml b/maven-plugin-report-plugin/src/it/plugin-report/pom.xml
index e665568d..424ecec8 100644
--- a/maven-plugin-report-plugin/src/it/plugin-report/pom.xml
+++ b/maven-plugin-report-plugin/src/it/plugin-report/pom.xml
@@ -69,7 +69,7 @@ under the License.
 
   <build>
     <plugins>
-    <plugin>
+      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.5.1</version>
diff --git a/maven-plugin-report-plugin/src/it/plugin-report/verify.groovy b/maven-plugin-report-plugin/src/it/plugin-report/verify.groovy
index 4e29ff06..f57200f2 100644
--- a/maven-plugin-report-plugin/src/it/plugin-report/verify.groovy
+++ b/maven-plugin-report-plugin/src/it/plugin-report/verify.groovy
@@ -25,5 +25,6 @@ assert pluginInfo.isFile()
 
 assert !pluginInfo.text.contains('Memory')
 assert !pluginInfo.text.contains('Disk Space')
-// missing prerequisites in pom
-assert pluginInfo.text.contains('No minimum requirement.')
+// check JDK and Maven requirements
+assert pluginInfo.text.contains('1.8')
+assert pluginInfo.text.contains('3.2.5')
diff --git a/maven-plugin-report-plugin/src/it/settings.xml b/maven-plugin-report-plugin/src/it/settings.xml
index 44480e37..b128a4e8 100644
--- a/maven-plugin-report-plugin/src/it/settings.xml
+++ b/maven-plugin-report-plugin/src/it/settings.xml
@@ -38,10 +38,12 @@ under the License.
           <id>local.central</id>
           <url>@localRepositoryUrl@</url>
           <releases>
-            <enabled>true</enabled>
+            <updatePolicy>always</updatePolicy>
+            <checksumPolicy>ignore</checksumPolicy>
           </releases>
           <snapshots>
-            <enabled>true</enabled>
+            <updatePolicy>always</updatePolicy>
+            <checksumPolicy>ignore</checksumPolicy>
           </snapshots>
         </repository>
       </repositories>
@@ -50,10 +52,12 @@ under the License.
           <id>local.central</id>
           <url>@localRepositoryUrl@</url>
           <releases>
-            <enabled>true</enabled>
+            <updatePolicy>always</updatePolicy>
+            <checksumPolicy>ignore</checksumPolicy>
           </releases>
           <snapshots>
-            <enabled>true</enabled>
+            <updatePolicy>always</updatePolicy>
+            <checksumPolicy>ignore</checksumPolicy>
           </snapshots>
         </pluginRepository>
       </pluginRepositories>
diff --git a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java
index 478cd30d..9eb7ac99 100644
--- a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java
+++ b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugin/plugin/report/PluginReport.java
@@ -49,6 +49,7 @@ import org.apache.maven.reporting.AbstractMavenReportRenderer;
 import org.apache.maven.reporting.MavenReportException;
 import org.apache.maven.rtinfo.RuntimeInformation;
 import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
+import org.apache.maven.tools.plugin.ExtendedPluginDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.generator.GeneratorException;
 import org.apache.maven.tools.plugin.generator.GeneratorUtils;
@@ -416,7 +417,7 @@ public class PluginReport
 
             startTable();
 
-            String maven = discoverMavenRequirement( project );
+            String maven = discoverMavenRequirement( project, pluginDescriptor );
             sink.tableRow();
             tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.maven" ) );
             tableCell( ( maven != null
@@ -424,7 +425,7 @@ public class PluginReport
                 : getBundle( locale ).getString( "report.plugin.systemrequirements.nominimum" ) ) );
             sink.tableRow_();
 
-            String jdk = discoverJdkRequirement( project );
+            String jdk = discoverJdkRequirement( project, pluginDescriptor );
             sink.tableRow();
             tableCell( getBundle( locale ).getString( "report.plugin.systemrequirements.jdk" ) );
             tableCell(
@@ -559,40 +560,57 @@ public class PluginReport
         }
 
         /**
-         * Try to lookup on the Maven prerequisites property.
+         * Tries to determine the Maven requirement from either the plugin descriptor or (if not set) from the 
+         * Maven prerequisites element in the POM.
          *
          * @param project      not null
+         * @param pluginDescriptor the plugin descriptor (not null)
          * @return the Maven version or null if not specified
          */
-        private static String discoverMavenRequirement( MavenProject project )
+        private static String discoverMavenRequirement( MavenProject project, PluginDescriptor pluginDescriptor )
         {
+            if ( StringUtils.isNotBlank( pluginDescriptor.getRequiredMavenVersion() ) )
+            {
+                return pluginDescriptor.getRequiredMavenVersion();
+            }
             return Optional.ofNullable( project.getPrerequisites() )
                 .map( Prerequisites::getMaven )
                 .orElse( null );
         }
 
         /**
+         * Tries to determine the JDK requirement from the following sources (until one is found)
          * <ol>
-         * <li>use configured jdk requirement</li>
-         * <li>use <code>target</code> configuration of <code>org.apache.maven.plugins:maven-compiler-plugin</code></li>
-         * <li>use <code>target</code> configuration of <code>org.apache.maven.plugins:maven-compiler-plugin</code> in
-         * <code>pluginManagement</code></li>
-         * <li>use <code>maven.compiler.target</code> property</li>
+         * <li>use JDK requirement from plugin descriptor</li>
+         * <li>use {@code release} configuration of {@code org.apache.maven.plugins:maven-compiler-plugin}</li>
+         * <li>use {@code maven.compiler.release<} property</li>
+         * <li>use {@code target} configuration of {@code org.apache.maven.plugins:maven-compiler-plugin}</li>
+         * <li>use {@code maven.compiler.target} property</li>
          * </ol>
          *
          * @param project      not null
+         * @param pluginDescriptor the plugin descriptor (not null)
          * @return the JDK version
          */
-        private static String discoverJdkRequirement( MavenProject project )
+        private static String discoverJdkRequirement( MavenProject project, PluginDescriptor pluginDescriptor )
         {
-
+            String jdk = null;
+            if ( pluginDescriptor instanceof ExtendedPluginDescriptor )
+            {
+                ExtendedPluginDescriptor extPluginDescriptor = (ExtendedPluginDescriptor) pluginDescriptor;
+                jdk = extPluginDescriptor.getRequiredJavaVersion();
+            }
+            if ( jdk != null )
+            {
+                return jdk;
+            }
             Plugin compiler = getCompilerPlugin( project.getBuild().getPluginsAsMap() );
             if ( compiler == null )
             {
                 compiler = getCompilerPlugin( project.getPluginManagement().getPluginsAsMap() );
             }
 
-            String jdk = getPluginParameter( compiler, "release" );
+            jdk = getPluginParameter( compiler, "release" );
             if ( jdk != null )
             {
                 return jdk;
diff --git a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java
index 8d3361a2..01810881 100644
--- a/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java
+++ b/maven-plugin-report-plugin/src/main/java/org/apache/maven/plugins/plugin/descriptor/EnhancedPluginDescriptorBuilder.java
@@ -25,10 +25,12 @@ import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.plugin.descriptor.PluginDescriptorBuilder;
 import org.apache.maven.rtinfo.RuntimeInformation;
 import org.apache.maven.tools.plugin.EnhancedParameterWrapper;
+import org.apache.maven.tools.plugin.ExtendedPluginDescriptor;
 import org.codehaus.plexus.configuration.PlexusConfiguration;
 import org.codehaus.plexus.configuration.PlexusConfigurationException;
 import org.apache.maven.plugin.plugin.report.PluginReport;
 
+import java.io.Reader;
 import java.net.URI;
 
 /**
@@ -36,11 +38,13 @@ import java.net.URI;
  * {@link org.apache.maven.tools.plugin.generator.PluginDescriptorFilesGenerator} and
  * used by {@link PluginReport}.
  * Populates the slightly extended {@link Parameter} object {@link EnhancedParameterWrapper}.
+ * In addition populates all (optional) elements added after Maven Plugin API 3.2.5.
  */
 public class EnhancedPluginDescriptorBuilder extends PluginDescriptorBuilder
 {
     private final boolean requireAddingMissingParameterSinceField;
-    
+    private PlexusConfiguration configuration;
+
     public EnhancedPluginDescriptorBuilder( RuntimeInformation rtInfo )
     {
         this( rtInfo.isMavenVersion( "[,3.3.9]" ) );
@@ -51,6 +55,29 @@ public class EnhancedPluginDescriptorBuilder extends PluginDescriptorBuilder
         this.requireAddingMissingParameterSinceField = requireAddingMissingParameterSinceField;
     }
 
+    /**
+     * Cache the returned configuration for additional evaluation in {@link #build(Reader, String)}.
+     */
+    @Override
+    public PlexusConfiguration buildConfiguration( Reader reader )
+        throws PlexusConfigurationException
+    {
+        configuration = super.buildConfiguration( reader );
+        return configuration;
+    }
+
+    @Override
+    public PluginDescriptor build( Reader reader, String source )
+        throws PlexusConfigurationException
+    {
+        PluginDescriptor pluginDescriptor = super.build( reader, source );
+        // elements added in plugin descriptor 1.1
+        ExtendedPluginDescriptor extendedPluginDescriptor = new ExtendedPluginDescriptor( pluginDescriptor );
+        extendedPluginDescriptor.setRequiredJavaVersion( configuration.getChild( "requiredJavaVersion" ).getValue() );
+        extendedPluginDescriptor.setRequiredMavenVersion( configuration.getChild( "requiredMavenVersion" ).getValue() );
+        return extendedPluginDescriptor;
+    }
+
     @Override
     public MojoDescriptor buildComponentDescriptor( PlexusConfiguration c, PluginDescriptor pluginDescriptor )
         throws PlexusConfigurationException
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 00b4a7fc..75b86560 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
@@ -31,11 +31,13 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.TreeSet;
@@ -52,6 +54,7 @@ import com.thoughtworks.qdox.model.JavaMethod;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
+import org.apache.maven.artifact.versioning.ComparableVersion;
 import org.apache.maven.plugin.descriptor.InvalidParameterException;
 import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
@@ -83,6 +86,7 @@ import org.codehaus.plexus.archiver.manager.ArchiverManager;
 import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.util.StringUtils;
+import org.objectweb.asm.Opcodes;
 
 /**
  * JavaMojoDescriptorExtractor, a MojoDescriptor extractor to read descriptors from java classes with annotations.
@@ -101,6 +105,36 @@ public class JavaAnnotationsMojoDescriptorExtractor
 
     private static final GroupKey GROUP_KEY = new GroupKey( GroupKey.JAVA_GROUP, 100 );
 
+    /**
+     * 
+     * @see <a href="https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-4.html#jvms-4.1">JVMS 4.1</a>
+     */
+    private static final Map<Integer, String> CLASS_VERSION_TO_JAVA_STRING;
+    static
+    {
+        CLASS_VERSION_TO_JAVA_STRING = new HashMap<>();
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_1, "1.1" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_2, "1.2" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_3, "1.3" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_4, "1.4" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_5, "1.5" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_6, "1.6" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_7, "1.7" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V1_8, "1.8" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V9, "9" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V10, "10" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V11, "11" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V12, "12" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V13, "13" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V14, "14" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V15, "15" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V16, "16" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V17, "17" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V18, "18" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V19, "19" );
+        CLASS_VERSION_TO_JAVA_STRING.put( Opcodes.V20, "20" );
+    }
+
     @Inject
     MojoAnnotationsScanner mojoAnnotationsScanner;
 
@@ -134,12 +168,46 @@ public class JavaAnnotationsMojoDescriptorExtractor
         return GROUP_KEY;
     }
 
+    /**
+     * Compares class file format versions.
+     * @see <a href="https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-4.html#jvms-4.1">JVMS 4.1</a>
+     *
+     */
+    @SuppressWarnings( "checkstyle:magicnumber" )
+    static final class ClassVersionComparator implements Comparator<Integer>
+    {
+        @Override
+        public int compare( Integer classVersion1, Integer classVersion2 )
+        {
+            // first compare major version (
+            int result = Integer.compare( classVersion1 & 0x00FF, classVersion2 & 0x00FF );
+            if ( result == 0 )
+            {
+                // compare minor version if major is equal
+                result = Integer.compare( classVersion1, classVersion2 );
+            }
+            return result;
+        }
+    }
+
     @Override
     public List<MojoDescriptor> execute( PluginToolsRequest request )
         throws ExtractionException, InvalidPluginDescriptorException
     {
         Map<String, MojoAnnotatedClass> mojoAnnotatedClasses = scanAnnotations( request );
 
+        Optional<Integer> maxClassVersion = mojoAnnotatedClasses.values().stream()
+                        .map( MojoAnnotatedClass::getClassVersion ).max( new ClassVersionComparator() );
+        if ( maxClassVersion.isPresent() )
+        {
+            String requiredJavaVersion = CLASS_VERSION_TO_JAVA_STRING.get( maxClassVersion.get() );
+            if ( StringUtils.isBlank( request.getRequiredJavaVersion() )
+                                      || new ComparableVersion( request.getRequiredJavaVersion() ).compareTo( 
+                                             new ComparableVersion( requiredJavaVersion ) ) < 0 )
+            {
+                request.setRequiredJavaVersion( requiredJavaVersion );
+            }
+        }
         JavaProjectBuilder builder = scanJavadoc( request, mojoAnnotatedClasses.values() );
         Map<String, JavaClass> javaClassesMap = discoverClasses( builder );
 
@@ -174,7 +242,9 @@ public class JavaAnnotationsMojoDescriptorExtractor
 
         mojoAnnotationsScannerRequest.setProject( request.getProject() );
 
-        return mojoAnnotationsScanner.scan( mojoAnnotationsScannerRequest );
+        Map<String, MojoAnnotatedClass> result = mojoAnnotationsScanner.scan( mojoAnnotationsScannerRequest );
+        request.setUsedMavenApiVersion( mojoAnnotationsScannerRequest.getMavenApiVersion() );
+        return result;
     }
 
     private JavaProjectBuilder scanJavadoc( PluginToolsRequest request,
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
index b681f8ec..b499428c 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/DefaultMojoAnnotationsScanner.java
@@ -22,6 +22,18 @@ package org.apache.maven.tools.plugin.extractor.annotations.scanner;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Execute;
@@ -44,18 +56,6 @@ import org.codehaus.plexus.util.reflection.ReflectorException;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.Type;
 
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
 /**
  * Mojo scanner with java annotations.
  *
@@ -85,12 +85,19 @@ public class DefaultMojoAnnotationsScanner
             for ( Artifact dependency : request.getDependencies() )
             {
                 scan( mojoAnnotatedClasses, dependency.getFile(), request.getIncludePatterns(), dependency, true );
+                if ( request.getMavenApiVersion() == null
+                     && dependency.getArtifactId().equals( "maven-plugin-api" )
+                     && dependency.getGroupId().equals( "org.apache.maven" ) )
+                {
+                    request.setMavenApiVersion( dependency.getVersion() );
+                }
             }
 
             for ( File classDirectory : request.getClassesDirectories() )
             {
                 scan( mojoAnnotatedClasses, classDirectory, request.getIncludePatterns(),
                       request.getProject().getArtifact(), false );
+                
             }
         }
         catch ( IOException e )
@@ -210,7 +217,6 @@ public class DefaultMojoAnnotationsScanner
         throws IOException, ExtractionException
     {
         MojoClassVisitor mojoClassVisitor = new MojoClassVisitor( );
-
         try
         {
             ClassReader rdr = new ClassReader( is );
@@ -254,6 +260,7 @@ public class DefaultMojoAnnotationsScanner
             }
             mojoAnnotatedClass.setArtifact( artifact );
             mojoAnnotatedClasses.put( mojoAnnotatedClass.getClassName(), mojoAnnotatedClass );
+            mojoAnnotatedClass.setClassVersion( mojoClassVisitor.getVersion() );
         }
     }
 
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java
index ab5f5b15..95146839 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotatedClass.java
@@ -19,15 +19,15 @@ package org.apache.maven.tools.plugin.extractor.annotations.scanner;
  * under the License.
  */
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ComponentAnnotationContent;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ExecuteAnnotationContent;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.MojoAnnotationContent;
 import org.apache.maven.tools.plugin.extractor.annotations.datamodel.ParameterAnnotationContent;
 
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * @author Olivier Lamy
  * @since 3.0
@@ -36,6 +36,8 @@ public class MojoAnnotatedClass
 {
     private String className;
 
+    private int classVersion;
+
     private String parentClassName;
 
     private MojoAnnotationContent mojo;
@@ -73,6 +75,17 @@ public class MojoAnnotatedClass
         return this;
     }
 
+    public int getClassVersion()
+    {
+        return classVersion;
+    }
+
+    public MojoAnnotatedClass setClassVersion( int classVersion )
+    {
+        this.classVersion = classVersion;
+        return this;
+    }
+
     public MojoAnnotationContent getMojo()
     {
         return mojo;
@@ -157,6 +170,7 @@ public class MojoAnnotatedClass
         final StringBuilder sb = new StringBuilder();
         sb.append( "MojoAnnotatedClass" );
         sb.append( "{className='" ).append( className ).append( '\'' );
+        sb.append( ", classVersion=" ).append( classVersion );
         sb.append( ", parentClassName='" ).append( parentClassName ).append( '\'' );
         sb.append( ", mojo=" ).append( mojo );
         sb.append( ", execute=" ).append( execute );
@@ -165,4 +179,5 @@ public class MojoAnnotatedClass
         sb.append( '}' );
         return sb.toString();
     }
+
 }
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java
index 5a27cbd5..55611eeb 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/MojoAnnotationsScannerRequest.java
@@ -45,6 +45,8 @@ public class MojoAnnotationsScannerRequest
 
     private MavenProject project;
 
+    private String mavenApiVersion;
+
     public MojoAnnotationsScannerRequest()
     {
         // no o
@@ -99,4 +101,14 @@ public class MojoAnnotationsScannerRequest
     {
         this.project = project;
     }
+
+    public String getMavenApiVersion()
+    {
+        return mavenApiVersion;
+    }
+
+    public void setMavenApiVersion( String mavenApiVersion )
+    {
+        this.mavenApiVersion = mavenApiVersion;
+    }
 }
diff --git a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
index 6267d64f..359cda68 100644
--- a/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
+++ b/maven-plugin-tools-annotations/src/main/java/org/apache/maven/tools/plugin/extractor/annotations/scanner/visitors/MojoClassVisitor.java
@@ -58,6 +58,8 @@ public class MojoClassVisitor
 
     private List<MojoMethodVisitor> methodVisitors = new ArrayList<>();
 
+    private int version;
+
     public MojoClassVisitor()
     {
         super( Opcodes.ASM9 );
@@ -68,6 +70,11 @@ public class MojoClassVisitor
         return mojoAnnotatedClass;
     }
 
+    public int getVersion()
+    {
+        return version;
+    }
+
     public MojoAnnotationVisitor getAnnotationVisitor( Class<?> annotation )
     {
         return annotationVisitorMap.get( annotation.getName() );
@@ -97,6 +104,7 @@ public class MojoClassVisitor
     @Override
     public void visit( int version, int access, String name, String signature, String superName, String[] interfaces )
     {
+        this.version = version;
         mojoAnnotatedClass = new MojoAnnotatedClass();
         mojoAnnotatedClass.setClassName( Type.getObjectType( name ).getClassName() );
         if ( superName != null )
diff --git a/maven-plugin-report-plugin/src/it/plugin-report/verify.groovy b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ClassVersionComparatorTest.java
similarity index 53%
copy from maven-plugin-report-plugin/src/it/plugin-report/verify.groovy
copy to maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ClassVersionComparatorTest.java
index 4e29ff06..7609e19b 100644
--- a/maven-plugin-report-plugin/src/it/plugin-report/verify.groovy
+++ b/maven-plugin-tools-annotations/src/test/java/org/apache/maven/tools/plugin/extractor/annotations/ClassVersionComparatorTest.java
@@ -1,3 +1,5 @@
+package org.apache.maven.tools.plugin.extractor.annotations;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -17,13 +19,21 @@
  * under the License.
  */
 
-assert new File( basedir, 'target/site/noop-mojo.html' ).isFile()
-assert new File( basedir, 'target/site/report-mojo.html' ).isFile()
+import java.util.Comparator;
+
+import net.bytebuddy.jar.asm.Opcodes;
+import org.junit.jupiter.api.Test;
 
-def pluginInfo = new File( basedir, 'target/site/plugin-info.html' )
-assert pluginInfo.isFile()
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
-assert !pluginInfo.text.contains('Memory')
-assert !pluginInfo.text.contains('Disk Space')
-// missing prerequisites in pom
-assert pluginInfo.text.contains('No minimum requirement.')
+class ClassVersionComparatorTest
+{
+    @Test
+    void testComparator()
+    {
+        Comparator<Integer> comparator = new JavaAnnotationsMojoDescriptorExtractor.ClassVersionComparator();
+        assertEquals( 0, Integer.signum( comparator.compare( Opcodes.V10, Opcodes.V10 ) ) );
+        assertEquals( 1, Integer.signum( comparator.compare( Opcodes.V11, Opcodes.V10 ) ) );
+        assertEquals( -1, Integer.signum( comparator.compare( Opcodes.V9, Opcodes.V10 ) ) );
+    }
+}
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java
index f7b937ea..d3d4d352 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/DefaultPluginToolsRequest.java
@@ -61,13 +61,17 @@ public class DefaultPluginToolsRequest
     private ArtifactRepository local;
 
     private URI internalJavadocBaseUrl;
-    
+
     private String internalJavadocVersion;
-    
+
     private List<URI> externalJavadocBaseUrls;
 
     private Settings settings;
 
+    private String requiredJavaVersion;
+
+    private String mavenApiVersion;
+
     public DefaultPluginToolsRequest( MavenProject project, PluginDescriptor pluginDescriptor )
     {
         this.project = project;
@@ -252,4 +256,32 @@ public class DefaultPluginToolsRequest
     {
         return settings;
     }
+
+    @Override
+    public PluginToolsRequest setRequiredJavaVersion( String requiredJavaVersion )
+    {
+        this.requiredJavaVersion = requiredJavaVersion;
+        return this;
+    }
+    
+    @Override
+    public String getRequiredJavaVersion()
+    {
+        return requiredJavaVersion;
+    }
+
+    @Override
+    public PluginToolsRequest setUsedMavenApiVersion( String mavenApiVersion )
+    {
+        this.mavenApiVersion = mavenApiVersion;
+        return this;
+    }
+
+    @Override
+    public String getUsedMavenApiVersion()
+    {
+        return mavenApiVersion;
+    }
+
+    
 }
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java
index 7a54c456..0ab5b439 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedMojoDescriptor.java
@@ -19,11 +19,14 @@ package org.apache.maven.tools.plugin;
  * under the License.
  */
 
+import java.util.Objects;
+
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.Parameter;
 
 /**
- * Extensions to MojoDescriptor added to Maven 3, then are not available when run under Maven2.
+ * Extensions to {@link MojoDescriptor} not supported by Maven 3.2.5.
+ * 
  * @author Kristian Rosenvold
  */
 public class ExtendedMojoDescriptor
@@ -31,10 +34,6 @@ public class ExtendedMojoDescriptor
 {
     private final boolean containsXhtmlTextValues;
 
-    private boolean threadSafe = false;
-
-    private String requiresDependencyCollection = null;
-
     public ExtendedMojoDescriptor()
     {
         this( false );
@@ -49,30 +48,6 @@ public class ExtendedMojoDescriptor
         this.containsXhtmlTextValues = containsXhtmlTextValues;
     }
 
-    @Override
-    public boolean isThreadSafe()
-    {
-        return threadSafe;
-    }
-
-    @Override
-    public void setThreadSafe( boolean threadSafe )
-    {
-        this.threadSafe = threadSafe;
-    }
-
-    @Override
-    public String getDependencyCollectionRequired()
-    {
-        return requiresDependencyCollection;
-    }
-
-    @Override
-    public void setDependencyCollectionRequired( String requiresDependencyCollection )
-    {
-        this.requiresDependencyCollection = requiresDependencyCollection;
-    }
-    
     /**
      * Indicates if the methods {@link #getDescription()}, {@link #getDeprecated()}, {@link Parameter#getDescription()}
      * and {@link Parameter#getDeprecated()} return XHTML values.
@@ -84,4 +59,32 @@ public class ExtendedMojoDescriptor
     {
         return containsXhtmlTextValues;
     }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + Objects.hash( containsXhtmlTextValues );
+        return result;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+        if ( !super.equals( obj ) )
+        {
+            return false;
+        }
+        if ( getClass() != obj.getClass() )
+        {
+            return false;
+        }
+        ExtendedMojoDescriptor other = (ExtendedMojoDescriptor) obj;
+        return containsXhtmlTextValues == other.containsXhtmlTextValues;
+    }
 }
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedPluginDescriptor.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedPluginDescriptor.java
new file mode 100644
index 00000000..f2f8c2d9
--- /dev/null
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/ExtendedPluginDescriptor.java
@@ -0,0 +1,282 @@
+package org.apache.maven.tools.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.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.descriptor.DuplicateMojoDescriptorException;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.plugin.lifecycle.Lifecycle;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+/**
+ * Extensions to {@link PluginDescriptor} not supported by Maven 3.2.5.
+ * This is a wrapper around an existing PluginDescriptor.
+ */
+public class ExtendedPluginDescriptor extends PluginDescriptor
+{
+    private final PluginDescriptor delegate;
+    private String requiredJavaVersion;
+
+    public ExtendedPluginDescriptor( PluginDescriptor delegate )
+    {
+        this.delegate = delegate;
+        // populate the fields feeding the final methods of ComponentSetDescriptor 
+        // which can't be overridden by this wrapper
+        this.setIsolatedRealm( delegate.isIsolatedRealm() );
+        this.setDependencies( delegate.getDependencies() );
+        this.setComponents( delegate.getComponents() );
+    }
+
+    public void setRequiredJavaVersion( String requiredJavaVersion )
+    {
+        this.requiredJavaVersion = requiredJavaVersion;
+    }
+
+    public String getRequiredJavaVersion()
+    {
+        return requiredJavaVersion;
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+        if ( !super.equals( obj ) )
+        {
+            return false;
+        }
+        if ( getClass() != obj.getClass() )
+        {
+            return false;
+        }
+        ExtendedPluginDescriptor other = (ExtendedPluginDescriptor) obj;
+        return Objects.equals( delegate, other.delegate )
+            && Objects.equals( requiredJavaVersion, other.requiredJavaVersion );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + Objects.hash( delegate, requiredJavaVersion );
+        return result;
+    }
+
+    /* -- START delegate methods --*/
+    public List<MojoDescriptor> getMojos()
+    {
+        return delegate.getMojos();
+    }
+
+    public void addMojo( MojoDescriptor mojoDescriptor )
+        throws DuplicateMojoDescriptorException
+    {
+        delegate.addMojo( mojoDescriptor );
+    }
+
+    public String getGroupId()
+    {
+        return delegate.getGroupId();
+    }
+
+    public void setGroupId( String groupId )
+    {
+        delegate.setGroupId( groupId );
+    }
+
+    public String getArtifactId()
+    {
+        return delegate.getArtifactId();
+    }
+
+    public void setArtifactId( String artifactId )
+    {
+        delegate.setArtifactId( artifactId );
+    }
+
+    public String getPluginLookupKey()
+    {
+        return delegate.getPluginLookupKey();
+    }
+
+    public String getId()
+    {
+        return delegate.getId();
+    }
+
+    public String getGoalPrefix()
+    {
+        return delegate.getGoalPrefix();
+    }
+
+    public void setGoalPrefix( String goalPrefix )
+    {
+        delegate.setGoalPrefix( goalPrefix );
+    }
+
+    public void setVersion( String version )
+    {
+        delegate.setVersion( version );
+    }
+
+    public String getVersion()
+    {
+        return delegate.getVersion();
+    }
+
+    public void setSource( String source )
+    {
+        delegate.setSource( source );
+    }
+
+    public String getSource()
+    {
+        return delegate.getSource();
+    }
+
+    public boolean isInheritedByDefault()
+    {
+        return delegate.isInheritedByDefault();
+    }
+
+    public void setInheritedByDefault( boolean inheritedByDefault )
+    {
+        delegate.setInheritedByDefault( inheritedByDefault );
+    }
+
+    public List<Artifact> getArtifacts()
+    {
+        return delegate.getArtifacts();
+    }
+
+    public void setArtifacts( List<Artifact> artifacts )
+    {
+        delegate.setArtifacts( artifacts );
+    }
+
+    public Map<String, Artifact> getArtifactMap()
+    {
+        return delegate.getArtifactMap();
+    }
+
+    public MojoDescriptor getMojo( String goal )
+    {
+        return delegate.getMojo( goal );
+    }
+
+    public void setClassRealm( ClassRealm classRealm )
+    {
+        delegate.setClassRealm( classRealm );
+    }
+
+    public ClassRealm getClassRealm()
+    {
+        return delegate.getClassRealm();
+    }
+
+    public void setIntroducedDependencyArtifacts( Set<Artifact> introducedDependencyArtifacts )
+    {
+        delegate.setIntroducedDependencyArtifacts( introducedDependencyArtifacts );
+    }
+
+    public Set<Artifact> getIntroducedDependencyArtifacts()
+    {
+        return delegate.getIntroducedDependencyArtifacts();
+    }
+
+    public void setName( String name )
+    {
+        delegate.setName( name );
+    }
+
+    public String getName()
+    {
+        return delegate.getName();
+    }
+
+    public void setDescription( String description )
+    {
+        delegate.setDescription( description );
+    }
+
+    public String getDescription()
+    {
+        return delegate.getDescription();
+    }
+
+    public void setRequiredMavenVersion( String requiredMavenVersion )
+    {
+        delegate.setRequiredMavenVersion( requiredMavenVersion );
+    }
+
+    public String getRequiredMavenVersion()
+    {
+        return delegate.getRequiredMavenVersion();
+    }
+
+    public void setPlugin( Plugin plugin )
+    {
+        delegate.setPlugin( plugin );
+    }
+
+    @Override
+    public Plugin getPlugin()
+    {
+        return delegate.getPlugin();
+    }
+
+    @Override
+    public Artifact getPluginArtifact()
+    {
+        return delegate.getPluginArtifact();
+    }
+
+    @Override
+    public void setPluginArtifact( Artifact pluginArtifact )
+    {
+        delegate.setPluginArtifact( pluginArtifact );
+    }
+
+    @Override
+    public Lifecycle getLifecycleMapping( String lifecycleId )
+        throws IOException, XmlPullParserException
+    {
+        return delegate.getLifecycleMapping( lifecycleId );
+    }
+
+    public PluginDescriptor clone()
+    {
+        return delegate.clone();
+    }
+
+}
diff --git a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java
index 9f740be7..a0721e80 100644
--- a/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java
+++ b/maven-plugin-tools-api/src/main/java/org/apache/maven/tools/plugin/PluginToolsRequest.java
@@ -197,4 +197,34 @@ public interface PluginToolsRequest
      * @since 3.7.0
      */
     Settings getSettings();
+    
+    /**
+     * 
+     * @param requiredJavaVersion the required java version for this plugin or {@code null} if unknown.
+     * @return This request.
+     * @since 3.8.0
+     */
+    PluginToolsRequest setRequiredJavaVersion( String requiredJavaVersion );
+
+    /**
+     * 
+     * @return the required java version for this plugin or {@code null} if unknown.
+     * @since 3.8.0
+     */
+    String getRequiredJavaVersion();
+
+    /**
+     * 
+     * @param mavenApiVersion
+     * @return his request.
+     * @since 3.8.0
+     */
+    PluginToolsRequest setUsedMavenApiVersion( String mavenApiVersion );
+
+    /**
+     * 
+     * @return the Maven API version being referenced or {@code null} if unknown
+     * @since 3.8.0
+     */
+    String getUsedMavenApiVersion();
 }
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 cbac0d5a..b9eef688 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
@@ -33,14 +33,14 @@ public interface MojoDescriptorExtractor
     /**
      * Returns the "name" (id) of the extractor.
      *
-     * @since TBD
+     * @since 3.7.0
      */
     String getName();
 
     /**
      * Returns {@code true} if extractor is deprecated.
      *
-     * @since TBD
+     * @since 3.7.0
      */
     boolean isDeprecated();
 
@@ -48,7 +48,7 @@ public interface MojoDescriptorExtractor
      * 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
+     * @since 3.7.0
      */
     GroupKey getGroupKey();
 
@@ -63,4 +63,15 @@ public interface MojoDescriptorExtractor
      */
     List<MojoDescriptor> execute( PluginToolsRequest request )
         throws ExtractionException, InvalidPluginDescriptorException;
+
+    /**
+     * The default implementation returns {@code null}.
+     * @return the required java version or {@code null} if unknown
+     *
+     * @since 3.8.0
+     */
+    default String getRequiredJavaVersion()
+    {
+        return null;
+    }
 }
\ No newline at end of file
diff --git a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
index cce415f0..493a1eba 100644
--- a/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
+++ b/maven-plugin-tools-generators/src/main/java/org/apache/maven/tools/plugin/generator/PluginDescriptorFilesGenerator.java
@@ -36,6 +36,7 @@ import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.plugin.descriptor.Requirement;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.tools.plugin.ExtendedMojoDescriptor;
+import org.apache.maven.tools.plugin.ExtendedPluginDescriptor;
 import org.apache.maven.tools.plugin.PluginToolsRequest;
 import org.apache.maven.tools.plugin.javadoc.JavadocLinkGenerator;
 import org.apache.maven.tools.plugin.util.PluginUtils;
@@ -163,6 +164,20 @@ public class PluginDescriptorFilesGenerator
 
                 GeneratorUtils.element( w, "inheritedByDefault",
                                         String.valueOf( pluginDescriptor.isInheritedByDefault() ) );
+
+                if ( pluginDescriptor instanceof ExtendedPluginDescriptor )
+                {
+                    ExtendedPluginDescriptor extPluginDescriptor = (ExtendedPluginDescriptor) pluginDescriptor;
+                    if ( StringUtils.isNotBlank( extPluginDescriptor.getRequiredJavaVersion() ) )
+                    {
+                        GeneratorUtils.element( w, "requiredJavaVersion", 
+                                                extPluginDescriptor.getRequiredJavaVersion() );
+                    }
+                }
+                if ( StringUtils.isNotBlank( pluginDescriptor.getRequiredMavenVersion() ) )
+                {
+                    GeneratorUtils.element( w, "requiredMavenVersion", pluginDescriptor.getRequiredMavenVersion() );
+                }
             }
 
             w.startElement( "mojos" );
diff --git a/pom.xml b/pom.xml
index 97dd2441..0f3c18e6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -100,6 +100,9 @@
     <slf4jVersion>1.7.5</slf4jVersion>
     <antVersion>1.10.12</antVersion>
     <maven.site.path>plugin-tools-archives/plugin-tools-LATEST</maven.site.path>
+    <!-- whenever the ASM version is updated also the 
+    maven-plugin-tools-annotations/src/main/java/o/a/m/tools/plugins/extractor/annotations/JavaAnnotationsMojoDescriptorExtractor#CLASS_VERSION_TO_JAVA_STRING 
+    needs to be updated as well -->
     <asmVersion>9.4</asmVersion>
     <doxiaVersion>1.11.1</doxiaVersion>
     <doxia-sitetoolsVersion>1.11.1</doxia-sitetoolsVersion>