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

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 8418fb39604eb3901c6606d8a92b34fc4fafa2b4
Author: Guillaume Nodet <gno...@gmail.com>
AuthorDate: Tue Apr 2 15:07:01 2024 +0200

    Cache parent artifact resolution
---
 maven-core/pom.xml                                 |  1 +
 .../impl/DefaultConsumerPomBuilder.java            |  1 +
 .../maven/project/DefaultProjectBuilder.java       |  5 +-
 .../apache/maven/project/ProjectModelResolver.java | 66 +++++++++++++++++++++-
 .../maven/project/ProjectModelResolverTest.java    |  1 +
 5 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/maven-core/pom.xml b/maven-core/pom.xml
index 86f84af70c..7675a3eb5f 100644
--- a/maven-core/pom.xml
+++ b/maven-core/pom.xml
@@ -304,6 +304,7 @@ under the License.
               <!-- END default constructor on Plexus/JSR 330 components -->
               <!-- system property with that name no longer evaluated -->
               
<exclude>org.apache.maven.project.DefaultProjectBuilder#DISABLE_GLOBAL_MODEL_CACHE_SYSTEM_PROPERTY</exclude>
+              
<exclude>org.apache.maven.project.ProjectModelResolver#ProjectModelResolver(org.eclipse.aether.RepositorySystemSession,org.eclipse.aether.RequestTrace,org.eclipse.aether.RepositorySystem,org.eclipse.aether.impl.RemoteRepositoryManager,java.util.List,org.apache.maven.project.ProjectBuildingRequest$RepositoryMerging,org.apache.maven.project.ReactorModelPool):CONSTRUCTOR_REMOVED</exclude>
               <!-- was only a workaround for Plexus Container, hopefully never 
used by anyone else -->
               
<exclude>org.apache.maven.plugin.DefaultBuildPluginManager#setMojoExecutionListeners(java.util.List)</exclude>
               <!-- could have never been used due to usage of non-export class 
(CoreExportsProvider) -->
diff --git 
a/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
 
b/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
index 79f2cb7363..336e344b43 100644
--- 
a/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
+++ 
b/maven-core/src/main/java/org/apache/maven/internal/transformation/impl/DefaultConsumerPomBuilder.java
@@ -208,6 +208,7 @@ class DefaultConsumerPomBuilder implements 
ConsumerPomBuilder {
                 remoteRepositoryManager,
                 project.getRemoteProjectRepositories(),
                 ProjectBuildingRequest.RepositoryMerging.POM_DOMINANT,
+                null,
                 null));
         
request.setTransformerContextBuilder(modelBuilder.newTransformerContextBuilder());
         
request.setSystemProperties(toProperties(session.getSystemProperties()));
diff --git 
a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java 
b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
index be2d16a94f..203e97b106 100644
--- 
a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
+++ 
b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
@@ -206,6 +206,7 @@ public class DefaultProjectBuilder implements 
ProjectBuilder {
         private final RepositorySystemSession session;
         private final List<RemoteRepository> repositories;
         private final ReactorModelPool modelPool;
+        private final ConcurrentMap<String, Object> parentCache;
         private final TransformerContextBuilder transformerContextBuilder;
         private final ExecutorService executor;
 
@@ -222,6 +223,7 @@ public class DefaultProjectBuilder implements 
ProjectBuilder {
                 this.modelPool = null;
                 this.transformerContextBuilder = null;
             }
+            this.parentCache = new ConcurrentHashMap<>();
         }
 
         ExecutorService createExecutor(int parallelism) {
@@ -893,7 +895,8 @@ public class DefaultProjectBuilder implements 
ProjectBuilder {
                     repositoryManager,
                     repositories,
                     request.getRepositoryMerging(),
-                    modelPool);
+                    modelPool,
+                    parentCache);
 
             
modelBuildingRequest.setValidationLevel(request.getValidationLevel());
             modelBuildingRequest.setProcessPlugins(request.isProcessPlugins());
