EXCLUDED_LOGGERS = Set.of(
+ BuildReportCollector.class.getName(),
+ "org.apache.maven.DefaultMaven",
+ "org.apache.maven.project.collector.DefaultProjectsSelector",
+ "org.apache.maven.plugin.internal.DefaultPluginValidationManager");
+
private final DefaultDiagnosticCollector diagnosticCollector;
@Inject
@@ -353,10 +366,10 @@ private void captureLogEvent(int level, String loggerName, String message, Throw
// Auto-collect WARN-level log events as build problems, giving Maven 3 plugins
// automatic deduplication and summary at end of build without code changes.
- // Skip our own logger to avoid feedback loops from problem summary printing.
- if (level == LocationAwareLogger.WARN_INT
- && message != null
- && !loggerName.equals(BuildReportCollector.class.getName())) {
+ // Skip loggers that already pipe structured BuilderProblems directly to the
+ // DiagnosticCollector (avoiding double-counting), and our own logger to avoid
+ // feedback loops from problem summary printing.
+ if (level == LocationAwareLogger.WARN_INT && message != null && !EXCLUDED_LOGGERS.contains(loggerName)) {
String syntheticKey = syntheticDiagnosticKey(loggerName, message);
diagnosticCollector.report(BuilderProblem.builder()
.source(loggerName)
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginValidationManager.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginValidationManager.java
index d65f8dad681a..6c2cc943add1 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginValidationManager.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/PluginValidationManager.java
@@ -18,6 +18,7 @@
*/
package org.apache.maven.plugin;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.eclipse.aether.RepositorySystemSession;
@@ -54,27 +55,94 @@ enum IssueLocality {
* 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.
+ *
+ * @since 4.1.0
*/
void reportPluginValidationIssue(
- IssueLocality locality, RepositorySystemSession session, Artifact pluginArtifact, String issue);
+ IssueLocality locality, RepositorySystemSession session, Artifact pluginArtifact, BuilderProblem problem);
/**
* Reports plugin issues applicable to the plugin as a whole.
*
* This method will record extra information as well, like plugin occurrence or declaration location.
+ *
+ * @since 4.1.0
*/
void reportPluginValidationIssue(
- IssueLocality locality, MavenSession mavenSession, MojoDescriptor mojoDescriptor, String issue);
+ IssueLocality locality, MavenSession mavenSession, MojoDescriptor mojoDescriptor, BuilderProblem problem);
/**
* Reports plugin Mojo issues applicable to the Mojo itself.
*
* This method will record extra information as well, like plugin occurrence or declaration location.
+ *
+ * @since 4.1.0
*/
void reportPluginMojoValidationIssue(
IssueLocality locality,
MavenSession mavenSession,
MojoDescriptor mojoDescriptor,
Class> mojoClass,
- String issue);
+ BuilderProblem problem);
+
+ // ---- Deprecated String-based adapters for external callers ----
+
+ /**
+ * @deprecated Use {@link #reportPluginValidationIssue(IssueLocality, RepositorySystemSession, Artifact,
+ * BuilderProblem)} instead.
+ */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ default void reportPluginValidationIssue(
+ IssueLocality locality, RepositorySystemSession session, Artifact pluginArtifact, String issue) {
+ reportPluginValidationIssue(
+ locality,
+ session,
+ pluginArtifact,
+ BuilderProblem.builder()
+ .message(issue)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:" + issue.hashCode())
+ .build());
+ }
+
+ /**
+ * @deprecated Use {@link #reportPluginValidationIssue(IssueLocality, MavenSession, MojoDescriptor,
+ * BuilderProblem)} instead.
+ */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ default void reportPluginValidationIssue(
+ IssueLocality locality, MavenSession mavenSession, MojoDescriptor mojoDescriptor, String issue) {
+ reportPluginValidationIssue(
+ locality,
+ mavenSession,
+ mojoDescriptor,
+ BuilderProblem.builder()
+ .message(issue)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:" + issue.hashCode())
+ .build());
+ }
+
+ /**
+ * @deprecated Use {@link #reportPluginMojoValidationIssue(IssueLocality, MavenSession, MojoDescriptor, Class,
+ * BuilderProblem)} instead.
+ */
+ @Deprecated(since = "4.1.0", forRemoval = true)
+ default void reportPluginMojoValidationIssue(
+ IssueLocality locality,
+ MavenSession mavenSession,
+ MojoDescriptor mojoDescriptor,
+ Class> mojoClass,
+ String issue) {
+ reportPluginMojoValidationIssue(
+ locality,
+ mavenSession,
+ mojoDescriptor,
+ mojoClass,
+ BuilderProblem.builder()
+ .message(issue)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:" + issue.hashCode())
+ .build());
+ }
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java
index 9e7426b168ff..47a772809e37 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/AbstractMavenPluginParametersValidator.java
@@ -18,6 +18,7 @@
*/
package org.apache.maven.plugin.internal;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.PluginValidationManager;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
@@ -97,6 +98,11 @@ protected boolean isIgnoredProperty(String strValue) {
protected abstract String getParameterLogReason(Parameter parameter);
+ /**
+ * Returns the validation key prefix for this validator (e.g. "deprecated-param", "readonly-param").
+ */
+ protected abstract String getValidationKeyPrefix();
+
protected String formatParameter(Parameter parameter) {
StringBuilder stringBuilder = new StringBuilder()
.append("Parameter '")
@@ -112,4 +118,12 @@ protected String formatParameter(Parameter parameter) {
return stringBuilder.toString();
}
+
+ protected BuilderProblem buildParameterProblem(Parameter parameter) {
+ return BuilderProblem.builder()
+ .message(formatParameter(parameter))
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:" + getValidationKeyPrefix() + ":" + parameter.getName())
+ .build();
+ }
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
index 15f3d8df7b64..a95cf34fff83 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java
@@ -51,6 +51,7 @@
import org.apache.maven.api.Service;
import org.apache.maven.api.Session;
import org.apache.maven.api.plugin.descriptor.Resolution;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.DependencyResolver;
import org.apache.maven.api.services.DependencyResolverResult;
import org.apache.maven.api.services.PathScopeRegistry;
@@ -751,7 +752,13 @@ private T loadV3Mojo(
session,
mojoDescriptor,
mojo.getClass(),
- "Mojo implements `Contextualizable` interface from Plexus Container, which is EOL.");
+ BuilderProblem.builder()
+ .message(
+ "Mojo implements `Contextualizable` interface from Plexus Container, which is EOL.")
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:contextualizable")
+ .suggestion("Migrate from Contextualizable to javax.inject dependency injection")
+ .build());
}
XmlNode dom = mojoExecution.getConfiguration() != null
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginValidationManager.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginValidationManager.java
index 0bd14d1635d1..e445b2978e1f 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginValidationManager.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginValidationManager.java
@@ -18,6 +18,7 @@
*/
package org.apache.maven.plugin.internal;
+import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
@@ -39,9 +40,11 @@
import java.util.stream.Collectors;
import org.apache.maven.api.Constants;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.eventspy.AbstractEventSpy;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.MavenSession;
+import org.apache.maven.internal.build.DefaultDiagnosticCollector;
import org.apache.maven.model.InputLocation;
import org.apache.maven.plugin.PluginValidationManager;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
@@ -83,6 +86,13 @@ private enum ValidationReportLevel {
private final Logger logger = LoggerFactory.getLogger(getClass());
+ private final DefaultDiagnosticCollector diagnosticCollector;
+
+ @Inject
+ DefaultPluginValidationManager(DefaultDiagnosticCollector diagnosticCollector) {
+ this.diagnosticCollector = diagnosticCollector;
+ }
+
@Override
public void onEvent(Object event) {
if (event instanceof ExecutionEvent executionEvent) {
@@ -158,28 +168,30 @@ private void mayReportInline(RepositorySystemSession session, IssueLocality loca
@Override
public void reportPluginValidationIssue(
- IssueLocality locality, RepositorySystemSession session, Artifact pluginArtifact, String issue) {
+ IssueLocality locality, RepositorySystemSession session, Artifact pluginArtifact, BuilderProblem problem) {
String pluginKey = pluginKey(pluginArtifact);
if (validationPluginExcludes(session).contains(pluginKey)) {
return;
}
PluginValidationIssues pluginIssues =
pluginIssues(session).computeIfAbsent(pluginKey, k -> new PluginValidationIssues());
- pluginIssues.reportPluginIssue(locality, null, issue);
- mayReportInline(session, locality, issue);
+ pluginIssues.reportPluginIssue(locality, null, problem.getMessage());
+ diagnosticCollector.report(problem);
+ mayReportInline(session, locality, problem.getMessage());
}
@Override
public void reportPluginValidationIssue(
- IssueLocality locality, MavenSession mavenSession, MojoDescriptor mojoDescriptor, String issue) {
+ IssueLocality locality, MavenSession mavenSession, MojoDescriptor mojoDescriptor, BuilderProblem problem) {
String pluginKey = pluginKey(mojoDescriptor);
if (validationPluginExcludes(mavenSession.getRepositorySession()).contains(pluginKey)) {
return;
}
PluginValidationIssues pluginIssues = pluginIssues(mavenSession.getRepositorySession())
.computeIfAbsent(pluginKey, k -> new PluginValidationIssues());
- pluginIssues.reportPluginIssue(locality, pluginDeclaration(mavenSession, mojoDescriptor), issue);
- mayReportInline(mavenSession.getRepositorySession(), locality, issue);
+ pluginIssues.reportPluginIssue(locality, pluginDeclaration(mavenSession, mojoDescriptor), problem.getMessage());
+ diagnosticCollector.report(problem);
+ mayReportInline(mavenSession.getRepositorySession(), locality, problem.getMessage());
}
@Override
@@ -188,7 +200,7 @@ public void reportPluginMojoValidationIssue(
MavenSession mavenSession,
MojoDescriptor mojoDescriptor,
Class> mojoClass,
- String issue) {
+ BuilderProblem problem) {
String pluginKey = pluginKey(mojoDescriptor);
if (validationPluginExcludes(mavenSession.getRepositorySession()).contains(pluginKey)) {
return;
@@ -196,8 +208,12 @@ public void reportPluginMojoValidationIssue(
PluginValidationIssues pluginIssues = pluginIssues(mavenSession.getRepositorySession())
.computeIfAbsent(pluginKey, k -> new PluginValidationIssues());
pluginIssues.reportPluginMojoIssue(
- locality, pluginDeclaration(mavenSession, mojoDescriptor), mojoInfo(mojoDescriptor, mojoClass), issue);
- mayReportInline(mavenSession.getRepositorySession(), locality, issue);
+ locality,
+ pluginDeclaration(mavenSession, mojoDescriptor),
+ mojoInfo(mojoDescriptor, mojoClass),
+ problem.getMessage());
+ diagnosticCollector.report(problem);
+ mayReportInline(mavenSession.getRepositorySession(), locality, problem.getMessage());
}
private void reportSessionCollectedValidationIssues(MavenSession mavenSession) {
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java
index faaac5cf1c53..81029df570fb 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedCoreExpressionValidator.java
@@ -63,6 +63,11 @@ protected String getParameterLogReason(Parameter parameter) {
+ DEPRECATED_CORE_PARAMETERS.get(parameter.getDefaultValue());
}
+ @Override
+ protected String getValidationKeyPrefix() {
+ return "deprecated-expr";
+ }
+
@Override
protected void doValidate(
MavenSession mavenSession,
@@ -76,9 +81,13 @@ protected void doValidate(
mojoDescriptor.getParameters().stream()
.filter(this::isDeprecated)
- .map(this::formatParameter)
- .forEach(m -> pluginValidationManager.reportPluginMojoValidationIssue(
- PluginValidationManager.IssueLocality.EXTERNAL, mavenSession, mojoDescriptor, mojoClass, m));
+ .map(this::buildParameterProblem)
+ .forEach(problem -> pluginValidationManager.reportPluginMojoValidationIssue(
+ PluginValidationManager.IssueLocality.EXTERNAL,
+ mavenSession,
+ mojoDescriptor,
+ mojoClass,
+ problem));
}
private boolean isDeprecated(Parameter parameter) {
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java
index a4d784c403dc..45c973fcd967 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DeprecatedPluginValidator.java
@@ -22,6 +22,7 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.api.services.MessageBuilderFactory;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.PluginValidationManager;
@@ -52,6 +53,11 @@ protected String getParameterLogReason(Parameter parameter) {
return "is deprecated: " + parameter.getDeprecated();
}
+ @Override
+ protected String getValidationKeyPrefix() {
+ return "deprecated-param";
+ }
+
@Override
protected void doValidate(
MavenSession mavenSession,
@@ -65,7 +71,11 @@ protected void doValidate(
mavenSession,
mojoDescriptor,
mojoClass,
- logDeprecatedMojo(mojoDescriptor));
+ BuilderProblem.builder()
+ .message(logDeprecatedMojo(mojoDescriptor))
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:deprecated-goal:" + mojoDescriptor.getGoal())
+ .build());
}
if (mojoDescriptor.getParameters() != null) {
@@ -92,7 +102,7 @@ private void checkParameter(
mavenSession,
mojoDescriptor,
mojoClass,
- formatParameter(parameter));
+ buildParameterProblem(parameter));
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven2DependenciesValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven2DependenciesValidator.java
index d2f8dd89ce77..05b206b97c0b 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven2DependenciesValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven2DependenciesValidator.java
@@ -25,6 +25,7 @@
import java.util.Set;
import java.util.stream.Collectors;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.plugin.PluginValidationManager;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
@@ -64,7 +65,12 @@ protected void doValidate(
PluginValidationManager.IssueLocality.EXTERNAL,
session,
pluginArtifact,
- "Plugin is a Maven 2.x plugin, which will be not supported in Maven 4.x");
+ BuilderProblem.builder()
+ .message("Plugin is a Maven 2.x plugin, which will be not supported in Maven 4.x")
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:maven2-plugin")
+ .suggestion("Upgrade to a Maven 3.x/4.x compatible version of this plugin")
+ .build());
}
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven3CompatDependenciesValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven3CompatDependenciesValidator.java
index 0cf8fee6ad35..559d3c189828 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven3CompatDependenciesValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/Maven3CompatDependenciesValidator.java
@@ -23,6 +23,7 @@
import javax.inject.Singleton;
import org.apache.maven.api.DependencyScope;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.plugin.PluginValidationManager;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
@@ -55,7 +56,13 @@ protected void doValidate(
PluginValidationManager.IssueLocality.EXTERNAL,
session,
pluginArtifact,
- "Plugin depends on the deprecated Maven 2.x compatibility layer, which will be not supported in Maven 4.x");
+ BuilderProblem.builder()
+ .message(
+ "Plugin depends on the deprecated Maven 2.x compatibility layer, which will be not supported in Maven 4.x")
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:maven-compat-dep")
+ .suggestion("Remove the maven-compat dependency from the plugin")
+ .build());
}
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenMixedDependenciesValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenMixedDependenciesValidator.java
index 27003836d3fd..3ae05d3a100a 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenMixedDependenciesValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenMixedDependenciesValidator.java
@@ -25,6 +25,7 @@
import java.util.Set;
import java.util.stream.Collectors;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.plugin.PluginValidationManager;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
@@ -63,7 +64,12 @@ protected void doValidate(
PluginValidationManager.IssueLocality.EXTERNAL,
session,
pluginArtifact,
- "Plugin mixes multiple Maven versions: " + mavenVersions);
+ BuilderProblem.builder()
+ .message("Plugin mixes multiple Maven versions: " + mavenVersions)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:mixed-maven-versions")
+ .suggestion("Align all Maven dependencies to a single version to avoid classloading issues")
+ .build());
}
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenScopeDependenciesValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenScopeDependenciesValidator.java
index 460a91c6ec18..48f78c901102 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenScopeDependenciesValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenScopeDependenciesValidator.java
@@ -26,6 +26,7 @@
import java.util.stream.Collectors;
import org.apache.maven.api.DependencyScope;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.plugin.PluginValidationManager;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
@@ -65,8 +66,15 @@ protected void doValidate(
PluginValidationManager.IssueLocality.EXTERNAL,
session,
pluginArtifact,
- "Plugin should declare Maven artifacts in `provided` scope. If the plugin already declares them in `provided` scope, update the maven-plugin-plugin to latest version. Artifacts found with wrong scope: "
- + mavenArtifacts);
+ BuilderProblem.builder()
+ .message(
+ "Plugin should declare Maven artifacts in `provided` scope. If the plugin already declares them in `provided` scope, update the maven-plugin-plugin to latest version. Artifacts found with wrong scope: "
+ + mavenArtifacts)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:wrong-scope")
+ .suggestion(
+ "Change Maven artifact dependencies to 'provided' scope or update maven-plugin-plugin")
+ .build());
}
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/PlexusContainerDefaultDependenciesValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/PlexusContainerDefaultDependenciesValidator.java
index 31638139a3f7..ba15ab4d80cc 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/PlexusContainerDefaultDependenciesValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/PlexusContainerDefaultDependenciesValidator.java
@@ -22,6 +22,7 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.plugin.PluginValidationManager;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
@@ -55,7 +56,12 @@ protected void doValidate(
PluginValidationManager.IssueLocality.EXTERNAL,
session,
pluginArtifact,
- "Plugin depends on plexus-container-default, which is EOL");
+ BuilderProblem.builder()
+ .message("Plugin depends on plexus-container-default, which is EOL")
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("plugin-validation:plexus-container-eol")
+ .suggestion("Migrate from plexus-container-default to javax.inject / Eclipse Sisu")
+ .build());
}
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java
index 2989fb5166a2..69e4d9870aff 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/ReadOnlyPluginParametersValidator.java
@@ -47,6 +47,11 @@ protected String getParameterLogReason(Parameter parameter) {
return "is read-only, must not be used in configuration";
}
+ @Override
+ protected String getValidationKeyPrefix() {
+ return "readonly-param";
+ }
+
@Override
protected void doValidate(
MavenSession mavenSession,
@@ -79,7 +84,7 @@ private void checkParameter(
mavenSession,
mojoDescriptor,
mojoClass,
- formatParameter(parameter));
+ buildParameterProblem(parameter));
}
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java b/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java
index 0be344384adf..bd5664d1eba2 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/project/collector/DefaultProjectsSelector.java
@@ -26,7 +26,9 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.maven.api.services.BuilderProblem;
import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.internal.build.DefaultDiagnosticCollector;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelProblemUtils;
import org.apache.maven.project.MavenProject;
@@ -45,10 +47,12 @@
public class DefaultProjectsSelector implements ProjectsSelector {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultProjectsSelector.class);
private final ProjectBuilder projectBuilder;
+ private final DefaultDiagnosticCollector diagnosticCollector;
@Inject
- public DefaultProjectsSelector(ProjectBuilder projectBuilder) {
+ public DefaultProjectsSelector(ProjectBuilder projectBuilder, DefaultDiagnosticCollector diagnosticCollector) {
this.projectBuilder = projectBuilder;
+ this.diagnosticCollector = diagnosticCollector;
}
@Override
@@ -83,6 +87,14 @@ public List selectProjects(List files, MavenExecutionRequest
LOGGER.warn("{}{}", problem.getMessage(), ((loc != null && !loc.isEmpty()) ? " @ " + loc : ""));
}
}
+
+ // Pipe structured problems directly to DiagnosticCollector so that
+ // source location and severity are preserved in the build report
+ // (instead of being lost to plain-text logging). The SLF4J hook
+ // excludes this logger to avoid double-counting.
+ for (ModelProblem problem : result.getProblems()) {
+ diagnosticCollector.report(toBuilderProblem(problem));
+ }
}
}
@@ -100,4 +112,26 @@ public List selectProjects(List files, MavenExecutionRequest
return projects;
}
+
+ /**
+ * Converts a compat {@link ModelProblem} to the Maven 4 {@link BuilderProblem} API,
+ * preserving source, line, column, severity, and message.
+ */
+ private static BuilderProblem toBuilderProblem(ModelProblem problem) {
+ BuilderProblem.Severity severity =
+ switch (problem.getSeverity()) {
+ case FATAL -> BuilderProblem.Severity.FATAL;
+ case ERROR -> BuilderProblem.Severity.ERROR;
+ default -> BuilderProblem.Severity.WARNING;
+ };
+ return BuilderProblem.builder()
+ .source(problem.getSource())
+ .lineNumber(problem.getLineNumber())
+ .columnNumber(problem.getColumnNumber())
+ .exception(problem.getException())
+ .message(problem.getMessage())
+ .severity(severity)
+ .key("model:" + problem.getMessage().hashCode())
+ .build();
+ }
}
diff --git a/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java b/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java
index 72dad0b244d5..6982db4b97a0 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/graph/DefaultGraphBuilderTest.java
@@ -101,7 +101,8 @@ class DefaultGraphBuilderTest {
private final MavenSession session = mock(MavenSession.class);
private final MavenExecutionRequest mavenExecutionRequest = mock(MavenExecutionRequest.class);
- private final ProjectsSelector projectsSelector = new DefaultProjectsSelector(projectBuilder);
+ private final ProjectsSelector projectsSelector = new DefaultProjectsSelector(
+ projectBuilder, new org.apache.maven.internal.build.DefaultDiagnosticCollector());
// Not using mocks for these strategies - a mock would just copy the actual implementation.
diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportCollectorTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportCollectorTest.java
index 5733daf74d0a..2358d5d3a9d6 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportCollectorTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportCollectorTest.java
@@ -35,7 +35,6 @@
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
-import org.apache.maven.impl.DefaultBuilderProblem;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@@ -334,8 +333,12 @@ void testDiagnosticSuppressionWildcard() {
// ---- Test helpers ----
private static BuilderProblem warning(String key, String message, String source) {
- return new DefaultBuilderProblem(
- source, -1, -1, null, message, BuilderProblem.Severity.WARNING, key, null, null);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key(key)
+ .build();
}
private MavenProject createProject(String groupId, String artifactId, String version) {
diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportIntegrationTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportIntegrationTest.java
index e200cd06b6f8..10f2dc1ae78b 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportIntegrationTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportIntegrationTest.java
@@ -35,7 +35,6 @@
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
-import org.apache.maven.impl.DefaultBuilderProblem;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
@@ -72,21 +71,41 @@ void setUp() {
}
private static BuilderProblem warning(String key, String message, String source) {
- return new DefaultBuilderProblem(
- source, -1, -1, null, message, BuilderProblem.Severity.WARNING, key, null, null);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key(key)
+ .build();
}
private static BuilderProblem warning(String key, String message, String source, String suggestion, String docUrl) {
- return new DefaultBuilderProblem(
- source, -1, -1, null, message, BuilderProblem.Severity.WARNING, key, suggestion, docUrl);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key(key)
+ .suggestion(suggestion)
+ .documentationUrl(docUrl)
+ .build();
}
private static BuilderProblem info(String key, String message, String source) {
- return new DefaultBuilderProblem(source, -1, -1, null, message, BuilderProblem.Severity.INFO, key, null, null);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.INFO)
+ .key(key)
+ .build();
}
private static BuilderProblem error(String key, String message, String source) {
- return new DefaultBuilderProblem(source, -1, -1, null, message, BuilderProblem.Severity.ERROR, key, null, null);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.ERROR)
+ .key(key)
+ .build();
}
/**
diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportJsonWriterTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportJsonWriterTest.java
index 073072c4a539..831bb8a06115 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportJsonWriterTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/internal/build/BuildReportJsonWriterTest.java
@@ -30,7 +30,6 @@
import org.apache.maven.api.build.report.ModuleReport;
import org.apache.maven.api.build.report.MojoReport;
import org.apache.maven.api.services.BuilderProblem;
-import org.apache.maven.impl.DefaultBuilderProblem;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -334,27 +333,23 @@ void testNullMojoFields() {
@Test
void testProblemsSerialization() {
- BuilderProblem p1 = new DefaultBuilderProblem(
- "maven-compiler-plugin:3.15.0:compile",
- 42,
- 1,
- null,
- "source/target value 8 is deprecated",
- BuilderProblem.Severity.WARNING,
- "deprecated-source-target",
- "Update to 11 or higher",
- "https://example.com/docs/compiler");
-
- BuilderProblem p2 = new DefaultBuilderProblem(
- "maven-compiler-plugin",
- -1,
- -1,
- null,
- "3 errors found",
- BuilderProblem.Severity.ERROR,
- "compilation-failure",
- null,
- null);
+ BuilderProblem p1 = BuilderProblem.builder()
+ .source("maven-compiler-plugin:3.15.0:compile")
+ .lineNumber(42)
+ .columnNumber(1)
+ .message("source/target value 8 is deprecated")
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("deprecated-source-target")
+ .suggestion("Update to 11 or higher")
+ .documentationUrl("https://example.com/docs/compiler")
+ .build();
+
+ BuilderProblem p2 = BuilderProblem.builder()
+ .source("maven-compiler-plugin")
+ .message("3 errors found")
+ .severity(BuilderProblem.Severity.ERROR)
+ .key("compilation-failure")
+ .build();
BuildReport report = new DefaultBuildReport(
BuildStatus.FAILURE,
diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/build/DefaultDiagnosticCollectorTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/build/DefaultDiagnosticCollectorTest.java
index 3276c3c533cc..90dfeefe1457 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/internal/build/DefaultDiagnosticCollectorTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/internal/build/DefaultDiagnosticCollectorTest.java
@@ -27,7 +27,6 @@
import java.util.concurrent.Future;
import org.apache.maven.api.services.BuilderProblem;
-import org.apache.maven.impl.DefaultBuilderProblem;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -45,16 +44,30 @@ void setUp() {
}
private static BuilderProblem warning(String key, String message, String source) {
- return new DefaultBuilderProblem(
- source, -1, -1, null, message, BuilderProblem.Severity.WARNING, key, null, null);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.WARNING)
+ .key(key)
+ .build();
}
private static BuilderProblem error(String key, String message, String source) {
- return new DefaultBuilderProblem(source, -1, -1, null, message, BuilderProblem.Severity.ERROR, key, null, null);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.ERROR)
+ .key(key)
+ .build();
}
private static BuilderProblem info(String key, String message, String source) {
- return new DefaultBuilderProblem(source, -1, -1, null, message, BuilderProblem.Severity.INFO, key, null, null);
+ return BuilderProblem.builder()
+ .source(source)
+ .message(message)
+ .severity(BuilderProblem.Severity.INFO)
+ .key(key)
+ .build();
}
@Test
@@ -175,16 +188,16 @@ void testSummaryListIsUnmodifiable() {
@Test
void testFullProblemFields() {
- BuilderProblem p = new DefaultBuilderProblem(
- "maven-compiler-plugin:3.15.0:compile",
- 42,
- 15,
- null,
- "unchecked cast from Object to List",
- BuilderProblem.Severity.WARNING,
- "unchecked-cast",
- "Add @SuppressWarnings(\"unchecked\") or use a type-safe alternative",
- "https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html");
+ BuilderProblem p = BuilderProblem.builder()
+ .source("maven-compiler-plugin:3.15.0:compile")
+ .lineNumber(42)
+ .columnNumber(15)
+ .message("unchecked cast from Object to List")
+ .severity(BuilderProblem.Severity.WARNING)
+ .key("unchecked-cast")
+ .suggestion("Add @SuppressWarnings(\"unchecked\") or use a type-safe alternative")
+ .documentationUrl("https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html")
+ .build();
collector.report(p);