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

sjaranowski pushed a commit to branch maven-3.9.x
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/maven-3.9.x by this push:
     new 3dd64abedb Allow a Maven plugin to require a Java version
3dd64abedb is described below

commit 3dd64abedbd7b19a6a9aaed0e46ab31993a09c3a
Author: Slawomir Jaranowski <[email protected]>
AuthorDate: Sat Nov 22 14:53:27 2025 +0100

    Allow a Maven plugin to require a Java version
    
    Introduced in Maven 4.0.0-alpha-3 - MNG-7566
    Plugin tools generate it since 3.8.1 - MPLUGIN-425
    
    As many plugins required newer JDK we can introduce it also for Maven 3.x 
for better error reporting
---
 .../maven/lifecycle/internal/MojoExecutor.java     |  2 +-
 .../maven/plugin/DefaultPluginDescriptorCache.java |  1 +
 .../apache/maven/plugin/MavenPluginManager.java    | 10 +++
 ...n.java => MavenPluginPrerequisitesChecker.java} | 22 ++++--
 .../maven/plugin/PluginIncompatibleException.java  |  6 +-
 .../plugin/internal/DefaultMavenPluginManager.java | 42 +++++++---
 .../MavenPluginJavaPrerequisiteChecker.java        | 67 ++++++++++++++++
 .../MavenPluginMavenPrerequisiteChecker.java       | 67 ++++++++++++++++
 .../internal/DefaultPluginVersionResolver.java     |  2 +-
 .../MavenPluginJavaPrerequisiteCheckerTest.java    | 40 ++++++++++
 .../maven/plugin/descriptor/PluginDescriptor.java  | 10 +++
 .../plugin/descriptor/PluginDescriptorBuilder.java |  7 ++
 maven-plugin-api/src/main/mdo/plugin.mdo           | 91 ++++++++++++----------
 13 files changed, 304 insertions(+), 63 deletions(-)

diff --git 
a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
 
