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 8e4041759bd7cbd5dd807577b66f9f79252ef33b Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Wed Jan 29 14:50:02 2025 +0100 [MNG-8540] Add global caching in the session --- .../maven/internal/impl/DefaultProjectBuilder.java | 7 ++ .../apache/maven/internal/impl/DefaultSession.java | 1 + .../impl/ConsumerPomBuilderTest.java | 39 -------- .../maven/api/services/model/ModelResolver.java | 89 +++++++++++------ .../org/apache/maven/impl/AbstractSession.java | 76 +++++++++++++++ .../apache/maven/impl/DefaultArtifactResolver.java | 5 + .../maven/impl/DefaultVersionRangeResolver.java | 5 + .../apache/maven/impl/DefaultVersionResolver.java | 4 + .../org/apache/maven/impl/InternalSession.java | 17 ++++ .../maven/impl/model/DefaultModelBuilder.java | 87 +---------------- .../maven/impl/resolver/DefaultModelResolver.java | 107 ++++++++++++--------- 11 files changed, 239 insertions(+), 198 deletions(-) diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java index 06690ec1b5..b51241642a 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java @@ -42,6 +42,7 @@ import org.apache.maven.api.services.Source; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.impl.DefaultDependencyResolverResult; +import org.apache.maven.impl.InternalSession; import org.apache.maven.impl.MappedCollection; import org.apache.maven.impl.RequestTraceHelper; import org.apache.maven.model.building.ModelProblem; @@ -67,6 +68,12 @@ public DefaultProjectBuilder(org.apache.maven.project.ProjectBuilder builder) { @Override public ProjectBuilderResult build(ProjectBuilderRequest request) throws ProjectBuilderException, IllegalArgumentException { + InternalSession session = InternalSession.from(request.getSession()); + return session.request(request, this::doBuild); + } + + protected ProjectBuilderResult doBuild(ProjectBuilderRequest request) + throws ProjectBuilderException, IllegalArgumentException { InternalMavenSession session = InternalMavenSession.from(request.getSession()); RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(request.getSession(), request); try { diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index f87c95310e..d105759853 100644 --- a/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -182,6 +182,7 @@ public Map<String, Object> getPluginContext(Project project) { } } + @Override protected Session newSession(RepositorySystemSession repoSession, List<RemoteRepository> repositories) { final MavenSession ms = nonNull(getMavenSession()); final MavenSession mss; diff --git a/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java b/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java index a5ff690b9a..23d94c7e85 100644 --- a/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java +++ b/impl/maven-core/src/test/java/org/apache/maven/internal/transformation/impl/ConsumerPomBuilderTest.java @@ -24,12 +24,10 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; import org.apache.maven.api.DependencyCoordinates; import org.apache.maven.api.Node; import org.apache.maven.api.PathScope; -import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Session; import org.apache.maven.api.SessionData; import org.apache.maven.api.model.Model; @@ -37,11 +35,7 @@ import org.apache.maven.api.services.DependencyResolverResult; import org.apache.maven.api.services.ModelBuilder; import org.apache.maven.api.services.ModelBuilderRequest; -import org.apache.maven.api.services.ModelSource; import org.apache.maven.api.services.Sources; -import org.apache.maven.api.services.model.ModelResolver; -import org.apache.maven.api.services.model.ModelResolverException; -import org.apache.maven.di.Injector; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.impl.DefaultArtifactCoordinatesFactory; import org.apache.maven.impl.DefaultDependencyCoordinatesFactory; @@ -52,7 +46,6 @@ import org.apache.maven.internal.impl.InternalMavenSession; import org.apache.maven.internal.transformation.AbstractRepositoryTestCase; import org.apache.maven.project.MavenProject; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -67,15 +60,6 @@ public class ConsumerPomBuilderTest extends AbstractRepositoryTestCase { @Inject ModelBuilder modelBuilder; - @BeforeEach - void setupTransformerContext() throws Exception { - // We need bind the model resolver explicitly to avoid going to maven central - getContainer().lookup(Injector.class).bindImplicit(MyModelResolver.class); - InternalSession iSession = InternalSession.from(session); - // set up the model resolver - iSession.getData().set(SessionData.key(ModelResolver.class), new MyModelResolver()); - } - @Override protected List<Object> getSessionServices() { List<Object> services = new ArrayList<>(super.getSessionServices()); @@ -152,27 +136,4 @@ void testSimpleConsumer() throws Exception { assertNotNull(model); assertTrue(model.getProfiles().isEmpty()); } - - static class MyModelResolver implements ModelResolver { - @Override - public ModelSource resolveModel( - Session session, - List<RemoteRepository> repositories, - String groupId, - String artifactId, - String version, - String classifier, - Consumer<String> resolvedVersion) - throws ModelResolverException { - String id = groupId + ":" + artifactId + ":" + version; - if (id.startsWith("org.sonatype.mavenbook.multi:parent:")) { - return Sources.buildSource(Paths.get("src/test/resources/consumer/simple/pom.xml")); - } else if (id.startsWith("org.sonatype.mavenbook.multi:simple-parent:")) { - return Sources.buildSource(Paths.get("src/test/resources/consumer/simple/simple-parent/pom.xml")); - } else if (id.startsWith("org.my.group:parent:")) { - return Sources.buildSource(Paths.get("src/test/resources/consumer/trivial/pom.xml")); - } - return null; - } - } } diff --git a/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java index aa8ffdbfe8..0a7cbb621c 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/api/services/model/ModelResolver.java @@ -19,8 +19,8 @@ package org.apache.maven.api.services.model; import java.util.List; +import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Service; @@ -30,6 +30,9 @@ import org.apache.maven.api.model.Dependency; import org.apache.maven.api.model.Parent; import org.apache.maven.api.services.ModelSource; +import org.apache.maven.api.services.Request; +import org.apache.maven.api.services.RequestTrace; +import org.apache.maven.api.services.Result; /** * Resolves a POM from its coordinates. @@ -47,21 +50,12 @@ public interface ModelResolver extends Service { * @throws ModelResolverException If the POM could not be resolved from any configured repository. */ @Nonnull - default ModelSource resolveModel( + ModelSource resolveModel( @Nonnull Session session, @Nullable List<RemoteRepository> repositories, @Nonnull Parent parent, @Nonnull AtomicReference<Parent> modified) - throws ModelResolverException { - return resolveModel( - session, - repositories, - parent.getGroupId(), - parent.getArtifactId(), - parent.getVersion(), - null, - version -> modified.set(parent.withVersion(version))); - } + throws ModelResolverException; /** * Tries to resolve the POM for the specified dependency coordinates possibly updating {@code dependency}. @@ -74,30 +68,71 @@ default ModelSource resolveModel( * @throws ModelResolverException If the POM could not be resolved from any configured repository. */ @Nonnull - default ModelSource resolveModel( + ModelSource resolveModel( @Nonnull Session session, @Nullable List<RemoteRepository> repositories, @Nonnull Dependency dependency, @Nonnull AtomicReference<Dependency> modified) - throws ModelResolverException { - return resolveModel( - session, - repositories, - dependency.getGroupId(), - dependency.getArtifactId(), - dependency.getVersion(), - dependency.getClassifier(), - version -> modified.set(dependency.withVersion(version))); - } + throws ModelResolverException; @Nonnull - ModelSource resolveModel( + ModelResolverResult resolveModel(@Nonnull ModelResolverRequest request) throws ModelResolverException; + + record ModelResolverRequest( @Nonnull Session session, + @Nullable RequestTrace trace, @Nullable List<RemoteRepository> repositories, @Nonnull String groupId, @Nonnull String artifactId, @Nonnull String version, - @Nullable String classifier, - @Nonnull Consumer<String> resolvedVersion) - throws ModelResolverException; + @Nullable String classifier) + implements Request<Session> { + @Nonnull + @Override + public Session getSession() { + return session; + } + + @Nullable + @Override + public RequestTrace getTrace() { + return trace; + } + + @Override + public boolean equals(Object o) { + return o instanceof ModelResolverRequest that + && repositories == that.repositories + && Objects.equals(groupId, that.groupId) + && Objects.equals(artifactId, that.artifactId) + && Objects.equals(version, that.version) + && Objects.equals(classifier, that.classifier); + } + + @Override + public int hashCode() { + return Objects.hash(repositories, groupId, artifactId, version, classifier); + } + + @Override + @Nonnull + public String toString() { + return getClass().getSimpleName() + "[" + "repositories=" + + repositories + ", groupId=" + + groupId + + ", artifactId=" + artifactId + + ", version=" + version + + ", classifier=" + classifier + + ']'; + } + } + + record ModelResolverResult(ModelResolverRequest request, ModelSource source, String version) + implements Result<ModelResolverRequest> { + @Nonnull + @Override + public ModelResolverRequest getRequest() { + return request; + } + } } diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java index 117b81fa45..0f511ae09e 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/AbstractSession.java @@ -31,6 +31,7 @@ import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -84,7 +85,9 @@ import org.apache.maven.api.services.PathScopeRegistry; import org.apache.maven.api.services.ProjectScopeRegistry; import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.Request; import org.apache.maven.api.services.RequestTrace; +import org.apache.maven.api.services.Result; import org.apache.maven.api.services.TypeRegistry; import org.apache.maven.api.services.VersionParser; import org.apache.maven.api.services.VersionRangeResolver; @@ -116,6 +119,8 @@ public abstract class AbstractSession implements InternalSession { private final Map<org.eclipse.aether.graph.Dependency, Dependency> allDependencies = Collections.synchronizedMap(new WeakHashMap<>()); + private final Map<Object, CachingSupplier<?, ?>> requestCache; + static { TransferResource.setClock(MonotonicClock.get()); } @@ -130,6 +135,77 @@ public AbstractSession( this.repositorySystem = repositorySystem; this.repositories = getRepositories(repositories, resolverRepositories); this.lookup = lookup; + this.requestCache = new ConcurrentHashMap<>(); + } + + @Override + public <REQ extends Request<?>, REP extends Result<REQ>> REP request(REQ req, Function<REQ, REP> supplier) { + if (requestCache == null) { + return supplier.apply(req); + } + @SuppressWarnings("all") + CachingSupplier<REQ, REP> cs = + (CachingSupplier) requestCache.computeIfAbsent(req, r -> new CachingSupplier<>(supplier)); + return cs.apply(req); + } + + /** + * A caching supplier wrapper that caches results and exceptions from the underlying supplier. + * Used internally to cache expensive computations in the session. + * + * @param <REQ> The request type + * @param <REP> The response type + */ + static class CachingSupplier<REQ, REP> implements Function<REQ, REP> { + final Function<REQ, REP> supplier; + volatile Object value; + + CachingSupplier(Function<REQ, REP> supplier) { + this.supplier = supplier; + } + + @Override + @SuppressWarnings({"unchecked", "checkstyle:InnerAssignment"}) + public REP apply(REQ req) { + Object v; + if ((v = value) == null) { + synchronized (this) { + if ((v = value) == null) { + try { + v = value = supplier.apply(req); + } catch (Exception e) { + v = value = new CachingSupplier.AltRes(e); + } + } + } + } + if (v instanceof CachingSupplier.AltRes altRes) { + uncheckedThrow(altRes.t); + } + return (REP) v; + } + + /** + * Special holder class for exceptions that occur during supplier execution. + * Allows caching and re-throwing of exceptions on subsequent calls. + */ + static class AltRes { + final Throwable t; + + /** + * Creates a new AltRes with the given throwable. + * + * @param t The throwable to store + */ + AltRes(Throwable t) { + this.t = t; + } + } + } + + @SuppressWarnings("unchecked") + static <T extends Throwable> void uncheckedThrow(Throwable t) throws T { + throw (T) t; // rely on vacuous cast } @Override diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java index b83d649206..8331100d23 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultArtifactResolver.java @@ -50,6 +50,11 @@ public class DefaultArtifactResolver implements ArtifactResolver { public ArtifactResolverResult resolve(ArtifactResolverRequest request) throws ArtifactResolverException, IllegalArgumentException { nonNull(request, "request"); + InternalSession session = InternalSession.from(request.getSession()); + return session.request(request, this::doResolve); + } + + protected ArtifactResolverResult doResolve(ArtifactResolverRequest request) { InternalSession session = InternalSession.from(request.getSession()); RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request); try { diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java index a189d4328a..b3ef4d59b8 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionRangeResolver.java @@ -57,7 +57,12 @@ public VersionRangeResolverResult resolve(VersionRangeResolverRequest request) throws VersionRangeResolverException { requireNonNull(request, "request"); InternalSession session = InternalSession.from(request.getSession()); + return session.request(request, this::doResolve); + } + public VersionRangeResolverResult doResolve(VersionRangeResolverRequest request) + throws VersionRangeResolverException { + InternalSession session = InternalSession.from(request.getSession()); RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request); try { VersionRangeResult res = repositorySystem.resolveVersionRange( diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java index a9b4ba4748..ff07e5bb26 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultVersionResolver.java @@ -52,7 +52,11 @@ public DefaultVersionResolver(RepositorySystem repositorySystem) { public VersionResolverResult resolve(VersionResolverRequest request) throws VersionResolverException { nonNull(request, "request"); InternalSession session = InternalSession.from(request.getSession()); + return session.request(request, this::doResolve); + } + protected VersionResolverResult doResolve(VersionResolverRequest request) throws VersionResolverException { + InternalSession session = InternalSession.from(request.getSession()); RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request); try { VersionRequest req = new VersionRequest( diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java index fe8a44715b..63c6fbcfc1 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/InternalSession.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.List; +import java.util.function.Function; import org.apache.maven.api.Artifact; import org.apache.maven.api.ArtifactCoordinates; @@ -31,7 +32,9 @@ import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.services.Request; import org.apache.maven.api.services.RequestTrace; +import org.apache.maven.api.services.Result; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; @@ -53,6 +56,20 @@ static void associate(org.eclipse.aether.RepositorySystemSession rsession, Sessi } } + /** + * Executes and optionally caches a request using the provided supplier function. If caching is enabled + * for this session, the result will be cached and subsequent identical requests will return the cached + * value without re-executing the supplier. + * + * @param <REQ> The request type + * @param <REP> The response type + * @param req The request object used as the cache key + * @param supplier The function to execute and cache the result + * @return The result from the supplier (either fresh or cached) + * @throws RuntimeException Any exception thrown by the supplier will be cached and re-thrown on subsequent calls + */ + <REQ extends Request<?>, REP extends Result<REQ>> REP request(REQ req, Function<REQ, REP> supplier); + RemoteRepository getRemoteRepository(org.eclipse.aether.repository.RemoteRepository repository); Node getNode(org.eclipse.aether.graph.DependencyNode node); diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java index a39f981a13..2809c0b19c 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java @@ -41,7 +41,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; import java.util.function.Supplier; import java.util.function.UnaryOperator; import java.util.regex.Matcher; @@ -1049,8 +1048,7 @@ Model resolveAndReadParentExternally(Model childModel, DefaultProfileActivationC modelSource = resolveReactorModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); if (modelSource == null) { AtomicReference<Parent> modified = new AtomicReference<>(); - modelSource = new CachingModelResolver() - .resolveModel(request.getSession(), repositories, parent, modified); + modelSource = modelResolver.resolveModel(request.getSession(), repositories, parent, modified); if (modified.get() != null) { parent = modified.get(); } @@ -1721,8 +1719,8 @@ private Model doLoadDependencyManagement( try { importSource = resolveReactorModel(groupId, artifactId, version); if (importSource == null) { - importSource = new CachingModelResolver() - .resolveModel(request.getSession(), repositories, dependency, new AtomicReference<>()); + importSource = modelResolver.resolveModel( + request.getSession(), repositories, dependency, new AtomicReference<>()); } } catch (ModelBuilderException | ModelResolverException e) { StringBuilder buffer = new StringBuilder(256); @@ -1815,85 +1813,6 @@ boolean isBuildRequest() { boolean isBuildRequestWithActivation() { return request.getRequestType() != ModelBuilderRequest.RequestType.BUILD_CONSUMER; } - - record ModelResolverResult(ModelSource source, String resolvedVersion) {} - - class CachingModelResolver implements ModelResolver { - @Override - public ModelSource resolveModel( - Session session, - List<RemoteRepository> repositories, - Parent parent, - AtomicReference<Parent> modified) - throws ModelResolverException { - ModelResolverResult result = cache.computeIfAbsent( - repositories, - parent.getGroupId(), - parent.getArtifactId(), - parent.getVersion(), - null, - MODEL, - () -> { - AtomicReference<Parent> mod = new AtomicReference<>(); - ModelSource res = modelResolver.resolveModel(session, repositories, parent, mod); - return new ModelResolverResult( - res, mod.get() != null ? mod.get().getVersion() : null); - }); - if (result.resolvedVersion != null && modified != null) { - modified.set(parent.withVersion(result.resolvedVersion)); - } - return result.source; - } - - @Override - public ModelSource resolveModel( - Session session, - List<RemoteRepository> repositories, - Dependency dependency, - AtomicReference<Dependency> modified) - throws ModelResolverException { - ModelResolverResult result = cache.computeIfAbsent( - repositories, - dependency.getGroupId(), - dependency.getArtifactId(), - dependency.getVersion(), - dependency.getClassifier(), - MODEL, - () -> { - AtomicReference<Dependency> mod = new AtomicReference<>(); - ModelSource res = modelResolver.resolveModel(session, repositories, dependency, mod); - return new ModelResolverResult( - res, mod.get() != null ? mod.get().getVersion() : null); - }); - if (result.resolvedVersion != null && modified != null) { - modified.set(dependency.withVersion(result.resolvedVersion)); - } - return result.source; - } - - @Override - public ModelSource resolveModel( - Session session, - List<RemoteRepository> repositories, - String groupId, - String artifactId, - String version, - String classifier, - Consumer<String> resolvedVersion) - throws ModelResolverException { - ModelResolverResult result = - cache.computeIfAbsent(repositories, groupId, artifactId, version, classifier, MODEL, () -> { - AtomicReference<String> mod = new AtomicReference<>(); - ModelSource res = modelResolver.resolveModel( - session, repositories, groupId, artifactId, version, classifier, mod::set); - return new ModelResolverResult(res, mod.get()); - }); - if (result.resolvedVersion != null) { - resolvedVersion.accept(result.resolvedVersion); - } - return result.source; - } - } } @SuppressWarnings("deprecation") diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultModelResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultModelResolver.java index 69bf46c759..0abee8de30 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultModelResolver.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultModelResolver.java @@ -21,7 +21,6 @@ import java.nio.file.Path; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; import java.util.stream.Collectors; import org.apache.maven.api.ArtifactCoordinates; @@ -41,6 +40,8 @@ import org.apache.maven.api.services.VersionRangeResolverException; import org.apache.maven.api.services.model.ModelResolver; import org.apache.maven.api.services.model.ModelResolverException; +import org.apache.maven.impl.InternalSession; +import org.apache.maven.impl.RequestTraceHelper; /** * A model resolver to assist building of dependency POMs. @@ -59,16 +60,21 @@ public ModelSource resolveModel( @Nonnull Parent parent, @Nonnull AtomicReference<Parent> modified) throws ModelResolverException { - return resolveModel( - session, - repositories, - parent.getGroupId(), - parent.getArtifactId(), - parent.getVersion(), - "parent", - null, + ModelResolverResult result = resolveModel( + new ModelResolverRequest( + session, + null, + repositories, + parent.getGroupId(), + parent.getArtifactId(), + parent.getVersion(), + null), parent.getLocation("version"), - version -> modified.set(parent.withVersion(version))); + "parent"); + if (result.version() != null) { + modified.set(parent.withVersion(result.version())); + } + return result.source(); } @Nonnull @@ -78,44 +84,46 @@ public ModelSource resolveModel( @Nonnull Dependency dependency, @Nonnull AtomicReference<Dependency> modified) throws ModelResolverException { - return resolveModel( - session, - repositories, - dependency.getGroupId(), - dependency.getArtifactId(), - dependency.getVersion(), - "dependency", - dependency.getClassifier(), + ModelResolverResult result = resolveModel( + new ModelResolverRequest( + session, + null, + repositories, + dependency.getGroupId(), + dependency.getArtifactId(), + dependency.getVersion(), + dependency.getClassifier()), dependency.getLocation("version"), - version -> modified.set(dependency.withVersion(version))); + "dependency"); + if (result.version() != null) { + modified.set(dependency.withVersion(result.version())); + } + return result.source(); } + @Nonnull @Override - public ModelSource resolveModel( - @Nonnull Session session, - @Nullable List<RemoteRepository> repositories, - @Nonnull String groupId, - @Nonnull String artifactId, - @Nonnull String version, - @Nullable String classifier, - @Nonnull Consumer<String> resolvedVersion) + public ModelResolverResult resolveModel(@Nonnull ModelResolverRequest request) throws ModelResolverException { + return resolveModel(request, null, null); + } + + public ModelResolverResult resolveModel( + @Nonnull ModelResolverRequest request, InputLocation location, String modelType) throws ModelResolverException { - return resolveModel( - session, repositories, groupId, artifactId, version, null, classifier, null, resolvedVersion); + return InternalSession.from(request.session()).request(request, r -> doResolveModel(r, location, modelType)); } - @SuppressWarnings("checkstyle:ParameterNumber") - public ModelSource resolveModel( - Session session, - List<RemoteRepository> repositories, - String groupId, - String artifactId, - String version, - String type, - String classifier, - InputLocation location, - Consumer<String> resolvedVersion) + public ModelResolverResult doResolveModel( + @Nonnull ModelResolverRequest request, InputLocation location, String modelType) throws ModelResolverException { + Session session = request.session(); + String groupId = request.groupId(); + String artifactId = request.artifactId(); + String version = request.version(); + String classifier = request.classifier(); + List<RemoteRepository> repositories = request.repositories(); + + RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request); try { ArtifactCoordinates coords = session.createArtifactCoordinates(groupId, artifactId, version, classifier, "pom", null); @@ -123,7 +131,8 @@ public ModelSource resolveModel( && coords.getVersionConstraint().getVersionRange().getUpperBoundary() == null) { // Message below is checked for in the MNG-2199 core IT. throw new ModelResolverException( - "The requested " + (type != null ? type + " " : "") + "version range '" + version + "'" + "The requested " + (modelType != null ? modelType + " " : "") + "version range '" + version + + "'" + (location != null ? " (at " + location + ")" : "") + " does not specify an upper bound", groupId, @@ -132,18 +141,18 @@ public ModelSource resolveModel( } String newVersion = session.resolveHighestVersion(coords, repositories) .orElseThrow(() -> new ModelResolverException( - "No versions matched the requested " + (type != null ? type + " " : "") + "version range '" - + version + "'", + "No versions matched the requested " + (modelType != null ? modelType + " " : "") + + "version range '" + version + "'", groupId, artifactId, version)) .asString(); - if (!version.equals(newVersion)) { - resolvedVersion.accept(newVersion); - } - + String resultVersion = version.equals(newVersion) ? null : newVersion; Path path = getPath(session, repositories, groupId, artifactId, newVersion, classifier); - return Sources.resolvedSource(path, groupId + ":" + artifactId + ":" + newVersion); + return new ModelResolverResult( + request, + Sources.resolvedSource(path, groupId + ":" + artifactId + ":" + newVersion), + resultVersion); } catch (VersionRangeResolverException | ArtifactResolverException e) { throw new ModelResolverException( e.getMessage() + " (remote repositories: " @@ -154,6 +163,8 @@ public ModelSource resolveModel( artifactId, version, e); + } finally { + RequestTraceHelper.exit(trace); } }