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

cstamas 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 36a4e9ff6 [MNG-7754] Improvement and extension of plugin validation 
(#1079)
36a4e9ff6 is described below

commit 36a4e9ff644850a96cfd173cda95819a8836e833
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Wed Apr 12 11:42:30 2023 +0200

    [MNG-7754] Improvement and extension of plugin validation (#1079)
    
    This is general rework of current Maven 3.9.x line how it handles plugin 
and mojo validations.
    
    Changes:
    * added plugin validations for dependencies
    * introduced pluginValidationManager that gathers violations
    * manager creates a report at build end, with dense and non repeating data
    * this is in spirit to lessen already too verbose logging, as current 
solution would report violations as many times plugin is used in reactor, and 
that can be many (ie. a plugin from parent for each module)
    
    
    Example report of Maven 3.9.x build: 
https://gist.github.com/cstamas/b62fdcd53eaf316123cf183f5a24e6a5
    
    ---
    
    https://issues.apache.org/jira/browse/MNG-7754
---
 .../maven/plugin/PluginValidationManager.java      |  55 +++++
 .../AbstractMavenPluginDependenciesValidator.java  |  55 +++++
 ...PluginDescriptorSourcedParametersValidator.java |   6 +
 .../AbstractMavenPluginParametersValidator.java    |  40 +--
 .../plugin/internal/DefaultMavenPluginManager.java |  22 +-
 .../DefaultPluginDependenciesResolver.java         |  17 ++
 .../internal/DefaultPluginValidationManager.java   | 270 +++++++++++++++++++++
 .../DeprecatedCoreExpressionValidator.java         |  21 +-
 .../plugin/internal/DeprecatedPluginValidator.java |  43 ++--
 .../internal/Maven2DependenciesValidator.java      |  63 +++++
 .../internal/MavenMixedDependenciesValidator.java  |  60 +++++
 .../MavenPluginConfigurationValidator.java         |   5 +-
 ....java => MavenPluginDependenciesValidator.java} |  16 +-
 .../internal/MavenScopeDependenciesValidator.java  |  62 +++++
 ...lexusContainerDefaultDependenciesValidator.java |  53 ++++
 .../ReadOnlyPluginParametersValidator.java         |  24 +-
 16 files changed, 762 insertions(+), 50 deletions(-)

diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/PluginValidationManager.java 
b/maven-core/src/main/java/org/apache/maven/plugin/PluginValidationManager.java
new file mode 100644
index 000000000..aaf0f29c4
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/PluginValidationManager.java
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+
+/**
+ * Component collecting plugin validation issues and reporting them.
+ *
+ * @since 3.9.2
+ */
+public interface PluginValidationManager {
+    /**
+     * Reports plugin issues applicable to the plugin as a whole.
+     * <p>
+     * This method should be used in "early" phase of plugin execution, 
possibly even when plugin or mojo descriptor
+     * does not exist yet. In turn, this method will not record extra 
information like plugin occurrence or declaration
+     * location as those are not yet available.
+     */
+    void reportPluginValidationIssue(RepositorySystemSession session, Artifact 
pluginArtifact, String issue);
+
+    /**
+     * Reports plugin issues applicable to the plugin as a whole.
+     * <p>
+     * This method will record extra information as well, like plugin 
occurrence or declaration location.
+     */
+    void reportPluginValidationIssue(MavenSession mavenSession, MojoDescriptor 
mojoDescriptor, String issue);
+
+    /**
+     * Reports plugin Mojo issues applicable to the Mojo itself.
+     * <p>
+     * This method will record extra information as well, like plugin 
occurrence or declaration location.
+     */
+    void reportPluginMojoValidationIssue(
+            MavenSession mavenSession, MojoDescriptor mojoDescriptor, Class<?> 
mojoClass, String issue);
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginDependenciesValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginDependenciesValidator.java
new file mode 100644
index 000000000..6f75c0d33
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginDependenciesValidator.java
@@ -0,0 +1,55 @@
+/*
+ * 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 java.util.Arrays;
+import java.util.List;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Service responsible for validating plugin dependencies.
+ *
+ * @since 3.9.2
+ */
+abstract class AbstractMavenPluginDependenciesValidator implements 
MavenPluginDependenciesValidator {
+
+    protected final List<String> expectedProvidedScopeExclusions = 
Arrays.asList(
+            "org.apache.maven:maven-archiver", "org.apache.maven:maven-jxr", 
"org.apache.maven:plexus-utils");
+
+    protected final PluginValidationManager pluginValidationManager;
+
+    protected AbstractMavenPluginDependenciesValidator(PluginValidationManager 
pluginValidationManager) {
+        this.pluginValidationManager = requireNonNull(pluginValidationManager);
+    }
+
+    @Override
+    public void validate(MavenSession mavenSession, MojoDescriptor 
mojoDescriptor) {
+        if (mojoDescriptor.getPluginDescriptor() != null
+                && mojoDescriptor.getPluginDescriptor().getDependencies() != 
null) {
+            doValidate(mavenSession, mojoDescriptor);
+        }
+    }
+
+    protected abstract void doValidate(MavenSession mavenSession, 
MojoDescriptor mojoDescriptor);
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginDescriptorSourcedParametersValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginDescriptorSourcedParametersValidator.java
index 94ca55781..76a0e16a4 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginDescriptorSourcedParametersValidator.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginDescriptorSourcedParametersValidator.java
@@ -21,6 +21,8 @@ package org.apache.maven.plugin.internal;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.maven.plugin.PluginValidationManager;
+
 /**
  * Common implementations for plugin parameters configuration validation that 
relies on Mojo descriptor (leaves out
  * core parameters by default).
@@ -48,6 +50,10 @@ abstract class 
AbstractMavenPluginDescriptorSourcedParametersValidator extends A
     private static final List<String> IGNORED_PROPERTY_PREFIX =
             Arrays.asList("mojo.", "pom.", "plugin.", "project.", "session.", 
"settings.");
 
+    protected 
AbstractMavenPluginDescriptorSourcedParametersValidator(PluginValidationManager 
pluginValidationManager) {
+        super(pluginValidationManager);
+    }
+
     @Override
     protected boolean isIgnoredProperty(String strValue) {
         if (!strValue.startsWith("${")) {
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java
index 809a75dfc..c5eeb72c7 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java
@@ -18,15 +18,15 @@
  */
 package org.apache.maven.plugin.internal;
 
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.Parameter;
-import org.apache.maven.shared.utils.logging.MessageBuilder;
-import org.apache.maven.shared.utils.logging.MessageUtils;
 import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
 import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
 import org.codehaus.plexus.configuration.PlexusConfiguration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static java.util.Objects.requireNonNull;
 
 /**
  * Common implementations for plugin parameters configuration validation.
@@ -35,7 +35,11 @@ import org.slf4j.LoggerFactory;
  */
 abstract class AbstractMavenPluginParametersValidator implements 
MavenPluginConfigurationValidator {
 
-    protected final Logger logger = LoggerFactory.getLogger(getClass());
+    protected final PluginValidationManager pluginValidationManager;
+
+    protected AbstractMavenPluginParametersValidator(PluginValidationManager 
pluginValidationManager) {
+        this.pluginValidationManager = requireNonNull(pluginValidationManager);
+    }
 
     protected boolean isValueSet(PlexusConfiguration config, 
ExpressionEvaluator expressionEvaluator) {
         if (config == null) {
@@ -73,18 +77,18 @@ abstract class AbstractMavenPluginParametersValidator 
implements MavenPluginConf
 
     @Override
     public final void validate(
+            MavenSession mavenSession,
             MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
             PlexusConfiguration pomConfiguration,
             ExpressionEvaluator expressionEvaluator) {
-        if (!logger.isWarnEnabled()) {
-            return;
-        }
-
-        doValidate(mojoDescriptor, pomConfiguration, expressionEvaluator);
+        doValidate(mavenSession, mojoDescriptor, mojoClass, pomConfiguration, 
expressionEvaluator);
     }
 
     protected abstract void doValidate(
+            MavenSession mavenSession,
             MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
             PlexusConfiguration pomConfiguration,
             ExpressionEvaluator expressionEvaluator);
 
@@ -94,19 +98,19 @@ abstract class AbstractMavenPluginParametersValidator 
implements MavenPluginConf
 
     protected abstract String getParameterLogReason(Parameter parameter);
 
-    protected void logParameter(Parameter parameter) {
-        MessageBuilder messageBuilder = MessageUtils.buffer()
-                .warning("Parameter '")
-                .warning(parameter.getName())
-                .warning('\'');
+    protected String formatParameter(Parameter parameter) {
+        StringBuilder stringBuilder = new StringBuilder()
+                .append("Parameter '")
+                .append(parameter.getName())
+                .append('\'');
 
         if (parameter.getExpression() != null) {
             String userProperty = parameter.getExpression().replace("${", 
"'").replace('}', '\'');
-            messageBuilder.warning(" (user property 
").warning(userProperty).warning(")");
+            stringBuilder.append(" (user property 
").append(userProperty).append(")");
         }
 
-        messageBuilder.warning(" ").warning(getParameterLogReason(parameter));
+        stringBuilder.append(" ").append(getParameterLogReason(parameter));
 
-        logger.warn(messageBuilder.toString());
+        return stringBuilder.toString();
     }
 }
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 e652e4c77..6cc9c9e9d 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
@@ -64,6 +64,7 @@ import org.apache.maven.plugin.PluginParameterException;
 import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
 import org.apache.maven.plugin.PluginRealmCache;
 import org.apache.maven.plugin.PluginResolutionException;
+import org.apache.maven.plugin.PluginValidationManager;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.Parameter;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
@@ -96,6 +97,7 @@ import 
org.codehaus.plexus.configuration.PlexusConfigurationException;
 import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
 import org.codehaus.plexus.logging.Logger;
 import org.codehaus.plexus.logging.LoggerManager;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 import org.codehaus.plexus.util.ReaderFactory;
 import org.codehaus.plexus.util.StringUtils;
 import org.codehaus.plexus.util.xml.Xpp3Dom;
@@ -164,6 +166,12 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
     @Requirement
     private List<MavenPluginConfigurationValidator> configurationValidators;
 
+    @Requirement
+    private List<MavenPluginDependenciesValidator> dependenciesValidators;
+
+    @Requirement
+    private PluginValidationManager pluginValidationManager;
+
     private ExtensionDescriptorBuilder extensionDescriptorBuilder = new 
ExtensionDescriptorBuilder();
 
     private PluginDescriptorBuilder builder = new PluginDescriptorBuilder();
@@ -540,6 +548,18 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
                 ((Mojo) mojo).setLog(new DefaultLog(mojoLogger));
             }
 
+            if (mojo instanceof Contextualizable) {
+                pluginValidationManager.reportPluginMojoValidationIssue(
+                        session,
+                        mojoDescriptor,
+                        mojo.getClass(),
+                        "Implements `Contextualizable` interface from Plexus 
Container, which is EOL.");
+            }
+
+            for (MavenPluginDependenciesValidator validator : 
dependenciesValidators) {
+                validator.validate(session, mojoDescriptor);
+            }
+
             Xpp3Dom dom = mojoExecution.getConfiguration();
 
             PlexusConfiguration pomConfiguration;
@@ -553,7 +573,7 @@ public class DefaultMavenPluginManager implements 
MavenPluginManager {
             ExpressionEvaluator expressionEvaluator = new 
PluginParameterExpressionEvaluator(session, mojoExecution);
 
             for (MavenPluginConfigurationValidator validator : 
configurationValidators) {
-                validator.validate(mojoDescriptor, pomConfiguration, 
expressionEvaluator);
+                validator.validate(session, mojoDescriptor, mojo.getClass(), 
pomConfiguration, expressionEvaluator);
             }
 
             populateMojoExecutionFields(
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
index c2307612b..0d1dc4f80 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
@@ -28,6 +28,7 @@ import org.apache.maven.RepositoryUtils;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.PluginResolutionException;
+import org.apache.maven.plugin.PluginValidationManager;
 import org.codehaus.plexus.component.annotations.Component;
 import org.codehaus.plexus.component.annotations.Requirement;
 import org.codehaus.plexus.logging.Logger;
@@ -78,6 +79,9 @@ public class DefaultPluginDependenciesResolver implements 
PluginDependenciesReso
     @Requirement
     private RepositorySystem repoSystem;
 
+    @Requirement
+    private PluginValidationManager pluginValidationManager;
+
     private Artifact toArtifact(Plugin plugin, RepositorySystemSession 
session) {
         return new DefaultArtifact(
                 plugin.getGroupId(),
@@ -103,6 +107,19 @@ public class DefaultPluginDependenciesResolver implements 
PluginDependenciesReso
             request.setTrace(trace);
             ArtifactDescriptorResult result = 
repoSystem.readArtifactDescriptor(pluginSession, request);
 
+            if (result.getDependencies() != null) {
+                for (org.eclipse.aether.graph.Dependency dependency : 
result.getDependencies()) {
+                    if 
("org.apache.maven".equals(dependency.getArtifact().getGroupId())
+                            && 
"maven-compat".equals(dependency.getArtifact().getArtifactId())
+                            && !JavaScopes.TEST.equals(dependency.getScope())) 
{
+                        pluginValidationManager.reportPluginValidationIssue(
+                                session,
+                                pluginArtifact,
+                                "Plugin depends on the deprecated Maven 2.x 
compatibility layer, which may not be supported in Maven 4.x");
+                    }
+                }
+            }
+
             pluginArtifact = result.getArtifact();
 
             if (logger.isWarnEnabled()) {
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginValidationManager.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginValidationManager.java
new file mode 100644
index 000000000..57ce4ebab
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginValidationManager.java
@@ -0,0 +1,270 @@
+/*
+ * 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 java.io.File;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.maven.AbstractMavenLifecycleParticipant;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.InputLocation;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.util.ConfigUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+@Named
+public final class DefaultPluginValidationManager extends 
AbstractMavenLifecycleParticipant
+        implements PluginValidationManager {
+
+    private static final String ISSUES_KEY = 
DefaultPluginValidationManager.class.getName() + ".issues";
+
+    private static final String MAVEN_PLUGIN_VALIDATION_KEY = 
"maven.plugin.validation";
+
+    private enum ValidationLevel {
+        DISABLED,
+        ENABLED,
+        VERBOSE
+    }
+
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Override
+    public void afterSessionEnd(MavenSession session) {
+        reportSessionCollectedValidationIssues(session);
+    }
+
+    private ValidationLevel validationLevel(RepositorySystemSession session) {
+        String level = ConfigUtils.getString(session, null, 
MAVEN_PLUGIN_VALIDATION_KEY);
+        if (level == null || level.isEmpty()) {
+            return ValidationLevel.ENABLED;
+        }
+        try {
+            return ValidationLevel.valueOf(level.toUpperCase(Locale.ENGLISH));
+        } catch (IllegalArgumentException e) {
+            logger.warn(
+                    "Invalid value specified for property {}: '{}'. Supported 
values are (case insensitive): {}",
+                    MAVEN_PLUGIN_VALIDATION_KEY,
+                    level,
+                    Arrays.toString(ValidationLevel.values()));
+            return ValidationLevel.ENABLED;
+        }
+    }
+
+    private String pluginKey(String groupId, String artifactId, String 
version) {
+        return groupId + ":" + artifactId + ":" + version;
+    }
+
+    private String pluginKey(MojoDescriptor mojoDescriptor) {
+        PluginDescriptor pd = mojoDescriptor.getPluginDescriptor();
+        return pluginKey(pd.getGroupId(), pd.getArtifactId(), pd.getVersion());
+    }
+
+    private String pluginKey(Artifact pluginArtifact) {
+        return pluginKey(pluginArtifact.getGroupId(), 
pluginArtifact.getArtifactId(), pluginArtifact.getVersion());
+    }
+
+    @Override
+    public void reportPluginValidationIssue(RepositorySystemSession session, 
Artifact pluginArtifact, String issue) {
+        String pluginKey = pluginKey(pluginArtifact);
+        PluginValidationIssues pluginIssues =
+                pluginIssues(session).computeIfAbsent(pluginKey, k -> new 
PluginValidationIssues());
+        pluginIssues.reportPluginIssue(null, null, issue);
+    }
+
+    @Override
+    public void reportPluginValidationIssue(MavenSession mavenSession, 
MojoDescriptor mojoDescriptor, String issue) {
+        String pluginKey = pluginKey(mojoDescriptor);
+        PluginValidationIssues pluginIssues = 
pluginIssues(mavenSession.getRepositorySession())
+                .computeIfAbsent(pluginKey, k -> new PluginValidationIssues());
+        pluginIssues.reportPluginIssue(
+                pluginDeclaration(mavenSession, mojoDescriptor), 
pluginOccurrence(mavenSession), issue);
+    }
+
+    @Override
+    public void reportPluginMojoValidationIssue(
+            MavenSession mavenSession, MojoDescriptor mojoDescriptor, Class<?> 
mojoClass, String issue) {
+        String pluginKey = pluginKey(mojoDescriptor);
+        PluginValidationIssues pluginIssues = 
pluginIssues(mavenSession.getRepositorySession())
+                .computeIfAbsent(pluginKey, k -> new PluginValidationIssues());
+        pluginIssues.reportPluginMojoIssue(
+                pluginDeclaration(mavenSession, mojoDescriptor),
+                pluginOccurrence(mavenSession),
+                mojoInfo(mojoDescriptor, mojoClass),
+                issue);
+    }
+
+    private void reportSessionCollectedValidationIssues(MavenSession 
mavenSession) {
+        ValidationLevel validationLevel = 
validationLevel(mavenSession.getRepositorySession());
+        ConcurrentHashMap<String, PluginValidationIssues> issuesMap = 
pluginIssues(mavenSession.getRepositorySession());
+        if (!issuesMap.isEmpty()) {
+
+            logger.warn("");
+            logger.warn("Plugin validation issues were detected in {} 
plugin(s)", issuesMap.size());
+            logger.warn("");
+            if (validationLevel == ValidationLevel.DISABLED || 
!logger.isWarnEnabled()) {
+                return;
+            }
+
+            for (Map.Entry<String, PluginValidationIssues> entry : 
issuesMap.entrySet()) {
+                logger.warn("Plugin {}", entry.getKey());
+                PluginValidationIssues issues = entry.getValue();
+                if (validationLevel == ValidationLevel.VERBOSE && 
!issues.pluginDeclarations.isEmpty()) {
+                    logger.warn("  Declared at location(s):");
+                    for (String pluginDeclaration : issues.pluginDeclarations) 
{
+                        logger.warn("   * {}", pluginDeclaration);
+                    }
+                }
+                if (validationLevel == ValidationLevel.VERBOSE && 
!issues.pluginOccurrences.isEmpty()) {
+                    logger.warn("  Used in module(s):");
+                    for (String pluginOccurrence : issues.pluginOccurrences) {
+                        logger.warn("   * {}", pluginOccurrence);
+                    }
+                }
+                if (!issues.pluginIssues.isEmpty()) {
+                    logger.warn("  Plugin issue(s):");
+                    for (String pluginIssue : issues.pluginIssues) {
+                        logger.warn("   * {}", pluginIssue);
+                    }
+                }
+                if (!issues.mojoIssues.isEmpty()) {
+                    logger.warn("  Mojo issue(s):");
+                    for (String mojoInfo : issues.mojoIssues.keySet()) {
+                        logger.warn("   * Mojo {}", mojoInfo);
+                        for (String mojoIssue : 
issues.mojoIssues.get(mojoInfo)) {
+                            logger.warn("     - {}", mojoIssue);
+                        }
+                    }
+                }
+                logger.warn("");
+            }
+            logger.warn("");
+            logger.warn(
+                    "To fix these issues, please upgrade above listed plugins, 
or, notify their maintainers about reported issues.");
+            logger.warn("");
+            logger.warn(
+                    "For more or less details, use 'maven.plugin.validation' 
property with one of the values (case insensitive): {}",
+                    Arrays.toString(ValidationLevel.values()));
+            logger.warn("");
+        }
+    }
+
+    private String pluginDeclaration(MavenSession mavenSession, MojoDescriptor 
mojoDescriptor) {
+        InputLocation inputLocation =
+                
mojoDescriptor.getPluginDescriptor().getPlugin().getLocation("");
+        if (inputLocation != null && inputLocation.getSource() != null) {
+            StringBuilder stringBuilder = new StringBuilder();
+            stringBuilder.append(inputLocation.getSource().getModelId());
+            String location = inputLocation.getSource().getLocation();
+            if (location != null) {
+                if (location.contains("://")) {
+                    stringBuilder.append(" (").append(location).append(")");
+                } else {
+                    File rootBasedir = 
mavenSession.getTopLevelProject().getBasedir();
+                    File locationFile = new File(location);
+                    if (location.startsWith(rootBasedir.getPath())) {
+                        stringBuilder
+                                .append(" (")
+                                
.append(rootBasedir.toPath().relativize(locationFile.toPath()))
+                                .append(")");
+                    } else {
+                        stringBuilder.append(" 
(").append(location).append(")");
+                    }
+                }
+            }
+            stringBuilder.append(" @ line 
").append(inputLocation.getLineNumber());
+            return stringBuilder.toString();
+        } else {
+            return "unknown";
+        }
+    }
+
+    private String pluginOccurrence(MavenSession mavenSession) {
+        MavenProject prj = mavenSession.getCurrentProject();
+        String result = prj.getGroupId() + ":" + prj.getArtifactId() + ":" + 
prj.getVersion();
+        File currentPom = prj.getFile();
+        if (currentPom != null) {
+            File rootBasedir = mavenSession.getTopLevelProject().getBasedir();
+            result += " (" + 
rootBasedir.toPath().relativize(currentPom.toPath()) + ")";
+        }
+        return result;
+    }
+
+    private String mojoInfo(MojoDescriptor mojoDescriptor, Class<?> mojoClass) 
{
+        return mojoDescriptor.getFullGoalName() + " (" + mojoClass.getName() + 
")";
+    }
+
+    @SuppressWarnings("unchecked")
+    private ConcurrentHashMap<String, PluginValidationIssues> 
pluginIssues(RepositorySystemSession session) {
+        return (ConcurrentHashMap<String, PluginValidationIssues>)
+                session.getData().computeIfAbsent(ISSUES_KEY, 
ConcurrentHashMap::new);
+    }
+
+    private static class PluginValidationIssues {
+        private final LinkedHashSet<String> pluginDeclarations;
+
+        private final LinkedHashSet<String> pluginOccurrences;
+
+        private final LinkedHashSet<String> pluginIssues;
+
+        private final LinkedHashMap<String, LinkedHashSet<String>> mojoIssues;
+
+        private PluginValidationIssues() {
+            this.pluginDeclarations = new LinkedHashSet<>();
+            this.pluginOccurrences = new LinkedHashSet<>();
+            this.pluginIssues = new LinkedHashSet<>();
+            this.mojoIssues = new LinkedHashMap<>();
+        }
+
+        private synchronized void reportPluginIssue(String pluginDeclaration, 
String pluginOccurrence, String issue) {
+            if (pluginDeclaration != null) {
+                pluginDeclarations.add(pluginDeclaration);
+            }
+            if (pluginOccurrence != null) {
+                pluginOccurrences.add(pluginOccurrence);
+            }
+            pluginIssues.add(issue);
+        }
+
+        private synchronized void reportPluginMojoIssue(
+                String pluginDeclaration, String pluginOccurrence, String 
mojoInfo, String issue) {
+            if (pluginDeclaration != null) {
+                pluginDeclarations.add(pluginDeclaration);
+            }
+            if (pluginOccurrence != null) {
+                pluginOccurrences.add(pluginOccurrence);
+            }
+            mojoIssues.computeIfAbsent(mojoInfo, k -> new 
LinkedHashSet<>()).add(issue);
+        }
+    }
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java
index 0eea6f92a..54bb11434 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java
@@ -18,12 +18,15 @@
  */
 package org.apache.maven.plugin.internal;
 
+import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
 import java.util.HashMap;
 import java.util.Objects;
 
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.Parameter;
 import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
@@ -40,7 +43,7 @@ class DeprecatedCoreExpressionValidator extends 
AbstractMavenPluginParametersVal
     private static final HashMap<String, String> DEPRECATED_CORE_PARAMETERS;
 
     private static final String ARTIFACT_REPOSITORY_REASON =
-            "Avoid use of ArtifactRepository type. If you need access to local 
repository, switch to '${repositorySystemSession}' expression and get LRM from 
it instead.";
+            "ArtifactRepository type is deprecated and its use in Mojos should 
be avoided.";
 
     static {
         HashMap<String, String> deprecatedCoreParameters = new HashMap<>();
@@ -49,21 +52,33 @@ class DeprecatedCoreExpressionValidator extends 
AbstractMavenPluginParametersVal
         DEPRECATED_CORE_PARAMETERS = deprecatedCoreParameters;
     }
 
+    @Inject
+    DeprecatedCoreExpressionValidator(PluginValidationManager 
pluginValidationManager) {
+        super(pluginValidationManager);
+    }
+
     @Override
     protected String getParameterLogReason(Parameter parameter) {
-        return "is deprecated core expression; " + 
DEPRECATED_CORE_PARAMETERS.get(parameter.getDefaultValue());
+        return "uses deprecated parameter expression '" + 
parameter.getDefaultValue() + "': "
+                + DEPRECATED_CORE_PARAMETERS.get(parameter.getDefaultValue());
     }
 
     @Override
     protected void doValidate(
+            MavenSession mavenSession,
             MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
             PlexusConfiguration pomConfiguration,
             ExpressionEvaluator expressionEvaluator) {
         if (mojoDescriptor.getParameters() == null) {
             return;
         }
 
-        
mojoDescriptor.getParameters().stream().filter(this::isDeprecated).forEach(this::logParameter);
+        mojoDescriptor.getParameters().stream()
+                .filter(this::isDeprecated)
+                .map(this::formatParameter)
+                .forEach(m -> 
pluginValidationManager.reportPluginMojoValidationIssue(
+                        mavenSession, mojoDescriptor, mojoClass, m));
     }
 
     private boolean isDeprecated(Parameter parameter) {
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java
index d229d8a57..1fd07a10e 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java
@@ -18,9 +18,12 @@
  */
 package org.apache.maven.plugin.internal;
 
+import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.Parameter;
 import org.apache.maven.shared.utils.logging.MessageUtils;
@@ -35,6 +38,12 @@ import org.codehaus.plexus.configuration.PlexusConfiguration;
 @Singleton
 @Named
 class DeprecatedPluginValidator extends 
AbstractMavenPluginDescriptorSourcedParametersValidator {
+
+    @Inject
+    DeprecatedPluginValidator(PluginValidationManager pluginValidationManager) 
{
+        super(pluginValidationManager);
+    }
+
     @Override
     protected String getParameterLogReason(Parameter parameter) {
         return "is deprecated: " + parameter.getDeprecated();
@@ -42,40 +51,46 @@ class DeprecatedPluginValidator extends 
AbstractMavenPluginDescriptorSourcedPara
 
     @Override
     protected void doValidate(
+            MavenSession mavenSession,
             MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
             PlexusConfiguration pomConfiguration,
             ExpressionEvaluator expressionEvaluator) {
         if (mojoDescriptor.getDeprecated() != null) {
-            logDeprecatedMojo(mojoDescriptor);
+            pluginValidationManager.reportPluginMojoValidationIssue(
+                    mavenSession, mojoDescriptor, mojoClass, 
logDeprecatedMojo(mojoDescriptor));
         }
 
-        if (mojoDescriptor.getParameters() == null) {
-            return;
+        if (mojoDescriptor.getParameters() != null) {
+            mojoDescriptor.getParameters().stream()
+                    .filter(parameter -> parameter.getDeprecated() != null)
+                    .filter(Parameter::isEditable)
+                    .forEach(parameter -> checkParameter(
+                            mavenSession, mojoDescriptor, mojoClass, 
parameter, pomConfiguration, expressionEvaluator));
         }
-
-        mojoDescriptor.getParameters().stream()
-                .filter(parameter -> parameter.getDeprecated() != null)
-                .filter(Parameter::isEditable)
-                .forEach(parameter -> checkParameter(parameter, 
pomConfiguration, expressionEvaluator));
     }
 
     private void checkParameter(
-            Parameter parameter, PlexusConfiguration pomConfiguration, 
ExpressionEvaluator expressionEvaluator) {
+            MavenSession mavenSession,
+            MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
+            Parameter parameter,
+            PlexusConfiguration pomConfiguration,
+            ExpressionEvaluator expressionEvaluator) {
         PlexusConfiguration config = 
pomConfiguration.getChild(parameter.getName(), false);
 
         if (isValueSet(config, expressionEvaluator)) {
-            logParameter(parameter);
+            pluginValidationManager.reportPluginMojoValidationIssue(
+                    mavenSession, mojoDescriptor, mojoClass, 
formatParameter(parameter));
         }
     }
 
-    private void logDeprecatedMojo(MojoDescriptor mojoDescriptor) {
-        String message = MessageUtils.buffer()
+    private String logDeprecatedMojo(MojoDescriptor mojoDescriptor) {
+        return MessageUtils.buffer()
                 .warning("Goal '")
                 .warning(mojoDescriptor.getGoal())
                 .warning("' is deprecated: ")
                 .warning(mojoDescriptor.getDeprecated())
                 .toString();
-
-        logger.warn(message);
     }
 }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven2DependenciesValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven2DependenciesValidator.java
new file mode 100644
index 000000000..7e53bd40d
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven2DependenciesValidator.java
@@ -0,0 +1,63 @@
+/*
+ * 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 java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.codehaus.plexus.component.repository.ComponentDependency;
+
+/**
+ * Detects Maven2 plugins.
+ *
+ * @since 3.9.2
+ */
+@Singleton
+@Named
+class Maven2DependenciesValidator extends 
AbstractMavenPluginDependenciesValidator {
+
+    @Inject
+    Maven2DependenciesValidator(PluginValidationManager 
pluginValidationManager) {
+        super(pluginValidationManager);
+    }
+
+    @Override
+    protected void doValidate(MavenSession mavenSession, MojoDescriptor 
mojoDescriptor) {
+        Set<String> maven2Versions = 
mojoDescriptor.getPluginDescriptor().getDependencies().stream()
+                .filter(d -> "org.apache.maven".equals(d.getGroupId()))
+                .filter(d -> 
!expectedProvidedScopeExclusions.contains(d.getGroupId() + ":" + 
d.getArtifactId()))
+                .map(ComponentDependency::getVersion)
+                .filter(v -> v.startsWith("2."))
+                .collect(Collectors.toSet());
+
+        if (!maven2Versions.isEmpty()) {
+            pluginValidationManager.reportPluginValidationIssue(
+                    mavenSession,
+                    mojoDescriptor,
+                    "Plugin is a Maven 2.x plugin, which will be not supported 
in Maven 4.x");
+        }
+    }
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenMixedDependenciesValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenMixedDependenciesValidator.java
new file mode 100644
index 000000000..e881fc08b
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenMixedDependenciesValidator.java
@@ -0,0 +1,60 @@
+/*
+ * 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 java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+import org.codehaus.plexus.component.repository.ComponentDependency;
+
+/**
+ * Detects mixed Maven versions in plugins.
+ *
+ * @since 3.9.2
+ */
+@Singleton
+@Named
+class MavenMixedDependenciesValidator extends 
AbstractMavenPluginDependenciesValidator {
+
+    @Inject
+    MavenMixedDependenciesValidator(PluginValidationManager 
pluginValidationManager) {
+        super(pluginValidationManager);
+    }
+
+    @Override
+    protected void doValidate(MavenSession mavenSession, MojoDescriptor 
mojoDescriptor) {
+        Set<String> mavenVersions = 
mojoDescriptor.getPluginDescriptor().getDependencies().stream()
+                .filter(d -> "org.apache.maven".equals(d.getGroupId()))
+                .filter(d -> 
!expectedProvidedScopeExclusions.contains(d.getGroupId() + ":" + 
d.getArtifactId()))
+                .map(ComponentDependency::getVersion)
+                .collect(Collectors.toSet());
+
+        if (mavenVersions.size() > 1) {
+            pluginValidationManager.reportPluginValidationIssue(
+                    mavenSession, mojoDescriptor, "Plugin mixes multiple Maven 
versions: " + mavenVersions);
+        }
+    }
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginConfigurationValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginConfigurationValidator.java
index a79550c6f..cb0e3fb23 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginConfigurationValidator.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginConfigurationValidator.java
@@ -18,6 +18,7 @@
  */
 package org.apache.maven.plugin.internal;
 
+import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
 import org.codehaus.plexus.configuration.PlexusConfiguration;
@@ -29,10 +30,12 @@ import 
org.codehaus.plexus.configuration.PlexusConfiguration;
  */
 interface MavenPluginConfigurationValidator {
     /**
-     * Check mojo configuration.
+     * Checks mojo configuration issues.
      */
     void validate(
+            MavenSession mavenSession,
             MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
             PlexusConfiguration pomConfiguration,
             ExpressionEvaluator expressionEvaluator);
 }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginConfigurationValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginDependenciesValidator.java
similarity index 66%
copy from 
maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginConfigurationValidator.java
copy to 
maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginDependenciesValidator.java
index a79550c6f..b990bfe58 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginConfigurationValidator.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenPluginDependenciesValidator.java
@@ -18,21 +18,17 @@
  */
 package org.apache.maven.plugin.internal;
 
+import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
-import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
-import org.codehaus.plexus.configuration.PlexusConfiguration;
 
 /**
- * Service responsible for validating plugin configuration.
+ * Service responsible for validating plugin dependencies.
  *
- * @author Slawomir Jaranowski
+ * @since 3.9.2
  */
-interface MavenPluginConfigurationValidator {
+interface MavenPluginDependenciesValidator {
     /**
-     * Check mojo configuration.
+     * Checks mojo dependency issues.
      */
-    void validate(
-            MojoDescriptor mojoDescriptor,
-            PlexusConfiguration pomConfiguration,
-            ExpressionEvaluator expressionEvaluator);
+    void validate(MavenSession mavenSession, MojoDescriptor mojoDescriptor);
 }
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenScopeDependenciesValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenScopeDependenciesValidator.java
new file mode 100644
index 000000000..87aaa8f8e
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenScopeDependenciesValidator.java
@@ -0,0 +1,62 @@
+/*
+ * 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 java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+
+/**
+ * Detects Maven3 artifacts in bad scope in plugins.
+ *
+ * @since 3.9.2
+ */
+@Singleton
+@Named
+class MavenScopeDependenciesValidator extends 
AbstractMavenPluginDependenciesValidator {
+
+    @Inject
+    MavenScopeDependenciesValidator(PluginValidationManager 
pluginValidationManager) {
+        super(pluginValidationManager);
+    }
+
+    @Override
+    protected void doValidate(MavenSession mavenSession, MojoDescriptor 
mojoDescriptor) {
+        Set<String> mavenArtifacts = 
mojoDescriptor.getPluginDescriptor().getDependencies().stream()
+                .filter(d -> "org.apache.maven".equals(d.getGroupId()))
+                .filter(d -> 
!expectedProvidedScopeExclusions.contains(d.getGroupId() + ":" + 
d.getArtifactId()))
+                .filter(d -> d.getVersion().startsWith("3."))
+                .map(d -> d.getGroupId() + ":" + d.getArtifactId() + ":" + 
d.getVersion())
+                .collect(Collectors.toSet());
+
+        if (!mavenArtifacts.isEmpty()) {
+            pluginValidationManager.reportPluginValidationIssue(
+                    mavenSession,
+                    mojoDescriptor,
+                    "Plugin should declare these Maven artifacts in `provided` 
scope: " + mavenArtifacts);
+        }
+    }
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/PlexusContainerDefaultDependenciesValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/PlexusContainerDefaultDependenciesValidator.java
new file mode 100644
index 000000000..c326fede5
--- /dev/null
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/PlexusContainerDefaultDependenciesValidator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
+import org.apache.maven.plugin.descriptor.MojoDescriptor;
+
+/**
+ * Detects Plexus Container Default in plugins.
+ *
+ * @since 3.9.2
+ */
+@Singleton
+@Named
+class PlexusContainerDefaultDependenciesValidator extends 
AbstractMavenPluginDependenciesValidator {
+
+    @Inject
+    PlexusContainerDefaultDependenciesValidator(PluginValidationManager 
pluginValidationManager) {
+        super(pluginValidationManager);
+    }
+
+    protected void doValidate(MavenSession mavenSession, MojoDescriptor 
mojoDescriptor) {
+        boolean pcdPresent = 
mojoDescriptor.getPluginDescriptor().getDependencies().stream()
+                .filter(d -> "org.codehaus.plexus".equals(d.getGroupId()))
+                .anyMatch(d -> 
"plexus-container-default".equals(d.getArtifactId()));
+
+        if (pcdPresent) {
+            pluginValidationManager.reportPluginValidationIssue(
+                    mavenSession, mojoDescriptor, "Plugin depends on 
plexus-container-default, which is EOL");
+        }
+    }
+}
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java
index 6c1555079..83df41d0f 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java
@@ -18,9 +18,12 @@
  */
 package org.apache.maven.plugin.internal;
 
+import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginValidationManager;
 import org.apache.maven.plugin.descriptor.MojoDescriptor;
 import org.apache.maven.plugin.descriptor.Parameter;
 import 
org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
@@ -34,6 +37,12 @@ import org.codehaus.plexus.configuration.PlexusConfiguration;
 @Named
 @Singleton
 class ReadOnlyPluginParametersValidator extends 
AbstractMavenPluginDescriptorSourcedParametersValidator {
+
+    @Inject
+    ReadOnlyPluginParametersValidator(PluginValidationManager 
pluginValidationManager) {
+        super(pluginValidationManager);
+    }
+
     @Override
     protected String getParameterLogReason(Parameter parameter) {
         return "is read-only, must not be used in configuration";
@@ -41,7 +50,9 @@ class ReadOnlyPluginParametersValidator extends 
AbstractMavenPluginDescriptorSou
 
     @Override
     protected void doValidate(
+            MavenSession mavenSession,
             MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
             PlexusConfiguration pomConfiguration,
             ExpressionEvaluator expressionEvaluator) {
         if (mojoDescriptor.getParameters() == null) {
@@ -50,15 +61,22 @@ class ReadOnlyPluginParametersValidator extends 
AbstractMavenPluginDescriptorSou
 
         mojoDescriptor.getParameters().stream()
                 .filter(parameter -> !parameter.isEditable())
-                .forEach(parameter -> checkParameter(parameter, 
pomConfiguration, expressionEvaluator));
+                .forEach(parameter -> checkParameter(
+                        mavenSession, mojoDescriptor, mojoClass, parameter, 
pomConfiguration, expressionEvaluator));
     }
 
     private void checkParameter(
-            Parameter parameter, PlexusConfiguration pomConfiguration, 
ExpressionEvaluator expressionEvaluator) {
+            MavenSession mavenSession,
+            MojoDescriptor mojoDescriptor,
+            Class<?> mojoClass,
+            Parameter parameter,
+            PlexusConfiguration pomConfiguration,
+            ExpressionEvaluator expressionEvaluator) {
         PlexusConfiguration config = 
pomConfiguration.getChild(parameter.getName(), false);
 
         if (isValueSet(config, expressionEvaluator)) {
-            logParameter(parameter);
+            pluginValidationManager.reportPluginMojoValidationIssue(
+                    mavenSession, mojoDescriptor, mojoClass, 
formatParameter(parameter));
         }
     }
 }

Reply via email to