From 8418fb39604eb3901c6606d8a92b34fc4fafa2b4 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 2 Apr 2024 15:07:01 +0200 Subject: [PATCH] Cache parent artifact resolution --- maven-core/pom.xml | 1 + .../impl/DefaultConsumerPomBuilder.java | 1 + .../maven/project/DefaultProjectBuilder.java | 5 +- .../maven/project/ProjectModelResolver.java | 66 ++++++++++++++++++- .../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. org.apache.maven.project.DefaultProjectBuilder#DISABLE_GLOBAL_MODEL_CACHE_SYSTEM_PROPERTY + 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 org.apache.maven.plugin.DefaultBuildPluginManager#setMojoExecutionListeners(java.util.List) 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 repositories; private final ReactorModelPool modelPool; + private final ConcurrentMap 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> parentCache; + public ProjectModelResolver( RepositorySystemSession session, RequestTrace trace, @@ -86,7 +94,8 @@ public class ProjectModelResolver implements ModelResolver { RemoteRepositoryManager remoteRepositoryManager, List repositories, ProjectBuildingRequest.RepositoryMerging repositoryMerging, - ReactorModelPool modelPool) { + ReactorModelPool modelPool, + Map 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 modified) throws UnresolvableModelException { + Result result; + try { + ForkJoinTask 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 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 void uncheckedThrow(Throwable t) throws T { + throw (T) t; // rely on vacuous cast + } + + private ModelSource doResolveModel(Parent parent, AtomicReference 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); }