diff --git 
a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java 
b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java
index 0ae5bba9ad..723a56dd3b 100644
--- 
a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java
+++ 
b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java
@@ -23,7 +23,11 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.maven.api.model.Dependency;
@@ -57,6 +61,8 @@ import org.eclipse.aether.resolution.VersionRangeResult;
  */
 public class ProjectModelResolver implements ModelResolver {
 
+    private static final int MAX_CAP = 0x7fff;
+
     private final RepositorySystemSession session;
 
     private final RequestTrace trace;
@@ -79,6 +85,8 @@ public class ProjectModelResolver implements ModelResolver {
 
     private final ProjectBuildingRequest.RepositoryMerging repositoryMerging;
 
+    private final Map<String, ForkJoinTask<Result>> parentCache;
+
     public ProjectModelResolver(
             RepositorySystemSession session,
             RequestTrace trace,
@@ -86,7 +94,8 @@ public class ProjectModelResolver implements ModelResolver {
             RemoteRepositoryManager remoteRepositoryManager,
             List<RemoteRepository> repositories,
             ProjectBuildingRequest.RepositoryMerging repositoryMerging,
-            ReactorModelPool modelPool) {
+            ReactorModelPool modelPool,
+            Map<String, Object> parentCache) {
         this.session = session;
         this.trace = trace;
         this.resolver = resolver;
@@ -98,6 +107,7 @@ public class ProjectModelResolver implements ModelResolver {
         this.repositoryMerging = repositoryMerging;
         this.repositoryIds = new HashSet<>();
         this.modelPool = modelPool;
+        this.parentCache = parentCache != null ? (Map) parentCache : new 
ConcurrentHashMap<>();
     }
 
     private ProjectModelResolver(ProjectModelResolver original) {
@@ -111,6 +121,7 @@ public class ProjectModelResolver implements ModelResolver {
         this.repositoryMerging = original.repositoryMerging;
         this.repositoryIds = new HashSet<>(original.repositoryIds);
         this.modelPool = original.modelPool;
+        this.parentCache = original.parentCache;
     }
 
     public void addRepository(Repository repository) throws 
InvalidRepositoryException {
@@ -171,9 +182,62 @@ public class ProjectModelResolver implements ModelResolver 
{
         return new ArtifactModelSource(pomArtifact.getFile(), groupId, 
artifactId, version);
     }
 
+    record Result(ModelSource source, Parent parent, Exception e) {}
+
+    private ForkJoinPool pool = new ForkJoinPool(MAX_CAP);
+
     @Override
     public ModelSource resolveModel(final Parent parent, 
AtomicReference<Parent> modified)
             throws UnresolvableModelException {
+        Result result;
+        try {
+            ForkJoinTask<Result> future = 
parentCache.computeIfAbsent(parent.getId(), id -> new ForkJoinTask<>() {
+                Result result;
+
+                @Override
+                public Result getRawResult() {
+                    return result;
+                }
+
+                @Override
+                protected void setRawResult(Result result) {
+                    this.result = result;
+                }
+
+                @Override
+                protected boolean exec() {
+                    try {
+                        AtomicReference<Parent> modified = new 
AtomicReference<>();
+                        ModelSource source = doResolveModel(parent, modified);
+                        result = new Result(source, modified.get(), null);
+                    } catch (Exception e) {
+                        result = new Result(null, null, e);
+                    }
+                    return true;
+                }
+            });
+            pool.execute(future);
+            result = future.get();
+        } catch (Exception e) {
+            throw new UnresolvableModelException(e, parent.getGroupId(), 
parent.getArtifactId(), parent.getVersion());
+        }
+        if (result.e != null) {
+            uncheckedThrow(result.e);
+            return null;
+        } else {
+            if (result.parent != null && modified != null) {
+                modified.set(result.parent);
+            }
+            return result.source;
+        }
+    }
+
+    static <T extends Throwable> void uncheckedThrow(Throwable t) throws T {
+        throw (T) t; // rely on vacuous cast
+    }
+
+    private ModelSource doResolveModel(Parent parent, AtomicReference<Parent> 
modified)
+            throws UnresolvableModelException {
         try {
             final Artifact artifact =
                     new DefaultArtifact(parent.getGroupId(), 
parent.getArtifactId(), "", "pom", parent.getVersion());
diff --git 
a/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java
 
b/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java
index e96d324d93..f9621b23fc 100644
--- 
a/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java
+++ 
b/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java
@@ -200,6 +200,7 @@ class ProjectModelResolverTest extends 
AbstractMavenProjectTestCase {
                 getContainer().lookup(RemoteRepositoryManager.class),
                 this.getRemoteRepositories(),
                 ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT,
+                null,
                 null);
     }
 

Reply via email to