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

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


The following commit(s) were added to refs/heads/maven-3.10.x by this push:
     new c64fbe4aa7 Feat: Align CP ordering with Maven 4 (#12327)
c64fbe4aa7 is described below

commit c64fbe4aa7e348a30bfecf8c5118d6d399627301
Author: Tamas Cservenak <[email protected]>
AuthorDate: Fri Jun 19 13:57:26 2026 +0200

    Feat: Align CP ordering with Maven 4 (#12327)
    
    This PR aligns classpath ordering with Maven 4 (level order). All Maven 2/3 
versions released so far has "pre-order" flattening (historical reasons, Maven 
2 did it like that). Maven 3.10.0 switches to Resolver 2, where resolver 
exposes flattening configuration too, and defaults to safer "level order", 
preventing issues like described here https://arxiv.org/abs/2407.18760v3
    
    For resolver configuration, see configuration key 
`aether.system.dependencyVisitor` in
    https://maven.apache.org/resolver/configuration.html If _full Maven 3 
behaviour needed_, user can simply set 
`-Daether.system.dependencyVisitor=preOrder` and it restores CP ordering to 
that used in Maven 3.9 and older.
    
    This PR changes:
    * remove scattered "flattening" happening in multiple spots in Maven, it is 
(and in fact was, but result was thrown away) fully delegating to Resolver.
    * simplify spots that was doing repeated deprecated pre-order flattening 
(which already happened in plugin dependencies resolver)
---
 .../plugin/internal/DefaultMavenPluginManager.java | 38 +++++++------------
 .../DefaultPluginDependenciesResolver.java         | 43 ++++++++++++++++++----
 .../internal/PluginDependenciesResolver.java       | 41 +++++++++++++++++++++
 .../internal/BootstrapCoreExtensionManager.java    | 22 +++++------
 4 files changed, 101 insertions(+), 43 deletions(-)

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 edd9bb129b..44aac42459 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
@@ -32,9 +32,7 @@
 import java.io.Reader;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -107,10 +105,10 @@
 import org.codehaus.plexus.util.xml.Xpp3Dom;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.graph.DependencyFilter;
-import org.eclipse.aether.graph.DependencyNode;
 import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.resolution.DependencyResult;
 import org.eclipse.aether.util.filter.AndDependencyFilter;
-import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
 
 /**
  * Provides basic services to manage Maven plugins and their mojos. This 
component is kept general in its design such
@@ -389,17 +387,17 @@ private void createPluginRealm(
         DependencyFilter dependencyFilter = 
project.getExtensionDependencyFilter();
         dependencyFilter = AndDependencyFilter.newInstance(dependencyFilter, 
filter);
 
-        DependencyNode root = pluginDependenciesResolver.resolve(
+        DependencyResult result = 
pluginDependenciesResolver.resolvePluginAndFlatten(
                 plugin,
                 RepositoryUtils.toArtifact(pluginArtifact),
                 dependencyFilter,
                 project.getRemotePluginRepositories(),
                 repositorySession);
 
-        PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
-        root.accept(nlg);
-
-        pluginArtifacts = toMavenArtifacts(root, nlg);
+        pluginArtifacts = result.getArtifactResults().stream()
+                .filter(ArtifactResult::isResolved)
+                .map(r -> RepositoryUtils.toArtifact(r.getArtifact()))
+                .collect(Collectors.toList());
 
         pluginRealm = classRealmManager.createPluginRealm(
                 plugin, parent, null, foreignImports, 
toAetherArtifacts(pluginArtifacts));
@@ -437,18 +435,6 @@ private List<org.eclipse.aether.artifact.Artifact> 
toAetherArtifacts(final List<
         return new ArrayList<>(RepositoryUtils.toArtifacts(pluginArtifacts));
     }
 
-    private List<Artifact> toMavenArtifacts(DependencyNode root, 
PreorderNodeListGenerator nlg) {
-        List<Artifact> artifacts = new ArrayList<>(nlg.getNodes().size());
-        RepositoryUtils.toArtifacts(artifacts, Collections.singleton(root), 
Collections.<String>emptyList(), null);
-        for (Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); ) {
-            Artifact artifact = it.next();
-            if (artifact.getFile() == null) {
-                it.remove();
-            }
-        }
-        return Collections.unmodifiableList(artifacts);
-    }
-
     private Map<String, ClassLoader> calcImports(MavenProject project, 
ClassLoader parent, List<String> imports) {
         Map<String, ClassLoader> foreignImports = new HashMap<>();
 
@@ -841,9 +827,11 @@ public ExtensionRealmCache.CacheRecord 
setupExtensionsRealm(
     private List<Artifact> resolveExtensionArtifacts(
             Plugin extensionPlugin, List<RemoteRepository> repositories, 
RepositorySystemSession session)
             throws PluginResolutionException {
-        DependencyNode root = 
pluginDependenciesResolver.resolve(extensionPlugin, null, null, repositories, 
session);
-        PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
-        root.accept(nlg);
-        return toMavenArtifacts(root, nlg);
+        DependencyResult result =
+                
pluginDependenciesResolver.resolvePluginAndFlatten(extensionPlugin, null, null, 
repositories, session);
+        return result.getArtifactResults().stream()
+                .filter(ArtifactResult::isResolved)
+                .map(r -> RepositoryUtils.toArtifact(r.getArtifact()))
+                .collect(Collectors.toList());
     }
 }
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 b2284661d6..ca7c1fcf08 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
@@ -57,6 +57,7 @@
 import org.eclipse.aether.resolution.ArtifactResolutionException;
 import org.eclipse.aether.resolution.DependencyRequest;
 import org.eclipse.aether.resolution.DependencyResolutionException;
+import org.eclipse.aether.resolution.DependencyResult;
 import org.eclipse.aether.util.artifact.JavaScopes;
 import org.eclipse.aether.util.filter.AndDependencyFilter;
 import org.eclipse.aether.util.filter.ScopeDependencyFilter;
@@ -98,6 +99,7 @@ private Artifact toArtifact(Plugin plugin, 
RepositorySystemSession session) {
                 session.getArtifactTypeRegistry().get("maven-plugin"));
     }
 
+    @Override
     public Artifact resolve(Plugin plugin, List<RemoteRepository> 
repositories, RepositorySystemSession session)
             throws PluginResolutionException {
         RequestTrace trace = RequestTrace.newChild(null, plugin);
@@ -154,16 +156,33 @@ public Artifact resolve(Plugin plugin, 
List<RemoteRepository> repositories, Repo
 
     /**
      * @since 3.3.0
+     * @deprecated Is unused since 3.10.0
      */
+    @Deprecated
     public DependencyNode resolveCoreExtension(
             Plugin plugin,
             DependencyFilter dependencyFilter,
             List<RemoteRepository> repositories,
             RepositorySystemSession session)
             throws PluginResolutionException {
+        return resolveInternal(plugin, null /* pluginArtifact */, 
dependencyFilter, repositories, session)
+                .getRoot();
+    }
+
+    /**
+     * @since 3.10.0
+     */
+    @Override
+    public DependencyResult resolveCoreExtensionAndFlatten(
+            Plugin plugin,
+            DependencyFilter dependencyFilter,
+            List<RemoteRepository> repositories,
+            RepositorySystemSession session)
+            throws PluginResolutionException {
         return resolveInternal(plugin, null /* pluginArtifact */, 
dependencyFilter, repositories, session);
     }
 
+    @Override
     public DependencyNode resolve(
             Plugin plugin,
             Artifact pluginArtifact,
@@ -171,10 +190,22 @@ public DependencyNode resolve(
             List<RemoteRepository> repositories,
             RepositorySystemSession session)
             throws PluginResolutionException {
+        return resolveInternal(plugin, pluginArtifact, dependencyFilter, 
repositories, session)
+                .getRoot();
+    }
+
+    @Override
+    public DependencyResult resolvePluginAndFlatten(
+            Plugin plugin,
+            Artifact pluginArtifact,
+            DependencyFilter dependencyFilter,
+            List<RemoteRepository> repositories,
+            RepositorySystemSession session)
+            throws PluginResolutionException {
         return resolveInternal(plugin, pluginArtifact, dependencyFilter, 
repositories, session);
     }
 
-    private DependencyNode resolveInternal(
+    private DependencyResult resolveInternal(
             Plugin plugin,
             Artifact pluginArtifact,
             DependencyFilter dependencyFilter,
@@ -190,8 +221,6 @@ private DependencyNode resolveInternal(
         DependencyFilter collectionFilter = new 
ScopeDependencyFilter("provided", "test");
         DependencyFilter resolutionFilter = 
AndDependencyFilter.newInstance(collectionFilter, dependencyFilter);
 
-        DependencyNode node;
-
         try {
             DependencySelector selector =
                     
AndDependencySelector.newInstance(session.getDependencySelector(), new 
WagonExcluder());
@@ -221,14 +250,16 @@ private DependencyNode resolveInternal(
 
             request.setTrace(RequestTrace.newChild(trace, depRequest));
 
-            node = repoSystem.collectDependencies(pluginSession, 
request).getRoot();
+            DependencyNode node =
+                    repoSystem.collectDependencies(pluginSession, 
request).getRoot();
 
             if (logger.isDebugEnabled()) {
                 node.accept(new GraphLogger());
             }
 
             depRequest.setRoot(node);
-            repoSystem.resolveDependencies(session, depRequest);
+            return repoSystem.resolveDependencies(session, depRequest);
+
         } catch (DependencyCollectionException e) {
             throw new PluginResolutionException(
                     plugin, e.getResult().getExceptions(), 
logger.isDebugEnabled() ? e : null);
@@ -241,8 +272,6 @@ private DependencyNode resolveInternal(
                     .collect(Collectors.toList());
             throw new PluginResolutionException(plugin, exceptions, 
logger.isDebugEnabled() ? e : null);
         }
-
-        return node;
     }
 
     // Keep this class in sync with 
org.apache.maven.project.DefaultProjectDependenciesResolver.GraphLogger
diff --git 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/PluginDependenciesResolver.java
 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/PluginDependenciesResolver.java
index 0f865df277..957365a293 100644
--- 
a/maven-core/src/main/java/org/apache/maven/plugin/internal/PluginDependenciesResolver.java
+++ 
b/maven-core/src/main/java/org/apache/maven/plugin/internal/PluginDependenciesResolver.java
@@ -27,6 +27,7 @@
 import org.eclipse.aether.graph.DependencyFilter;
 import org.eclipse.aether.graph.DependencyNode;
 import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.DependencyResult;
 
 /**
  * Assists in resolving the dependencies of a plugin. 
<strong>Warning:</strong> This is an internal utility interface
@@ -61,7 +62,9 @@ Artifact resolve(Plugin plugin, List<RemoteRepository> 
repositories, RepositoryS
      * @param session The repository session to use for resolving the plugin 
artifacts, must not be {@code null}.
      * @return The dependency tree denoting the resolved plugin class path, 
never {@code null}.
      * @throws PluginResolutionException If any dependency could not be 
resolved.
+     * @deprecated This method should be avoided, as it requires manual 
flattening; use {@link #resolvePluginAndFlatten(Plugin, Artifact, 
DependencyFilter, List, RepositorySystemSession)} instead to let Resolver 
handle it.
      */
+    @Deprecated
     DependencyNode resolve(
             Plugin plugin,
             Artifact pluginArtifact,
@@ -69,4 +72,42 @@ DependencyNode resolve(
             List<RemoteRepository> repositories,
             RepositorySystemSession session)
             throws PluginResolutionException;
+
+    /**
+     * Resolves the runtime dependencies of the specified core extension (as 
{@link Plugin} as GAV carrier).
+     *
+     * @param plugin The plugin for which to resolve the dependencies, must 
not be {@code null}.
+     * @param dependencyFilter A filter to exclude artifacts from resolution 
(but not collection), may be {@code null}.
+     * @param repositories The plugin repositories to use for resolving the 
plugin artifacts, must not be {@code null}.
+     * @param session The repository session to use for resolving the plugin 
artifacts, must not be {@code null}.
+     * @return The dependency resolution result having the resolved extension 
class path but also the tree, never {@code null}.
+     * @throws PluginResolutionException If any dependency could not be 
resolved.
+     * @since 3.10.0
+     */
+    DependencyResult resolveCoreExtensionAndFlatten(
+            Plugin plugin,
+            DependencyFilter dependencyFilter,
+            List<RemoteRepository> repositories,
+            RepositorySystemSession session)
+            throws PluginResolutionException;
+
+    /**
+     * Resolves the runtime dependencies of the specified plugin.
+     *
+     * @param plugin The plugin for which to resolve the dependencies, must 
not be {@code null}.
+     * @param pluginArtifact The plugin's main artifact, may be {@code null}.
+     * @param dependencyFilter A filter to exclude artifacts from resolution 
(but not collection), may be {@code null}.
+     * @param repositories The plugin repositories to use for resolving the 
plugin artifacts, must not be {@code null}.
+     * @param session The repository session to use for resolving the plugin 
artifacts, must not be {@code null}.
+     * @return The dependency resolution result having the resolved plugin 
class path but also the tree, never {@code null}.
+     * @throws PluginResolutionException If any dependency could not be 
resolved.
+     * @since 3.10.0
+     */
+    DependencyResult resolvePluginAndFlatten(
+            Plugin plugin,
+            Artifact pluginArtifact,
+            DependencyFilter dependencyFilter,
+            List<RemoteRepository> repositories,
+            RepositorySystemSession session)
+            throws PluginResolutionException;
 }
diff --git 
a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
 
b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
index c11e6ce893..53e20302d8 100644
--- 
a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
+++ 
b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java
@@ -26,6 +26,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.apache.maven.RepositoryUtils;
 import org.apache.maven.cli.internal.extension.model.CoreExtension;
@@ -35,7 +36,7 @@
 import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory;
 import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.PluginResolutionException;
-import org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver;
+import org.apache.maven.plugin.internal.PluginDependenciesResolver;
 import org.codehaus.plexus.DefaultPlexusContainer;
 import org.codehaus.plexus.PlexusContainer;
 import org.codehaus.plexus.classworlds.ClassWorld;
@@ -48,10 +49,10 @@
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.graph.DependencyFilter;
-import org.eclipse.aether.graph.DependencyNode;
 import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.resolution.DependencyResult;
 import org.eclipse.aether.util.filter.ExclusionsDependencyFilter;
-import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
 
 /**
  * BootstrapCoreExtensionManager
@@ -64,7 +65,7 @@ public class BootstrapCoreExtensionManager {
 
     private final Logger log;
 
-    private final DefaultPluginDependenciesResolver pluginDependenciesResolver;
+    private final PluginDependenciesResolver pluginDependenciesResolver;
 
     private final DefaultRepositorySystemSessionFactory 
repositorySystemSessionFactory;
 
@@ -77,7 +78,7 @@ public class BootstrapCoreExtensionManager {
     @Inject
     public BootstrapCoreExtensionManager(
             Logger log,
-            DefaultPluginDependenciesResolver pluginDependenciesResolver,
+            PluginDependenciesResolver pluginDependenciesResolver,
             DefaultRepositorySystemSessionFactory 
repositorySystemSessionFactory,
             CoreExports coreExports,
             PlexusContainer container) {
@@ -174,13 +175,12 @@ private List<Artifact> resolveExtension(
             
plugin.setArtifactId(interpolator.interpolate(extension.getArtifactId()));
             
plugin.setVersion(interpolator.interpolate(extension.getVersion()));
 
-            DependencyNode root = 
pluginDependenciesResolver.resolveCoreExtension(
+            DependencyResult result = 
pluginDependenciesResolver.resolveCoreExtensionAndFlatten(
                     plugin, dependencyFilter, repositories, repoSession);
-            PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
-            root.accept(nlg);
-            List<Artifact> artifacts = nlg.getArtifacts(false);
-
-            return artifacts;
+            return result.getArtifactResults().stream()
+                    .filter(ArtifactResult::isResolved)
+                    .map(ArtifactResult::getArtifact)
+                    .collect(Collectors.toList());
         } catch (PluginResolutionException | InterpolationException e) {
             throw new ExtensionResolutionException(extension, e);
         }

Reply via email to