b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
index dbda4149c4..cf40525c79 100644
--- 
a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
+++ 
b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoExecutor.java
@@ -184,7 +184,7 @@ private void execute(
         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
 
         try {
-            
mavenPluginManager.checkRequiredMavenVersion(mojoDescriptor.getPluginDescriptor());
+            
mavenPluginManager.checkPrerequisites(mojoDescriptor.getPluginDescriptor());
         } catch (PluginIncompatibleException e) {
             throw new LifecycleExecutionException(mojoExecution, 
session.getCurrentProject(), e);
         }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
index 25dbf929e8..37fb478f34 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/DefaultPluginDescriptorCache.java
@@ -104,6 +104,7 @@ protected static PluginDescriptor clone(PluginDescriptor 
original) {
             clone.setName(original.getName());
             clone.setDescription(original.getDescription());
             clone.setRequiredMavenVersion(original.getRequiredMavenVersion());
+            clone.setRequiredJavaVersion(original.getRequiredJavaVersion());
 
             
clone.setPluginArtifact(ArtifactUtils.copyArtifactSafe(original.getPluginArtifact()));
 
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java 
b/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java
index d4d30fa93c..06389c2633 100644
--- a/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java
+++ b/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginManager.java
@@ -71,9 +71,19 @@ MojoDescriptor getMojoDescriptor(
      * Verifies the specified plugin is compatible with the current Maven 
runtime.
      *
      * @param pluginDescriptor The descriptor of the plugin to check, must not 
be {@code null}.
+     * @deprecated Use {@link #checkPrerequisites(PluginDescriptor)} instead.
      */
+    @Deprecated
     void checkRequiredMavenVersion(PluginDescriptor pluginDescriptor) throws 
PluginIncompatibleException;
 
+    /**
+     * Verifies that the specified plugin's prerequisites are met.
+     *
+     * @param pluginDescriptor The descriptor of the plugin to check, must not 
be {@code null}.
+     * @since 3.9.12
+     */
+    void checkPrerequisites(PluginDescriptor pluginDescriptor) throws 
PluginIncompatibleException;
+
     /**
      * Sets up the class realm for the specified plugin. Both the class realm 
and the plugin artifacts that constitute
      * it will be stored in the plugin descriptor.
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginIncompatibleException.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginPrerequisitesChecker.java
similarity index 63%
copy from 
maven-core/src/main/java/org/apache/maven/plugin/PluginIncompatibleException.java
copy to 
maven-core/src/main/java/org/apache/maven/plugin/MavenPluginPrerequisitesChecker.java
index 1e2c26168b..46e9fe1346 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginIncompatibleException.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/MavenPluginPrerequisitesChecker.java
@@ -18,14 +18,22 @@
  */
 package org.apache.maven.plugin;
 
-import org.apache.maven.model.Plugin;
+import java.util.function.Consumer;
+
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
 
 /**
- * Signals a plugin which is not compatible with the current Maven runtime.
+ * Service responsible for checking if plugin's prerequisites are met.
+ *
+ * @since 3.9.12
  */
-public class PluginIncompatibleException extends PluginManagerException {
-
-    public PluginIncompatibleException(Plugin plugin, String message) {
-        super(plugin, message, (Throwable) null);
-    }
+@FunctionalInterface
+public interface MavenPluginPrerequisitesChecker extends 
Consumer<PluginDescriptor> {
+    /**
+     *
+     * @param pluginDescriptor
+     * @throws IllegalStateException in case the checked prerequisites are not 
met
+     */
+    @Override
+    void accept(PluginDescriptor pluginDescriptor);
 }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginIncompatibleException.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/PluginIncompatibleException.java
index 1e2c26168b..d3c5edbf95 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginIncompatibleException.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/PluginIncompatibleException.java
@@ -26,6 +26,10 @@
 public class PluginIncompatibleException extends PluginManagerException {
 
     public PluginIncompatibleException(Plugin plugin, String message) {
-        super(plugin, message, (Throwable) null);
+        this(plugin, message, null);
+    }
+
+    public PluginIncompatibleException(Plugin plugin, String message, 
Throwable cause) {
+        super(plugin, message, cause);
     }
 }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
index e33197aa96..b3ed212385 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
@@ -35,6 +35,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.jar.JarFile;
+import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 
 import org.apache.maven.RepositoryUtils;
@@ -49,6 +50,7 @@
 import org.apache.maven.plugin.ExtensionRealmCache;
 import org.apache.maven.plugin.InvalidPluginDescriptorException;
 import org.apache.maven.plugin.MavenPluginManager;
+import org.apache.maven.plugin.MavenPluginPrerequisitesChecker;
 import org.apache.maven.plugin.MavenPluginValidator;
 import org.apache.maven.plugin.Mojo;
 import org.apache.maven.plugin.MojoExecution;
@@ -169,6 +171,9 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
     @Requirement
     private PluginValidationManager pluginValidationManager;
 
+    @Requirement
+    private List<MavenPluginPrerequisitesChecker> prerequisitesCheckers;
+
     private ExtensionDescriptorBuilder extensionDescriptorBuilder = new 
ExtensionDescriptorBuilder();
 
     private PluginDescriptorBuilder builder = new PluginDescriptorBuilder();
@@ -279,22 +284,37 @@ public MojoDescriptor getMojoDescriptor(
         return mojoDescriptor;
     }
 
-    public void checkRequiredMavenVersion(PluginDescriptor pluginDescriptor) 
throws PluginIncompatibleException {
-        String requiredMavenVersion = 
pluginDescriptor.getRequiredMavenVersion();
-        if (StringUtils.isNotBlank(requiredMavenVersion)) {
+    @Override
+    public void checkPrerequisites(PluginDescriptor pluginDescriptor) throws 
PluginIncompatibleException {
+        List<IllegalStateException> prerequisiteExceptions = new ArrayList<>();
+        prerequisitesCheckers.forEach(c -> {
             try {
-                if (!runtimeInformation.isMavenVersion(requiredMavenVersion)) {
-                    throw new PluginIncompatibleException(
-                            pluginDescriptor.getPlugin(),
-                            "The plugin " + pluginDescriptor.getId() + " 
requires Maven version "
-                                    + requiredMavenVersion);
-                }
-            } catch (RuntimeException e) {
-                logger.warn("Could not verify plugin's Maven prerequisite: " + 
e.getMessage());
+                c.accept(pluginDescriptor);
+            } catch (IllegalStateException e) {
+                prerequisiteExceptions.add(e);
             }
+        });
+        // aggregate all exceptions
+        if (!prerequisiteExceptions.isEmpty()) {
+            String messages = prerequisiteExceptions.stream()
+                    .map(IllegalStateException::getMessage)
+                    .collect(Collectors.joining(", "));
+            PluginIncompatibleException pie = new PluginIncompatibleException(
+                    pluginDescriptor.getPlugin(),
+                    "The plugin " + pluginDescriptor.getId() + " has unmet 
prerequisites: " + messages,
+                    prerequisiteExceptions.get(0));
+            // the first exception is added as cause, all other ones as 
suppressed exceptions
+            
prerequisiteExceptions.stream().skip(1).forEach(pie::addSuppressed);
+            throw pie;
         }
     }
 
+    @Override
+    @Deprecated
+    public void checkRequiredMavenVersion(PluginDescriptor pluginDescriptor) 
throws PluginIncompatibleException {
+        checkPrerequisites(pluginDescriptor);
+    }
+
     public void setupPluginRealm(
             PluginDescriptor pluginDescriptor,
             MavenSession session,
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginJavaPrerequisiteChecker.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginJavaPrerequisiteChecker.java
new file mode 100644
index 0000000000..ebb0811714
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginJavaPrerequisiteChecker.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+package org.apache.maven.plugin.internal;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.apache.maven.plugin.MavenPluginPrerequisitesChecker;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.eclipse.aether.util.version.GenericVersionScheme;
+import org.eclipse.aether.version.InvalidVersionSpecificationException;
+import org.eclipse.aether.version.Version;
+import org.eclipse.aether.version.VersionConstraint;
+import org.eclipse.aether.version.VersionScheme;
+
+@Named
+@Singleton
+public class MavenPluginJavaPrerequisiteChecker implements 
MavenPluginPrerequisitesChecker {
+    private final VersionScheme versionScheme = new GenericVersionScheme();
+
+    @Override
+    public void accept(PluginDescriptor pluginDescriptor) {
+        String requiredJavaVersion = pluginDescriptor.getRequiredJavaVersion();
+        if (requiredJavaVersion != null && !requiredJavaVersion.isEmpty()) {
+            String currentJavaVersion = System.getProperty("java.version");
+            if (!matchesVersion(requiredJavaVersion, currentJavaVersion)) {
+                throw new IllegalStateException("Required Java version " + 
requiredJavaVersion
+                        + " is not met by current version: " + 
currentJavaVersion);
+            }
+        }
+    }
+
+    boolean matchesVersion(String requiredVersion, String currentVersion) {
+        VersionConstraint constraint;
+        try {
+            constraint = 
versionScheme.parseVersionConstraint(requiredVersion.equals("8") ? "1.8" : 
requiredVersion);
+        } catch (InvalidVersionSpecificationException e) {
+            throw new IllegalArgumentException("Invalid 'requiredJavaVersion' 
given in plugin descriptor", e);
+        }
+        Version current;
+        try {
+            current = versionScheme.parseVersion(currentVersion);
+        } catch (InvalidVersionSpecificationException e) {
+            throw new IllegalStateException("Could not parse current Java 
version", e);
+        }
+        if (constraint.getRange() == null) {
+            return constraint.getVersion().compareTo(current) <= 0;
+        }
+        return constraint.containsVersion(current);
+    }
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginMavenPrerequisiteChecker.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginMavenPrerequisiteChecker.java
new file mode 100644
index 0000000000..55dec64fb5
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginMavenPrerequisiteChecker.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+package org.apache.maven.plugin.internal;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.apache.maven.plugin.MavenPluginPrerequisitesChecker;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.rtinfo.RuntimeInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Named
+@Singleton
+public class MavenPluginMavenPrerequisiteChecker implements 
MavenPluginPrerequisitesChecker {
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+    private final RuntimeInformation runtimeInformation;
+
+    @Inject
+    public MavenPluginMavenPrerequisiteChecker(RuntimeInformation 
runtimeInformation) {
+        super();
+        this.runtimeInformation = runtimeInformation;
+    }
+
+    @Override
+    public void accept(PluginDescriptor pluginDescriptor) {
+        String requiredMavenVersion = 
pluginDescriptor.getRequiredMavenVersion();
+
+        boolean isBlankVersion =
+                requiredMavenVersion == null || 
requiredMavenVersion.trim().isEmpty();
+
+        if (!isBlankVersion) {
+            boolean isRequirementMet = false;
+            try {
+                isRequirementMet = 
runtimeInformation.isMavenVersion(requiredMavenVersion);
+            } catch (IllegalArgumentException e) {
+                logger.warn(
+                        "Could not verify plugin's Maven prerequisite as an 
invalid version is given in "
+                                + requiredMavenVersion,
+                        e);
+                return;
+            }
+            if (!isRequirementMet) {
+                throw new IllegalStateException("Required Maven version " + 
requiredMavenVersion
+                        + " is not met by current version " + 
runtimeInformation.getMavenVersion());
+            }
+        }
+    }
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
index 0f3761063e..e732ed12a4 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
@@ -273,7 +273,7 @@ private boolean isCompatible(PluginVersionRequest request, 
String version) {
         }
 
         try {
-            pluginManager.checkRequiredMavenVersion(pluginDescriptor);
+            pluginManager.checkPrerequisites(pluginDescriptor);
         } catch (PluginIncompatibleException e) {
             if (logger.isDebugEnabled()) {
                 logger.warn("Ignoring incompatible plugin version " + version, 
e);
diff --git 
a/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenPluginJavaPrerequisiteCheckerTest.java
 
b/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenPluginJavaPrerequisiteCheckerTest.java
new file mode 100644
index 0000000000..5213f97b9a
--- /dev/null
+++ 
b/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenPluginJavaPrerequisiteCheckerTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package org.apache.maven.plugin.internal;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+public class MavenPluginJavaPrerequisiteCheckerTest {
+
+    @Test
+    public void testMatchesVersion() {
+        MavenPluginJavaPrerequisiteChecker checker = new 
MavenPluginJavaPrerequisiteChecker();
+        assertTrue(checker.matchesVersion("8", "1.8"));
+        assertTrue(checker.matchesVersion("8", "9.0.1+11"));
+        assertTrue(checker.matchesVersion("1.0", "1.8"));
+        assertTrue(checker.matchesVersion("1.8", "9.0.1+11"));
+        assertFalse(checker.matchesVersion("[1.0,2],[3,4]", "2.1"));
+        assertTrue(checker.matchesVersion("[1.0,2],[3,4]", "3.1"));
+        assertThrows(IllegalArgumentException.class, () -> 
checker.matchesVersion("(1.0,0)", "11"));
+    }
+}
diff --git 
a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java
 
b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java
index 88a2481f53..80550ddc11 100644
--- 
a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java
+++ 
b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptor.java
@@ -80,6 +80,8 @@ public class PluginDescriptor extends ComponentSetDescriptor 
implements Cloneabl
     // MNG-4840: set from plugin's pom.xml, not plugin.xml
     private String requiredMavenVersion;
 
+    private String requiredJavaVersion;
+
     private Plugin plugin;
 
     private Artifact pluginArtifact;
@@ -318,6 +320,14 @@ public String getRequiredMavenVersion() {
         return requiredMavenVersion;
     }
 
+    public void setRequiredJavaVersion(String requiredJavaVersion) {
+        this.requiredJavaVersion = requiredJavaVersion;
+    }
+
+    public String getRequiredJavaVersion() {
+        return requiredJavaVersion;
+    }
+
     public void setPlugin(Plugin plugin) {
         this.plugin = plugin;
     }
diff --git 
a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java
 
b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java
index 5d603e769b..dda5e8e616 100644
--- 
a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java
+++ 
b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java
@@ -22,6 +22,7 @@
 import java.io.Reader;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 import org.codehaus.plexus.component.repository.ComponentDependency;
 import org.codehaus.plexus.component.repository.ComponentRequirement;
@@ -104,6 +105,8 @@ public PluginDescriptor build(Reader reader, String source) 
throws PlexusConfigu
 
         pluginDescriptor.setDependencies(dependencies);
 
+        
pluginDescriptor.setRequiredJavaVersion(extractRequiredJavaVersion(c).orElse(null));
+
         return pluginDescriptor;
     }
 
@@ -319,4 +322,8 @@ public PlexusConfiguration buildConfiguration(Reader 
configuration) throws Plexu
             throw new PlexusConfigurationException(e.getMessage(), e);
         }
     }
+
+    private Optional<String> extractRequiredJavaVersion(PlexusConfiguration c) 
{
+        return 
Optional.ofNullable(c.getChild("requiredJavaVersion")).map(PlexusConfiguration::getValue);
+    }
 }
diff --git a/maven-plugin-api/src/main/mdo/plugin.mdo 
b/maven-plugin-api/src/main/mdo/plugin.mdo
index 99177948eb..adc17ef4c5 100644
--- a/maven-plugin-api/src/main/mdo/plugin.mdo
+++ b/maven-plugin-api/src/main/mdo/plugin.mdo
@@ -36,11 +36,10 @@ under the License.
     </default>
   </defaults>
   <classes>
-    <class rootElement="true" xml.tagName="plugin">
+    <class rootElement="true" xml.tagName="plugin" xdoc.anchorName="plugin">
       <name>PluginDescriptor</name>
       <version>1.0.0</version>
-      <description><![CDATA[Root element of the <code>plugin.xml</code> 
file.]]></description>
-      <!-- see o.a.m.plugin.descriptor.PluginDescriptor -->
+      <description>Root element of the {@code plugin.xml} file.</description>
       <fields>
         <field>
           <name>name</name>
@@ -59,6 +58,7 @@ under the License.
           <version>1.0.0</version>
           <description>The group id of the plugin.</description>
           <type>String</type>
+          <required>true</required>
         </field>
         <field>
           <name>artifactId</name>
@@ -92,6 +92,15 @@ under the License.
           <type>boolean</type>
           <defaultValue>true</defaultValue>
         </field>
+        <field>
+          <name>requiredJavaVersion</name>
+          <version>1.0.0</version>
+          <description>
+            A version range which specifies the supported Java versions. A 
version range can either use the usual mathematical syntax 
"[2.0.10,2.1.0),[3.0,)" or use a single version "2.2.1". The latter is a short 
form for "[2.2.1,)", i.e. denotes the minimum version required.
+            @since Used by Maven 4.0.0-alpha-3+ and 3.9.12+, generated by 
maven-plugin-tools 3.8.0+
+          </description>
+          <type>String</type>
+        </field>
         <field xdoc.separator="blank">
           <name>mojos</name>
           <version>1.0.0</version>
@@ -116,13 +125,10 @@ under the License.
       </fields>
     </class>
 
-    <class>
+    <class xdoc.anchorName="mojo">
       <name>MojoDescriptor</name>
       <version>1.0.0</version>
-      <description><![CDATA[
-        A Mojo description.
-      ]]></description>
-      <!-- see o.a.m.plugin.descriptor.MojoDescriptor -->
+      <description>A Mojo description.</description>
       <fields>
         <field>
           <name>goal</name>
@@ -159,12 +165,12 @@ under the License.
           <name>phase</name>
           <version>1.0.0</version>
           <type>String</type>
-          <description><![CDATA[
-            Defines a default phase to bind a mojo execution to if the user 
does not explicitly set a phase in the POM.
-            <i>Note:</i> This will not automagically make a mojo run when the 
plugin declaration is added
-            to the POM. It merely enables the user to omit the 
<code>&lt;phase&gt;</code> element from the
-            surrounding <code>&lt;execution&gt;</code> element.
-          ]]></description>
+          <description>
+            Defines a default phase to bind a Mojo execution to if the user 
does not explicitly set a phase in the POM.
+            &lt;p>&lt;b>Note:&lt;/b> This will not automagically make a Mojo 
run when the plugin declaration is added
+            to the POM. It merely enables the user to omit the {@code 
&lt;phase&gt;} element from the
+            surrounding {@code &lt;execution&gt;} element.&lt;/p>
+          </description>
         </field>
         <field>
           <name>executePhase</name>
@@ -189,24 +195,24 @@ under the License.
           <version>1.0.0</version>
           <type>String</type>
           <defaultValue>runtime</defaultValue>
-          <description><![CDATA[
+          <description>
             Flags this Mojo as requiring the dependencies in the specified 
class path to be resolved before it can
-            execute: <code>compile</code>, <code>runtime</code>, 
<code>test</code>,
-            <code>compile+runtime</code> (since Maven 3.0) or 
<code>runtime+system</code> (since Maven 3.0)
-          ]]></description>
+            execute: {@code compile}, {@code runtime}, {@code test},
+            {@code compile+runtime} (since Maven 3.0) or {@code 
runtime+system} (since Maven 3.0)
+          </description>
         </field>
         <field>
           <name>requiresDependencyCollection</name>
           <version>1.0.0</version>
           <type>String</type>
-          <description><![CDATA[
-            Flags this mojo as requiring information about the dependencies 
that would make up the specified class
+          <description>
+            Flags this Mojo as requiring information about the dependencies 
that would make up the specified class
             path. As the name suggests, this is similar to 
requiresDependencyResolution and supports the same values.
             The important difference is this will not resolve the files for 
the dependencies, i.e. the artifacts
-            associated with a Maven project can lack a file. As such, this 
annotation is meant for mojos that only
+            associated with a Maven project can lack a file. As such, this 
annotation is meant for Mojos that only
             want to analyze the set of transitive dependencies, in particular 
during early lifecycle phases where
             full dependency resolution might fail due to projects which 
haven't been built yet.
-          ]]></description>
+          </description>
         </field>
         <field>
           <name>requiresDirectInvocation</name>
@@ -241,7 +247,7 @@ under the License.
           <version>1.0.0</version>
           <type>boolean</type>
           <description>
-            Flags this Mojo to run it in a multi module way, i.e. aggregate 
the build with the set of projects
+            Flags this Mojo to run it in a multi-module way, i.e. aggregate 
the build with the set of projects
             listed as modules.
           </description>
           <defaultValue>false</defaultValue>
@@ -258,9 +264,10 @@ under the License.
           <version>1.0.0</version>
           <type>boolean</type>
           <description>
-            Marks this mojo as being thread-safe, i.e. the mojo safely 
supports concurrent execution during parallel
+            Marks this Mojo as being thread-safe, i.e. the Mojo safely 
supports concurrent execution during parallel
             builds. Mojos without this annotation will make Maven output a 
warning when used during a parallel build
-            session. Since Maven 3.0.
+            session.
+            @since Maven 3.0.
           </description>
           <defaultValue>false</defaultValue>
         </field>
@@ -275,9 +282,9 @@ under the License.
           <name>executionStrategy</name>
           <version>1.0.0</version>
           <type>String</type>
-          <description><![CDATA[
-            Specify the execution strategy: <code>once-per-session</code>, 
<code>always</code>.
-          ]]></description>
+          <description>
+            Specify the execution strategy: {@code once-per-session}, {@code 
always}.
+          </description>
           <defaultValue>once-per-session</defaultValue>
         </field>
         <field>
@@ -290,10 +297,10 @@ under the License.
           <name>deprecated</name>
           <version>1.0.0</version>
           <type>String</type>
-          <description><![CDATA[
-            Description with the reason of Mojo deprecation. Similar to 
Javadoc <code>@deprecated</code>
+          <description>
+            Description with the reason of Mojo deprecation. Similar to 
Javadoc {@code @deprecated}
             This will trigger a warning when a user tries to use a Mojo marked 
as deprecated.
-          ]]></description>
+          </description>
         </field>
         <field>
           <name>configurator</name>
@@ -332,7 +339,7 @@ under the License.
         <field xdoc.separator="blank">
           <name>requirements</name>
           <version>1.0.0</version>
-          <description></description>
+          <description>Use Maven 4 Dependency Injection (for v4 plugins) or 
JSR 330 annotations (for v3 plugins) to inject dependencies 
instead.</description>
           <association>
             <type>Requirement</type>
             <multiplicity>*</multiplicity>
@@ -341,10 +348,10 @@ under the License.
       </fields>
     </class>
 
-    <class>
+    <class xdoc.anchorName="parameter">
       <name>Parameter</name>
       <version>1.0.0</version>
-      <description>A phase mapping definition.</description>
+      <description>A parameter description.</description>
       <!-- see o.a.m.plugin.descriptor.Parameter -->
       <fields>
         <field>
@@ -391,15 +398,15 @@ under the License.
           <version>1.0.0</version>
           <type>boolean</type>
           <defaultValue>true</defaultValue>
-          <description><![CDATA[
+          <description>
             Specifies that this parameter can be configured directly by the 
user (as in the case of POM-specified
             configuration). This is useful when you want to force the user to 
use common POM elements rather than
             plugin configurations, as in the case where you want to use the 
artifact's final name as a parameter. In
-            this case, you want the user to modify 
<code>&lt;build&gt;&lt;finalName/&gt;&lt;/build&gt;</code> rather
+            this case, you want the user to modify {@code 
&lt;build&gt;&lt;finalName/&gt;&lt;/build&gt;} rather
             than specifying a value for finalName directly in the plugin 
configuration section. It is also useful to
             ensure that - for example - a List-typed parameter which expects 
items of type Artifact doesn't get a List
             full of Strings.
-          ]]></description>
+          </description>
         </field>
         <field>
           <name>implementation</name>
@@ -423,10 +430,10 @@ under the License.
           <name>deprecated</name>
           <version>1.0.0</version>
           <type>String</type>
-          <description><![CDATA[
-            Description with the reason of parameter deprecation. Similar to 
Javadoc <code>@deprecated</code>
+          <description>
+            Description with the reason of parameter deprecation. Similar to 
Javadoc {@code @deprecated}.
             This will trigger a warning when a user tries to configure a 
parameter marked as deprecated.
-          ]]></description>
+          </description>
         </field>
       </fields>
     </class>
@@ -459,7 +466,7 @@ under the License.
       </fields>
     </class>
 
-    <class>
+    <class xdoc.anchorName="requirement">
       <name>Requirement</name>
       <version>1.0.0</version>
       <description>Describes a component requirement.</description>
@@ -488,7 +495,7 @@ under the License.
       </fields>
     </class>
 
-    <class>
+    <class xdoc.anchorName="dependency">
       <name>Dependency</name>
       <version>1.0.0</version>
       <description>Definition of a dependency, needed by the plugin at 
runtime.</description>

Reply via email to