You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2025/01/29 08:17:12 UTC
(maven) branch master updated: [MNG-8519] Introduce Request / Results / RequestTrace (#2050)
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
The following commit(s) were added to refs/heads/master by this push:
new 2155d9f0c2 [MNG-8519] Introduce Request / Results / RequestTrace (#2050)
2155d9f0c2 is described below
commit 2155d9f0c240a0d01b3446868b46357924392738
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Wed Jan 29 09:17:07 2025 +0100
[MNG-8519] Introduce Request / Results / RequestTrace (#2050)
---
api/maven-api-core/pom.xml | 5 +
.../main/java/org/apache/maven/api/Session.java | 3 -
.../ArtifactCoordinatesFactoryRequest.java | 28 ++-
.../api/services/ArtifactDeployerRequest.java | 27 ++-
.../maven/api/services/ArtifactFactoryRequest.java | 29 ++-
.../api/services/ArtifactInstallerRequest.java | 26 ++-
.../api/services/ArtifactResolverRequest.java | 23 ++-
.../maven/api/services/ArtifactResolverResult.java | 2 +-
.../org/apache/maven/api/services/BaseRequest.java | 12 +-
.../DependencyCoordinatesFactoryRequest.java | 26 ++-
.../api/services/DependencyResolverRequest.java | 56 +++++-
.../api/services/DependencyResolverResult.java | 2 +-
.../maven/api/services/ModelBuilderRequest.java | 33 +++-
.../maven/api/services/ModelBuilderResult.java | 2 +-
.../maven/api/services/ProjectBuilderRequest.java | 27 ++-
.../maven/api/services/ProjectBuilderResult.java | 2 +-
.../org/apache/maven/api/services/Request.java | 91 ++++++++++
.../apache/maven/api/services/RequestTrace.java | 62 +++++++
.../{SettingsBuilderResult.java => Result.java} | 34 ++--
.../maven/api/services/SettingsBuilderRequest.java | 24 ++-
.../maven/api/services/SettingsBuilderResult.java | 2 +-
.../api/services/ToolchainsBuilderRequest.java | 22 ++-
.../api/services/ToolchainsBuilderResult.java | 2 +-
.../api/services/VersionRangeResolverRequest.java | 23 ++-
.../api/services/VersionRangeResolverResult.java | 2 +-
.../maven/api/services/VersionResolverRequest.java | 23 ++-
.../maven/api/services/VersionResolverResult.java | 2 +-
.../api/services/RequestImplementationTest.java | 79 +++++++++
.../maven/api/services/RequestTraceTest.java | 85 +++++++++
.../aether/ReverseTreeRepositoryListener.java | 8 +-
.../maven/internal/impl/DefaultProjectBuilder.java | 12 +-
.../DefaultPluginDependenciesResolver.java | 13 +-
.../internal/DefaultPluginPrefixResolver.java | 2 +-
.../internal/DefaultPluginVersionResolver.java | 2 +-
.../org/apache/maven/impl/AbstractSession.java | 17 ++
.../apache/maven/impl/DefaultArtifactResolver.java | 18 +-
.../maven/impl/DefaultDependencyResolver.java | 194 +++++++++++----------
.../impl/DefaultDependencyResolverResult.java | 17 +-
.../apache/maven/impl/DefaultSettingsBuilder.java | 13 +-
.../maven/impl/DefaultToolchainsBuilder.java | 14 +-
.../maven/impl/DefaultVersionRangeResolver.java | 21 ++-
.../apache/maven/impl/DefaultVersionResolver.java | 16 +-
.../org/apache/maven/impl/InternalSession.java | 24 +++
.../org/apache/maven/impl/RequestTraceHelper.java | 138 +++++++++++++++
.../maven/impl/model/DefaultModelBuilder.java | 84 ++++++---
.../impl/model/DefaultModelBuilderResult.java | 10 +-
.../resolver/DefaultArtifactDescriptorReader.java | 2 +
.../maven/impl/resolver/RequestTraceHelper.java | 69 --------
.../apache/maven/impl/RequestTraceHelperTest.java | 87 +++++++++
.../impl/model/DefaultModelBuilderResultTest.java | 109 ++++++++++++
.../maven/impl/standalone/RequestTraceTest.java | 106 +++++++++++
51 files changed, 1414 insertions(+), 316 deletions(-)
diff --git a/api/maven-api-core/pom.xml b/api/maven-api-core/pom.xml
index 6c1bb03326..4d97cb9d7f 100644
--- a/api/maven-api-core/pom.xml
+++ b/api/maven-api-core/pom.xml
@@ -65,6 +65,11 @@
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
index 39ae21a0cc..d9899dcc4c 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
@@ -38,9 +38,6 @@
/**
* The session to install / deploy / resolve artifacts and dependencies.
*
- * TODO: add request trace so that requests can be linked together and through the resolver
- * TODO: add a Request interface holding session + parent request
- *
* @since 4.0.0
*/
@Experimental
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinatesFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinatesFactoryRequest.java
index cf96d490fd..074c9bcebd 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinatesFactoryRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinatesFactoryRequest.java
@@ -34,10 +34,7 @@
*/
@Experimental
@Immutable
-public interface ArtifactCoordinatesFactoryRequest {
-
- @Nonnull
- Session getSession();
+public interface ArtifactCoordinatesFactoryRequest extends Request<Session> {
String getGroupId();
@@ -112,6 +109,7 @@ static ArtifactFactoryRequestBuilder builder() {
@NotThreadSafe
class ArtifactFactoryRequestBuilder {
private Session session;
+ private RequestTrace trace;
private String groupId;
private String artifactId;
private String version;
@@ -127,6 +125,11 @@ public ArtifactFactoryRequestBuilder session(Session session) {
return this;
}
+ public ArtifactFactoryRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public ArtifactFactoryRequestBuilder groupId(String groupId) {
this.groupId = groupId;
return this;
@@ -164,7 +167,7 @@ public ArtifactFactoryRequestBuilder coordinateString(String coordinateString) {
public ArtifactCoordinatesFactoryRequest build() {
return new DefaultArtifactFactoryRequestArtifact(
- session, groupId, artifactId, version, classifier, extension, type, coordinateString);
+ session, trace, groupId, artifactId, version, classifier, extension, type, coordinateString);
}
private static class DefaultArtifactFactoryRequestArtifact extends BaseRequest<Session>
@@ -180,6 +183,7 @@ private static class DefaultArtifactFactoryRequestArtifact extends BaseRequest<S
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultArtifactFactoryRequestArtifact(
@Nonnull Session session,
+ RequestTrace trace,
String groupId,
String artifactId,
String version,
@@ -187,7 +191,7 @@ private static class DefaultArtifactFactoryRequestArtifact extends BaseRequest<S
String extension,
String type,
String coordinatesString) {
- super(session);
+ super(session, trace);
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
@@ -230,6 +234,18 @@ public String getType() {
public String getCoordinatesString() {
return coordinatesString;
}
+
+ @Override
+ public String toString() {
+ return "ArtifactFactoryRequestArtifact[" + "groupId='"
+ + groupId + '\'' + ", artifactId='"
+ + artifactId + '\'' + ", version='"
+ + version + '\'' + ", classifier='"
+ + classifier + '\'' + ", extension='"
+ + extension + '\'' + ", type='"
+ + type + '\'' + ", coordinatesString='"
+ + coordinatesString + '\'' + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java
index 3c5dba3d9f..c2eaedf58b 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java
@@ -27,6 +27,7 @@
import org.apache.maven.api.annotations.Experimental;
import org.apache.maven.api.annotations.Immutable;
import org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.annotations.Nullable;
import static java.util.Objects.requireNonNull;
@@ -37,10 +38,7 @@
*/
@Experimental
@Immutable
-public interface ArtifactDeployerRequest {
-
- @Nonnull
- Session getSession();
+public interface ArtifactDeployerRequest extends Request<Session> {
@Nonnull
RemoteRepository getRepository();
@@ -69,6 +67,7 @@ static ArtifactDeployerRequest build(
class ArtifactDeployerRequestBuilder {
Session session;
+ RequestTrace trace;
RemoteRepository repository;
Collection<ProducedArtifact> artifacts;
int retryFailedDeploymentCount;
@@ -81,6 +80,12 @@ public ArtifactDeployerRequestBuilder session(Session session) {
return this;
}
+ @Nonnull
+ public ArtifactDeployerRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
@Nonnull
public ArtifactDeployerRequestBuilder repository(RemoteRepository repository) {
this.repository = repository;
@@ -99,7 +104,8 @@ public ArtifactDeployerRequestBuilder retryFailedDeploymentCount(int retryFailed
@Nonnull
public ArtifactDeployerRequest build() {
- return new DefaultArtifactDeployerRequest(session, repository, artifacts, retryFailedDeploymentCount);
+ return new DefaultArtifactDeployerRequest(
+ session, trace, repository, artifacts, retryFailedDeploymentCount);
}
private static class DefaultArtifactDeployerRequest extends BaseRequest<Session>
@@ -111,10 +117,11 @@ private static class DefaultArtifactDeployerRequest extends BaseRequest<Session>
DefaultArtifactDeployerRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
@Nonnull RemoteRepository repository,
@Nonnull Collection<ProducedArtifact> artifacts,
int retryFailedDeploymentCount) {
- super(session);
+ super(session, trace);
this.repository = requireNonNull(repository, "repository cannot be null");
this.artifacts = List.copyOf(requireNonNull(artifacts, "artifacts cannot be null"));
this.retryFailedDeploymentCount = retryFailedDeploymentCount;
@@ -136,6 +143,14 @@ public Collection<ProducedArtifact> getArtifacts() {
public int getRetryFailedDeploymentCount() {
return retryFailedDeploymentCount;
}
+
+ @Override
+ public String toString() {
+ return "ArtifactDeployerRequest[" + "repository="
+ + repository + ", artifacts="
+ + artifacts + ", retryFailedDeploymentCount="
+ + retryFailedDeploymentCount + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java
index 378eed1608..c162f42093 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java
@@ -23,6 +23,7 @@
import org.apache.maven.api.annotations.Immutable;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.NotThreadSafe;
+import org.apache.maven.api.annotations.Nullable;
import static java.util.Objects.requireNonNull;
@@ -33,10 +34,7 @@
*/
@Experimental
@Immutable
-public interface ArtifactFactoryRequest {
-
- @Nonnull
- Session getSession();
+public interface ArtifactFactoryRequest extends Request<Session> {
String getGroupId();
@@ -87,6 +85,7 @@ static ArtifactFactoryRequestBuilder builder() {
@NotThreadSafe
class ArtifactFactoryRequestBuilder {
private Session session;
+ private RequestTrace trace;
private String groupId;
private String artifactId;
private String version;
@@ -101,6 +100,11 @@ public ArtifactFactoryRequestBuilder session(Session session) {
return this;
}
+ public ArtifactFactoryRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public ArtifactFactoryRequestBuilder groupId(String groupId) {
this.groupId = groupId;
return this;
@@ -133,7 +137,7 @@ public ArtifactFactoryRequestBuilder type(String type) {
public ArtifactFactoryRequest build() {
return new DefaultArtifactFactoryRequest(
- session, groupId, artifactId, version, classifier, extension, type);
+ session, trace, groupId, artifactId, version, classifier, extension, type);
}
private static class DefaultArtifactFactoryRequest extends BaseRequest<Session>
@@ -145,15 +149,17 @@ private static class DefaultArtifactFactoryRequest extends BaseRequest<Session>
private final String extension;
private final String type;
+ @SuppressWarnings("checkstyle:ParameterNumber")
DefaultArtifactFactoryRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
String groupId,
String artifactId,
String version,
String classifier,
String extension,
String type) {
- super(session);
+ super(session, trace);
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
@@ -191,6 +197,17 @@ public String getExtension() {
public String getType() {
return type;
}
+
+ @Override
+ public String toString() {
+ return "ArtifactFactoryRequest[" + "groupId='"
+ + groupId + '\'' + ", artifactId='"
+ + artifactId + '\'' + ", version='"
+ + version + '\'' + ", classifier='"
+ + classifier + '\'' + ", extension='"
+ + extension + '\'' + ", type='"
+ + type + '\'' + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java
index badf60170d..7c3130aced 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java
@@ -39,10 +39,7 @@
*/
@Experimental
@Immutable
-public interface ArtifactInstallerRequest {
-
- @Nonnull
- Session getSession();
+public interface ArtifactInstallerRequest extends Request<Session> {
@Nonnull
Collection<ProducedArtifact> getArtifacts();
@@ -63,6 +60,7 @@ static ArtifactInstallerRequest build(Session session, Collection<ProducedArtifa
@NotThreadSafe
class ArtifactInstallerRequestBuilder {
Session session;
+ RequestTrace trace;
Collection<ProducedArtifact> artifacts = Collections.emptyList();
ArtifactInstallerRequestBuilder() {}
@@ -73,6 +71,12 @@ public ArtifactInstallerRequestBuilder session(@Nonnull Session session) {
return this;
}
+ @Nonnull
+ public ArtifactInstallerRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
@Nonnull
public ArtifactInstallerRequestBuilder artifacts(@Nullable Collection<ProducedArtifact> artifacts) {
this.artifacts = artifacts != null ? artifacts : Collections.emptyList();
@@ -81,15 +85,18 @@ public ArtifactInstallerRequestBuilder artifacts(@Nullable Collection<ProducedAr
@Nonnull
public ArtifactInstallerRequest build() {
- return new DefaultArtifactInstallerRequest(session, artifacts);
+ return new DefaultArtifactInstallerRequest(session, trace, artifacts);
}
static class DefaultArtifactInstallerRequest extends BaseRequest<Session> implements ArtifactInstallerRequest {
private final Collection<ProducedArtifact> artifacts;
- DefaultArtifactInstallerRequest(@Nonnull Session session, @Nonnull Collection<ProducedArtifact> artifacts) {
- super(session);
+ DefaultArtifactInstallerRequest(
+ @Nonnull Session session,
+ @Nullable RequestTrace trace,
+ @Nonnull Collection<ProducedArtifact> artifacts) {
+ super(session, trace);
this.artifacts = List.copyOf(requireNonNull(artifacts, "artifacts cannot be null"));
}
@@ -98,6 +105,11 @@ static class DefaultArtifactInstallerRequest extends BaseRequest<Session> implem
public Collection<ProducedArtifact> getArtifacts() {
return artifacts;
}
+
+ @Override
+ public String toString() {
+ return "ArtifactInstallerRequest[" + "artifacts=" + artifacts + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java
index ae937914e6..4651a07332 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java
@@ -39,9 +39,7 @@
*/
@Experimental
@Immutable
-public interface ArtifactResolverRequest {
- @Nonnull
- Session getSession();
+public interface ArtifactResolverRequest extends Request<Session> {
@Nonnull
Collection<? extends ArtifactCoordinates> getCoordinates();
@@ -78,6 +76,7 @@ static ArtifactResolverRequest build(
@NotThreadSafe
class ArtifactResolverRequestBuilder {
Session session;
+ RequestTrace trace;
Collection<? extends ArtifactCoordinates> coordinates;
List<RemoteRepository> repositories;
@@ -89,6 +88,12 @@ public ArtifactResolverRequestBuilder session(Session session) {
return this;
}
+ @Nonnull
+ public ArtifactResolverRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
@Nonnull
public ArtifactResolverRequestBuilder coordinates(Collection<? extends ArtifactCoordinates> coordinates) {
this.coordinates = coordinates;
@@ -103,7 +108,7 @@ public ArtifactResolverRequestBuilder repositories(List<RemoteRepository> reposi
@Nonnull
public ArtifactResolverRequest build() {
- return new DefaultArtifactResolverRequest(session, coordinates, repositories);
+ return new DefaultArtifactResolverRequest(session, trace, coordinates, repositories);
}
private static class DefaultArtifactResolverRequest extends BaseRequest<Session>
@@ -116,9 +121,10 @@ private static class DefaultArtifactResolverRequest extends BaseRequest<Session>
DefaultArtifactResolverRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
@Nonnull Collection<? extends ArtifactCoordinates> coordinates,
@Nonnull List<RemoteRepository> repositories) {
- super(session);
+ super(session, trace);
this.coordinates = List.copyOf(requireNonNull(coordinates, "coordinates cannot be null"));
this.repositories = repositories;
}
@@ -134,6 +140,13 @@ public Collection<? extends ArtifactCoordinates> getCoordinates() {
public List<RemoteRepository> getRepositories() {
return repositories;
}
+
+ @Override
+ public String toString() {
+ return "ArtifactResolverRequest[" + "coordinates="
+ + coordinates + ", repositories="
+ + repositories + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java
index 74d6cacb5f..f00f7b2337 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java
@@ -33,7 +33,7 @@
* @since 4.0.0
*/
@Experimental
-public interface ArtifactResolverResult {
+public interface ArtifactResolverResult extends Result<ArtifactResolverRequest> {
/**
* @return {@link Artifact}
*/
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java
index 43bbf6e0b3..6bf2c31b22 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java
@@ -30,16 +30,26 @@
* @since 4.0.0
*/
@Experimental
-abstract class BaseRequest<S extends ProtoSession> {
+abstract class BaseRequest<S extends ProtoSession> implements Request<S> {
private final S session;
+ private final RequestTrace trace;
protected BaseRequest(@Nonnull S session) {
+ this(session, null);
+ }
+
+ protected BaseRequest(@Nonnull S session, RequestTrace trace) {
this.session = requireNonNull(session, "session cannot be null");
+ this.trace = trace;
}
@Nonnull
public S getSession() {
return session;
}
+
+ public RequestTrace getTrace() {
+ return trace;
+ }
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinatesFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinatesFactoryRequest.java
index 7618aaa992..5bcf124711 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinatesFactoryRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinatesFactoryRequest.java
@@ -30,6 +30,7 @@
import org.apache.maven.api.annotations.Immutable;
import org.apache.maven.api.annotations.Nonnull;
import org.apache.maven.api.annotations.NotThreadSafe;
+import org.apache.maven.api.annotations.Nullable;
import static java.util.Objects.requireNonNull;
@@ -105,6 +106,7 @@ static DependencyCoordinatesFactoryRequestBuilder builder() {
@NotThreadSafe
class DependencyCoordinatesFactoryRequestBuilder {
private Session session;
+ private RequestTrace trace;
private String groupId;
private String artifactId;
private String version;
@@ -123,6 +125,11 @@ public DependencyCoordinatesFactoryRequestBuilder session(Session session) {
return this;
}
+ public DependencyCoordinatesFactoryRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public DependencyCoordinatesFactoryRequestBuilder groupId(String groupId) {
this.groupId = groupId;
return this;
@@ -191,6 +198,7 @@ public DependencyCoordinatesFactoryRequestBuilder exclusion(Exclusion exclusion)
public DependencyCoordinatesFactoryRequest build() {
return new DefaultDependencyCoordinatesFactoryRequest(
session,
+ trace,
groupId,
artifactId,
version,
@@ -219,6 +227,7 @@ private static class DefaultDependencyCoordinatesFactoryRequest extends BaseRequ
@SuppressWarnings("checkstyle:ParameterNumber")
private DefaultDependencyCoordinatesFactoryRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
String groupId,
String artifactId,
String version,
@@ -229,7 +238,7 @@ private DefaultDependencyCoordinatesFactoryRequest(
String scope,
boolean optional,
Collection<Exclusion> exclusions) {
- super(session);
+ super(session, trace);
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
@@ -291,6 +300,21 @@ public boolean isOptional() {
public Collection<Exclusion> getExclusions() {
return exclusions;
}
+
+ @Override
+ public String toString() {
+ return "DependencyCoordinatesFactoryRequest[" + "groupId='"
+ + groupId + '\'' + ", artifactId='"
+ + artifactId + '\'' + ", version='"
+ + version + '\'' + ", classifier='"
+ + classifier + '\'' + ", extension='"
+ + extension + '\'' + ", type='"
+ + type + '\'' + ", coordinateString='"
+ + coordinateString + '\'' + ", scope='"
+ + scope + '\'' + ", optional="
+ + optional + ", exclusions="
+ + exclusions + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
index 1a8d3529f1..532a9b6551 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
@@ -52,7 +52,7 @@
*/
@Experimental
@Immutable
-public interface DependencyResolverRequest {
+public interface DependencyResolverRequest extends Request<Session> {
enum RequestType {
COLLECT,
@@ -60,9 +60,6 @@ enum RequestType {
RESOLVE
}
- @Nonnull
- Session getSession();
-
@Nonnull
RequestType getRequestType();
@@ -173,6 +170,7 @@ static DependencyResolverRequest build(
class DependencyResolverRequestBuilder {
Session session;
+ RequestTrace trace;
RequestType requestType;
Project project;
Artifact rootArtifact;
@@ -192,6 +190,12 @@ public DependencyResolverRequestBuilder session(@Nonnull Session session) {
return this;
}
+ @Nonnull
+ public DependencyResolverRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
@Nonnull
public DependencyResolverRequestBuilder requestType(@Nonnull RequestType requestType) {
this.requestType = requestType;
@@ -350,6 +354,7 @@ public DependencyResolverRequestBuilder repositories(@Nonnull List<RemoteReposit
public DependencyResolverRequest build() {
return new DefaultDependencyResolverRequest(
session,
+ trace,
requestType,
project,
rootArtifact,
@@ -364,6 +369,31 @@ public DependencyResolverRequest build() {
static class DefaultDependencyResolverRequest extends BaseRequest<Session>
implements DependencyResolverRequest {
+
+ static final class AlwaysTrueFilter implements Predicate<PathType> {
+ @Override
+ public boolean test(PathType pathType) {
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof AlwaysTrueFilter;
+ }
+
+ @Override
+ public int hashCode() {
+ return AlwaysTrueFilter.class.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "AlwaysTrueFilter[]";
+ }
+ }
+
+ private static final Predicate<PathType> DEFAULT_FILTER = new AlwaysTrueFilter();
+
private final RequestType requestType;
private final Project project;
private final Artifact rootArtifact;
@@ -385,6 +415,7 @@ static class DefaultDependencyResolverRequest extends BaseRequest<Session>
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultDependencyResolverRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
@Nonnull RequestType requestType,
@Nullable Project project,
@Nullable Artifact rootArtifact,
@@ -395,7 +426,7 @@ static class DefaultDependencyResolverRequest extends BaseRequest<Session>
@Nullable PathScope pathScope,
@Nullable Predicate<PathType> pathTypeFilter,
@Nullable List<RemoteRepository> repositories) {
- super(session);
+ super(session, trace);
this.requestType = requireNonNull(requestType, "requestType cannot be null");
this.project = project;
this.rootArtifact = rootArtifact;
@@ -405,7 +436,7 @@ static class DefaultDependencyResolverRequest extends BaseRequest<Session>
List.copyOf(requireNonNull(managedDependencies, "managedDependencies cannot be null"));
this.verbose = verbose;
this.pathScope = requireNonNull(pathScope, "pathScope cannot be null");
- this.pathTypeFilter = (pathTypeFilter != null) ? pathTypeFilter : (t) -> true;
+ this.pathTypeFilter = (pathTypeFilter != null) ? pathTypeFilter : DEFAULT_FILTER;
this.repositories = repositories;
if (verbose && requestType != RequestType.COLLECT) {
throw new IllegalArgumentException("verbose cannot only be true when collecting dependencies");
@@ -468,10 +499,19 @@ public List<RemoteRepository> getRepositories() {
return repositories;
}
- @Nonnull
@Override
public String toString() {
- return getRoot() + " -> " + getDependencies();
+ return "DependencyResolverRequest[" + "requestType="
+ + requestType + ", project="
+ + project + ", rootArtifact="
+ + rootArtifact + ", root="
+ + root + ", dependencies="
+ + dependencies + ", managedDependencies="
+ + managedDependencies + ", verbose="
+ + verbose + ", pathScope="
+ + pathScope + ", pathTypeFilter="
+ + pathTypeFilter + ", repositories="
+ + repositories + ']';
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java
index 7b7f920469..af53d280e2 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java
@@ -41,7 +41,7 @@
* @see DependencyResolver#resolve(DependencyResolverRequest)
*/
@Experimental
-public interface DependencyResolverResult {
+public interface DependencyResolverResult extends Result<DependencyResolverRequest> {
/**
* Gets the exceptions that occurred while building the dependency graph.
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java
index 0b80828bc9..99d384fc93 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderRequest.java
@@ -42,7 +42,7 @@
*/
@Experimental
@Immutable
-public interface ModelBuilderRequest {
+public interface ModelBuilderRequest extends Request<Session> {
/**
* The possible request types for building a model.
@@ -87,9 +87,6 @@ enum RepositoryMerging {
REQUEST_DOMINANT,
}
- @Nonnull
- Session getSession();
-
@Nonnull
ModelSource getSource();
@@ -177,6 +174,7 @@ static ModelBuilderRequestBuilder builder(ModelBuilderRequest request) {
@NotThreadSafe
class ModelBuilderRequestBuilder {
Session session;
+ RequestTrace trace;
RequestType requestType;
boolean locationTracking;
boolean recursive;
@@ -194,6 +192,7 @@ class ModelBuilderRequestBuilder {
ModelBuilderRequestBuilder(ModelBuilderRequest request) {
this.session = request.getSession();
+ this.trace = request.getTrace();
this.requestType = request.getRequestType();
this.locationTracking = request.isLocationTracking();
this.recursive = request.isRecursive();
@@ -213,6 +212,11 @@ public ModelBuilderRequestBuilder session(Session session) {
return this;
}
+ public ModelBuilderRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public ModelBuilderRequestBuilder requestType(RequestType requestType) {
this.requestType = requestType;
return this;
@@ -276,6 +280,7 @@ public ModelBuilderRequestBuilder lifecycleBindingsInjector(ModelTransformer lif
public ModelBuilderRequest build() {
return new DefaultModelBuilderRequest(
session,
+ trace,
requestType,
locationTracking,
recursive,
@@ -307,6 +312,7 @@ private static class DefaultModelBuilderRequest extends BaseRequest<Session> imp
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultModelBuilderRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
@Nonnull RequestType requestType,
boolean locationTracking,
boolean recursive,
@@ -319,7 +325,7 @@ private static class DefaultModelBuilderRequest extends BaseRequest<Session> imp
RepositoryMerging repositoryMerging,
List<RemoteRepository> repositories,
ModelTransformer lifecycleBindingsInjector) {
- super(session);
+ super(session, trace);
this.requestType = requireNonNull(requestType, "requestType cannot be null");
this.locationTracking = locationTracking;
this.recursive = recursive;
@@ -395,6 +401,23 @@ public List<RemoteRepository> getRepositories() {
public ModelTransformer getLifecycleBindingsInjector() {
return lifecycleBindingsInjector;
}
+
+ @Override
+ public String toString() {
+ return "ModelBuilderRequest[" + "requestType="
+ + requestType + ", locationTracking="
+ + locationTracking + ", recursive="
+ + recursive + ", source="
+ + source + ", profiles="
+ + profiles + ", activeProfileIds="
+ + activeProfileIds + ", inactiveProfileIds="
+ + inactiveProfileIds + ", systemProperties="
+ + systemProperties + ", userProperties="
+ + userProperties + ", repositoryMerging="
+ + repositoryMerging + ", repositories="
+ + repositories + ", lifecycleBindingsInjector="
+ + lifecycleBindingsInjector + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderResult.java
index df38a5a62d..e4bec3a4d5 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ModelBuilderResult.java
@@ -31,7 +31,7 @@
* @since 4.0.0
*/
@Experimental
-public interface ModelBuilderResult {
+public interface ModelBuilderResult extends Result<ModelBuilderRequest> {
/**
* Gets the source from which the model was read.
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java
index feedd5103b..e0e9eee5b5 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java
@@ -42,10 +42,7 @@
*/
@Experimental
@Immutable
-public interface ProjectBuilderRequest {
-
- @Nonnull
- Session getSession();
+public interface ProjectBuilderRequest extends Request<Session> {
@Nonnull
Optional<Path> getPath();
@@ -86,6 +83,7 @@ static ProjectBuilderRequestBuilder builder() {
@NotThreadSafe
class ProjectBuilderRequestBuilder {
Session session;
+ RequestTrace trace;
Path path;
Source source;
boolean allowStubModel;
@@ -100,6 +98,11 @@ public ProjectBuilderRequestBuilder session(Session session) {
return this;
}
+ public ProjectBuilderRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public ProjectBuilderRequestBuilder path(Path path) {
this.path = path;
return this;
@@ -122,7 +125,7 @@ public ProjectBuilderRequestBuilder repositories(List<RemoteRepository> reposito
public ProjectBuilderRequest build() {
return new DefaultProjectBuilderRequest(
- session, path, source, allowStubModel, recursive, processPlugins, repositories);
+ session, trace, path, source, allowStubModel, recursive, processPlugins, repositories);
}
private static class DefaultProjectBuilderRequest extends BaseRequest<Session>
@@ -137,13 +140,14 @@ private static class DefaultProjectBuilderRequest extends BaseRequest<Session>
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultProjectBuilderRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
@Nullable Path path,
@Nullable Source source,
boolean allowStubModel,
boolean recursive,
boolean processPlugins,
@Nullable List<RemoteRepository> repositories) {
- super(session);
+ super(session, trace);
this.path = path;
this.source = source;
this.allowStubModel = allowStubModel;
@@ -183,6 +187,17 @@ public boolean isProcessPlugins() {
public List<RemoteRepository> getRepositories() {
return repositories;
}
+
+ @Override
+ public String toString() {
+ return "ProjectBuilderRequest[" + "path="
+ + path + ", source="
+ + source + ", allowStubModel="
+ + allowStubModel + ", recursive="
+ + recursive + ", processPlugins="
+ + processPlugins + ", repositories="
+ + repositories + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java
index 2247aa7b2e..1cc43440e9 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java
@@ -32,7 +32,7 @@
* @since 4.0.0
*/
@Experimental
-public interface ProjectBuilderResult {
+public interface ProjectBuilderResult extends Result<ProjectBuilderRequest> {
/**
* Gets the identifier of the project that could not be built. The general format of the identifier is {@code
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Request.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Request.java
new file mode 100644
index 0000000000..28eecc94d8
--- /dev/null
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Request.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.api.services;
+
+import org.apache.maven.api.ProtoSession;
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Immutable;
+import org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.annotations.Nullable;
+
+/**
+ * Base interface for service requests in Maven. This interface defines the common contract
+ * for all request types within the Maven service layer, providing access to session context
+ * and request tracing capabilities.
+ *
+ * <p>Each request is associated with a {@link ProtoSession} that contains the configuration
+ * and context necessary for request processing, including:
+ * <ul>
+ * <li>User and system properties for interpolation</li>
+ * <li>Session start time information</li>
+ * <li>Project directory structures</li>
+ * </ul>
+ *
+ * <p>Requests can optionally carry trace information through {@link RequestTrace} to support:
+ * <ul>
+ * <li>Debugging and troubleshooting of request flows</li>
+ * <li>Audit logging of operations</li>
+ * <li>Performance monitoring of nested operations</li>
+ * </ul>
+ *
+ * <p>This interface is designed to be extended by specific request types that handle
+ * different Maven operations. All implementations must be immutable to ensure thread safety
+ * and predictable behavior in concurrent environments.
+ *
+ * @param <S> the type of ProtoSession associated with this request, allowing for
+ * type-safe session handling in specific request implementations
+ *
+ * @see ProtoSession
+ * @see RequestTrace
+ * @see Result
+ * @since 4.0.0
+ */
+@Experimental
+@Immutable
+public interface Request<S extends ProtoSession> {
+
+ /**
+ * Returns the session associated with this request.
+ *
+ * @return the session instance, never {@code null}
+ */
+ @Nonnull
+ S getSession();
+
+ /**
+ * Returns the trace information associated with this request, if any.
+ * The trace provides context about the request's position in the operation
+ * hierarchy and can carry additional diagnostic information.
+ *
+ * @return the request trace, or {@code null} if no trace information is available
+ */
+ @Nullable
+ RequestTrace getTrace();
+
+ /**
+ * Returns a string representation of this request, used for debugging and logging purposes.
+ * The format should include the request type and any significant attributes that define the
+ * request's state.
+ *
+ * @return a string representation of this request, never {@code null}
+ */
+ @Override
+ @Nonnull
+ String toString();
+}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RequestTrace.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RequestTrace.java
new file mode 100644
index 0000000000..6dafc3aeaf
--- /dev/null
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RequestTrace.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.api.services;
+
+import org.apache.maven.api.annotations.Nullable;
+
+/**
+ * Represents a hierarchical trace of nested requests within a session, enabling correlation between
+ * session events and their originating operations in the application code. The trace structure
+ * supports the following key features:
+ *
+ * <ul>
+ * <li>Maintains parent-child relationships between requests to track operation nesting</li>
+ * <li>Carries contextual data describing the current request or operation</li>
+ * <li>Supports both internal session operations and client-provided trace information</li>
+ * </ul>
+ *
+ * <p>For internal session operations, the trace typically contains {@code *Request} objects
+ * that represent the current processing state. Client code can also create traces with
+ * application-specific data to provide context when invoking session methods.</p>
+ *
+ * <p>This trace information is particularly useful for:</p>
+ * <ul>
+ * <li>Debugging and troubleshooting request flows</li>
+ * <li>Audit logging of session operations</li>
+ * <li>Performance monitoring of nested operations</li>
+ * </ul>
+ *
+ * @param context The context identifier for this request trace, helping to identify the scope or purpose
+ * of the request. May be null if no specific context is needed.
+ * @param parent The parent request trace that led to this request, establishing the chain of nested
+ * operations. May be null for top-level requests.
+ * @param data Additional data associated with this request trace, typically containing the actual request
+ * object being processed or any application-specific state information. May be null if no
+ * additional data is needed.
+ */
+public record RequestTrace(@Nullable String context, @Nullable RequestTrace parent, @Nullable Object data) {
+
+ public static final String CONTEXT_PLUGIN = "plugin";
+ public static final String CONTEXT_PROJECT = "project";
+ public static final String CONTEXT_BOOTSTRAP = "bootstrap";
+
+ public RequestTrace(RequestTrace parent, Object data) {
+ this(parent != null ? parent.context() : null, parent, data);
+ }
+}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Result.java
similarity index 53%
copy from api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java
copy to api/maven-api-core/src/main/java/org/apache/maven/api/services/Result.java
index c05e244767..65bdf97a91 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Result.java
@@ -19,31 +19,35 @@
package org.apache.maven.api.services;
import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Immutable;
import org.apache.maven.api.annotations.Nonnull;
-import org.apache.maven.api.settings.Settings;
/**
+ * Base interface for service operation results in Maven. This interface defines the common contract
+ * for operation results, providing access to the original request that generated this result.
*
+ * <p>Each result is linked to its originating {@link Request}, allowing for:
+ * <ul>
+ * <li>Traceability between requests and their outcomes</li>
+ * <li>Access to the session context used during processing</li>
+ * <li>Correlation of results with their initiating parameters</li>
+ * </ul>
+ *
+ * @param <REQ> the type of Request that produced this result, ensuring type-safe
+ * access to the original request parameters
+ *
+ * @see Request
* @since 4.0.0
*/
@Experimental
-public interface SettingsBuilderResult {
-
- /**
- * Gets the assembled settings.
- *
- * @return the assembled settings, never {@code null}
- */
- @Nonnull
- Settings getEffectiveSettings();
+@Immutable
+public interface Result<REQ extends Request<?>> {
/**
- * Gets the problems that were encountered during the settings building. Note that only problems of severity
- * {@link BuilderProblem.Severity#WARNING} and below are reported here. Problems with a higher severity level cause
- * the settings builder to fail with a {@link SettingsBuilderException}.
+ * Returns the request that produced this result.
*
- * @return the problems that were encountered during the settings building, can be empty but never {@code null}
+ * @return the originating request instance, never {@code null}
*/
@Nonnull
- ProblemCollector<BuilderProblem> getProblems();
+ REQ getRequest();
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java
index 311f922362..57fe9cace4 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderRequest.java
@@ -37,10 +37,7 @@
*/
@Experimental
@Immutable
-public interface SettingsBuilderRequest {
-
- @Nonnull
- ProtoSession getSession();
+public interface SettingsBuilderRequest extends Request<ProtoSession> {
/**
* Gets the installation settings source.
@@ -133,6 +130,7 @@ static SettingsBuilderRequestBuilder builder() {
@NotThreadSafe
class SettingsBuilderRequestBuilder {
ProtoSession session;
+ RequestTrace trace;
Source installationSettingsSource;
Source projectSettingsSource;
Source userSettingsSource;
@@ -143,6 +141,11 @@ public SettingsBuilderRequestBuilder session(ProtoSession session) {
return this;
}
+ public SettingsBuilderRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public SettingsBuilderRequestBuilder installationSettingsSource(Source installationSettingsSource) {
this.installationSettingsSource = installationSettingsSource;
return this;
@@ -166,6 +169,7 @@ public SettingsBuilderRequestBuilder interpolationSource(UnaryOperator<String> i
public SettingsBuilderRequest build() {
return new DefaultSettingsBuilderRequest(
session,
+ trace,
installationSettingsSource,
projectSettingsSource,
userSettingsSource,
@@ -182,11 +186,12 @@ private static class DefaultSettingsBuilderRequest extends BaseRequest<ProtoSess
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultSettingsBuilderRequest(
@Nonnull ProtoSession session,
+ @Nullable RequestTrace trace,
@Nullable Source installationSettingsSource,
@Nullable Source projectSettingsSource,
@Nullable Source userSettingsSource,
@Nullable UnaryOperator<String> interpolationSource) {
- super(session);
+ super(session, trace);
this.installationSettingsSource = installationSettingsSource;
this.projectSettingsSource = projectSettingsSource;
this.userSettingsSource = userSettingsSource;
@@ -216,6 +221,15 @@ public Optional<Source> getUserSettingsSource() {
public Optional<UnaryOperator<String>> getInterpolationSource() {
return Optional.ofNullable(interpolationSource);
}
+
+ @Override
+ public String toString() {
+ return "SettingsBuilderRequest[" + "installationSettingsSource="
+ + installationSettingsSource + ", projectSettingsSource="
+ + projectSettingsSource + ", userSettingsSource="
+ + userSettingsSource + ", interpolationSource="
+ + interpolationSource + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java
index c05e244767..37b6213da2 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/SettingsBuilderResult.java
@@ -27,7 +27,7 @@
* @since 4.0.0
*/
@Experimental
-public interface SettingsBuilderResult {
+public interface SettingsBuilderResult extends Result<SettingsBuilderRequest> {
/**
* Gets the assembled settings.
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java
index ea7c5ab912..9eca5b1310 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderRequest.java
@@ -35,9 +35,7 @@
* @since 4.0.0
*/
@Experimental
-public interface ToolchainsBuilderRequest {
- @Nonnull
- ProtoSession getSession();
+public interface ToolchainsBuilderRequest extends Request<ProtoSession> {
/**
* Gets the installation Toolchains source.
@@ -93,6 +91,7 @@ static ToolchainsBuilderRequestBuilder builder() {
@NotThreadSafe
class ToolchainsBuilderRequestBuilder {
ProtoSession session;
+ RequestTrace trace;
Source installationToolchainsSource;
Source userToolchainsSource;
@@ -101,6 +100,11 @@ public ToolchainsBuilderRequestBuilder session(ProtoSession session) {
return this;
}
+ public ToolchainsBuilderRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public ToolchainsBuilderRequestBuilder installationToolchainsSource(Source installationToolchainsSource) {
this.installationToolchainsSource = installationToolchainsSource;
return this;
@@ -113,7 +117,7 @@ public ToolchainsBuilderRequestBuilder userToolchainsSource(Source userToolchain
public ToolchainsBuilderRequest build() {
return new ToolchainsBuilderRequestBuilder.DefaultToolchainsBuilderRequest(
- session, installationToolchainsSource, userToolchainsSource);
+ session, trace, installationToolchainsSource, userToolchainsSource);
}
private static class DefaultToolchainsBuilderRequest extends BaseRequest<ProtoSession>
@@ -124,9 +128,10 @@ private static class DefaultToolchainsBuilderRequest extends BaseRequest<ProtoSe
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultToolchainsBuilderRequest(
@Nonnull ProtoSession session,
+ @Nullable RequestTrace trace,
@Nullable Source installationToolchainsSource,
@Nullable Source userToolchainsSource) {
- super(session);
+ super(session, trace);
this.installationToolchainsSource = installationToolchainsSource;
this.userToolchainsSource = userToolchainsSource;
}
@@ -142,6 +147,13 @@ public Optional<Source> getInstallationToolchainsSource() {
public Optional<Source> getUserToolchainsSource() {
return Optional.ofNullable(userToolchainsSource);
}
+
+ @Override
+ public String toString() {
+ return "ToolchainsBuilderRequest[" + "installationToolchainsSource="
+ + installationToolchainsSource + ", userToolchainsSource="
+ + userToolchainsSource + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java
index d48d45bd79..3cf06a7397 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainsBuilderResult.java
@@ -27,7 +27,7 @@
* @since 4.0.0
*/
@Experimental
-public interface ToolchainsBuilderResult {
+public interface ToolchainsBuilderResult extends Result<ToolchainsBuilderRequest> {
/**
* Gets the assembled toolchains.
*
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java
index d563091dbe..3ab8a89b1e 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverRequest.java
@@ -35,10 +35,7 @@
* @since 4.0.0
*/
@Experimental
-public interface VersionRangeResolverRequest {
-
- @Nonnull
- Session getSession();
+public interface VersionRangeResolverRequest extends Request<Session> {
@Nonnull
ArtifactCoordinates getArtifactCoordinates();
@@ -72,6 +69,7 @@ static VersionResolverRequestBuilder builder() {
@NotThreadSafe
class VersionResolverRequestBuilder {
Session session;
+ RequestTrace trace;
ArtifactCoordinates artifactCoordinates;
List<RemoteRepository> repositories;
@@ -80,6 +78,11 @@ public VersionResolverRequestBuilder session(Session session) {
return this;
}
+ public VersionResolverRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public VersionResolverRequestBuilder artifactCoordinates(ArtifactCoordinates artifactCoordinates) {
this.artifactCoordinates = artifactCoordinates;
return this;
@@ -91,7 +94,7 @@ public VersionResolverRequestBuilder repositories(List<RemoteRepository> reposit
}
public VersionRangeResolverRequest build() {
- return new DefaultVersionResolverRequest(session, artifactCoordinates, repositories);
+ return new DefaultVersionResolverRequest(session, trace, artifactCoordinates, repositories);
}
private static class DefaultVersionResolverRequest extends BaseRequest<Session>
@@ -102,9 +105,10 @@ private static class DefaultVersionResolverRequest extends BaseRequest<Session>
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultVersionResolverRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
@Nonnull ArtifactCoordinates artifactCoordinates,
@Nullable List<RemoteRepository> repositories) {
- super(session);
+ super(session, trace);
this.artifactCoordinates = artifactCoordinates;
this.repositories = repositories;
}
@@ -120,6 +124,13 @@ public ArtifactCoordinates getArtifactCoordinates() {
public List<RemoteRepository> getRepositories() {
return repositories;
}
+
+ @Override
+ public String toString() {
+ return "VersionResolverRequest[" + "artifactCoordinates="
+ + artifactCoordinates + ", repositories="
+ + repositories + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverResult.java
index e0a5f83485..798190c0a0 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionRangeResolverResult.java
@@ -36,7 +36,7 @@
* @since 4.0.0
*/
@Experimental
-public interface VersionRangeResolverResult {
+public interface VersionRangeResolverResult extends Result<VersionRangeResolverRequest> {
/**
* Gets the exceptions that occurred while resolving the version range.
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java
index 71a9a558eb..f2751d0c0c 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverRequest.java
@@ -35,10 +35,7 @@
* @since 4.0.0
*/
@Experimental
-public interface VersionResolverRequest {
-
- @Nonnull
- Session getSession();
+public interface VersionResolverRequest extends Request<Session> {
@Nonnull
ArtifactCoordinates getArtifactCoordinates();
@@ -74,6 +71,7 @@ static VersionResolverRequestBuilder builder() {
@NotThreadSafe
class VersionResolverRequestBuilder {
Session session;
+ RequestTrace trace;
ArtifactCoordinates artifactCoordinates;
List<RemoteRepository> repositories;
@@ -82,6 +80,11 @@ public VersionResolverRequestBuilder session(Session session) {
return this;
}
+ public VersionResolverRequestBuilder trace(RequestTrace trace) {
+ this.trace = trace;
+ return this;
+ }
+
public VersionResolverRequestBuilder artifactCoordinates(ArtifactCoordinates artifactCoordinates) {
this.artifactCoordinates = artifactCoordinates;
return this;
@@ -93,7 +96,7 @@ public VersionResolverRequestBuilder repositories(List<RemoteRepository> reposit
}
public VersionResolverRequest build() {
- return new DefaultVersionResolverRequest(session, artifactCoordinates, repositories);
+ return new DefaultVersionResolverRequest(session, trace, artifactCoordinates, repositories);
}
private static class DefaultVersionResolverRequest extends BaseRequest<Session>
@@ -104,9 +107,10 @@ private static class DefaultVersionResolverRequest extends BaseRequest<Session>
@SuppressWarnings("checkstyle:ParameterNumber")
DefaultVersionResolverRequest(
@Nonnull Session session,
+ @Nullable RequestTrace trace,
@Nonnull ArtifactCoordinates artifactCoordinates,
@Nullable List<RemoteRepository> repositories) {
- super(session);
+ super(session, trace);
this.artifactCoordinates = artifactCoordinates;
this.repositories = repositories;
}
@@ -122,6 +126,13 @@ public ArtifactCoordinates getArtifactCoordinates() {
public List<RemoteRepository> getRepositories() {
return repositories;
}
+
+ @Override
+ public String toString() {
+ return "VersionResolverRequest[" + "artifactCoordinates="
+ + artifactCoordinates + ", repositories="
+ + repositories + ']';
+ }
}
}
}
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverResult.java
index 2897183e8c..5b9e61b40d 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverResult.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionResolverResult.java
@@ -31,7 +31,7 @@
* @since 4.0.0
*/
@Experimental
-public interface VersionResolverResult {
+public interface VersionResolverResult extends Result<VersionResolverRequest> {
@Nonnull
List<Exception> getExceptions();
diff --git a/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestImplementationTest.java b/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestImplementationTest.java
new file mode 100644
index 0000000000..61dc77c2e9
--- /dev/null
+++ b/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestImplementationTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.api.services;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.maven.api.ArtifactCoordinates;
+import org.apache.maven.api.RemoteRepository;
+import org.apache.maven.api.Session;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.mock;
+
+class RequestImplementationTest {
+
+ @Test
+ void testArtifactResolverRequestEquality() {
+ Session session = mock(Session.class);
+ ArtifactCoordinates coords1 = mock(ArtifactCoordinates.class);
+ ArtifactCoordinates coords2 = mock(ArtifactCoordinates.class);
+ RemoteRepository repo1 = mock(RemoteRepository.class);
+ RemoteRepository repo2 = mock(RemoteRepository.class);
+
+ List<RemoteRepository> repositories1 = Arrays.asList(repo1, repo2);
+ List<RemoteRepository> repositories2 = Arrays.asList(repo1, repo2);
+
+ ArtifactResolverRequest.ArtifactResolverRequestBuilder builder = ArtifactResolverRequest.builder();
+
+ ArtifactResolverRequest request1 = builder.session(session)
+ .coordinates(Arrays.asList(coords1, coords2))
+ .repositories(repositories1)
+ .build();
+
+ ArtifactResolverRequest request2 = builder.session(session)
+ .coordinates(Arrays.asList(coords1, coords2))
+ .repositories(repositories2)
+ .build();
+
+ ArtifactResolverRequest request3 = builder.session(session)
+ .coordinates(Arrays.asList(coords2, coords1)) // Different order
+ .repositories(repositories1)
+ .build();
+
+ // Test toString
+ String toString = request1.toString();
+ assertTrue(toString.contains("coordinates="));
+ assertTrue(toString.contains("repositories="));
+ }
+
+ @Test
+ void testRequestTraceIntegration() {
+ Session session = mock(Session.class);
+ RequestTrace trace = new RequestTrace("test-context", null, "test-data");
+
+ ArtifactInstallerRequest request =
+ ArtifactInstallerRequest.builder().session(session).trace(trace).build();
+
+ assertEquals(trace, request.getTrace());
+ assertEquals(session, request.getSession());
+ }
+}
diff --git a/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestTraceTest.java b/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestTraceTest.java
new file mode 100644
index 0000000000..4172a15d57
--- /dev/null
+++ b/api/maven-api-core/src/test/java/org/apache/maven/api/services/RequestTraceTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.api.services;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class RequestTraceTest {
+
+ @Test
+ void testRequestTraceCreation() {
+ RequestTrace parentTrace = new RequestTrace("parent-context", null, "parent-data");
+ RequestTrace childTrace = new RequestTrace("child-context", parentTrace, "child-data");
+
+ assertEquals("parent-context", parentTrace.context());
+ assertNull(parentTrace.parent());
+ assertEquals("parent-data", parentTrace.data());
+
+ assertEquals("child-context", childTrace.context());
+ assertSame(parentTrace, childTrace.parent());
+ assertEquals("child-data", childTrace.data());
+ }
+
+ @Test
+ void testRequestTraceWithParentContextInheritance() {
+ RequestTrace parentTrace = new RequestTrace("parent-context", null, "parent-data");
+ RequestTrace childTrace = new RequestTrace(parentTrace, "child-data");
+
+ assertEquals("parent-context", parentTrace.context());
+ assertEquals("parent-context", childTrace.context());
+ assertEquals("child-data", childTrace.data());
+ }
+
+ @Test
+ void testPredefinedContexts() {
+ assertEquals("plugin", RequestTrace.CONTEXT_PLUGIN);
+ assertEquals("project", RequestTrace.CONTEXT_PROJECT);
+ assertEquals("bootstrap", RequestTrace.CONTEXT_BOOTSTRAP);
+ }
+
+ @Test
+ void testNullValues() {
+ RequestTrace trace = new RequestTrace(null, null, null);
+ assertNull(trace.context());
+ assertNull(trace.parent());
+ assertNull(trace.data());
+ }
+
+ @Test
+ void testChainedTraces() {
+ RequestTrace root = new RequestTrace("root", null, "root-data");
+ RequestTrace level1 = new RequestTrace("level1", root, "level1-data");
+ RequestTrace level2 = new RequestTrace("level2", level1, "level2-data");
+ RequestTrace level3 = new RequestTrace(level2, "level3-data");
+
+ // Verify the chain
+ assertNull(root.parent());
+ assertEquals(root, level1.parent());
+ assertEquals(level1, level2.parent());
+ assertEquals(level2, level3.parent());
+
+ // Verify context inheritance
+ assertEquals("root", root.context());
+ assertEquals("level1", level1.context());
+ assertEquals("level2", level2.context());
+ assertEquals("level2", level3.context()); // Inherited from parent
+ }
+}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListener.java b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListener.java
index f1ae7295dc..a7379ae3cb 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListener.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/internal/aether/ReverseTreeRepositoryListener.java
@@ -29,8 +29,8 @@
import java.util.ListIterator;
import java.util.Objects;
-import org.apache.maven.model.InputLocation;
-import org.apache.maven.model.Plugin;
+import org.apache.maven.api.model.InputLocation;
+import org.apache.maven.api.model.Plugin;
import org.eclipse.aether.AbstractRepositoryListener;
import org.eclipse.aether.RepositoryEvent;
import org.eclipse.aether.RepositorySystemSession;
@@ -78,6 +78,8 @@ public void artifactResolved(RepositoryEvent event) {
artifactRequest = artifactRequestData;
} else if (data instanceof Plugin pluginData) {
plugin = pluginData;
+ } else if (data instanceof org.apache.maven.model.Plugin pluginData) {
+ plugin = pluginData.getDelegate();
}
trace = trace.getParent();
}
@@ -152,7 +154,7 @@ public void artifactResolved(RepositoryEvent event) {
}
if (trackingFile == null) {
- return;
+ return; // parent or imported bom ?
}
try {
Files.createDirectories(trackingDir);
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 f77536fc28..06690ec1b5 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
@@ -43,6 +43,7 @@
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.impl.DefaultDependencyResolverResult;
import org.apache.maven.impl.MappedCollection;
+import org.apache.maven.impl.RequestTraceHelper;
import org.apache.maven.model.building.ModelProblem;
import org.apache.maven.model.building.ModelSource2;
import org.apache.maven.project.DefaultProjectBuildingRequest;
@@ -67,6 +68,7 @@ public DefaultProjectBuilder(org.apache.maven.project.ProjectBuilder builder) {
public ProjectBuilderResult build(ProjectBuilderRequest request)
throws ProjectBuilderException, IllegalArgumentException {
InternalMavenSession session = InternalMavenSession.from(request.getSession());
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(request.getSession(), request);
try {
List<ArtifactRepository> repositories = session.toArtifactRepositories(
request.getRepositories() != null ? request.getRepositories() : session.getRemoteRepositories());
@@ -87,6 +89,11 @@ public ProjectBuilderResult build(ProjectBuilderRequest request)
throw new IllegalArgumentException("Invalid request");
}
return new ProjectBuilderResult() {
+ @Override
+ public ProjectBuilderRequest getRequest() {
+ return request;
+ }
+
@Nonnull
@Override
public String getProjectId() {
@@ -175,11 +182,14 @@ public Severity getSeverity() {
public Optional<DependencyResolverResult> getDependencyResolverResult() {
return Optional.ofNullable(res.getDependencyResolutionResult())
.map(r -> new DefaultDependencyResolverResult(
- null, r.getCollectionErrors(), session.getNode(r.getDependencyGraph()), 0));
+ // TODO: this should not be null
+ null, null, r.getCollectionErrors(), session.getNode(r.getDependencyGraph()), 0));
}
};
} catch (ProjectBuildingException e) {
throw new ProjectBuilderException("Unable to build project", e);
+ } finally {
+ RequestTraceHelper.exit(trace);
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
index e40586fba5..16aee3db31 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
@@ -30,6 +30,8 @@
import org.apache.maven.RepositoryUtils;
import org.apache.maven.api.DependencyScope;
+import org.apache.maven.impl.InternalSession;
+import org.apache.maven.impl.RequestTraceHelper;
import org.apache.maven.impl.resolver.RelocatedArtifact;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
@@ -70,7 +72,7 @@
@Named
@Singleton
public class DefaultPluginDependenciesResolver implements PluginDependenciesResolver {
- private static final String REPOSITORY_CONTEXT = "plugin";
+ private static final String REPOSITORY_CONTEXT = org.apache.maven.api.services.RequestTrace.CONTEXT_PLUGIN;
private final Logger logger = LoggerFactory.getLogger(getClass());
@@ -187,7 +189,8 @@ private DependencyResult resolveInternal(
List<RemoteRepository> repositories,
RepositorySystemSession session)
throws PluginResolutionException {
- RequestTrace trace = RequestTrace.newChild(null, plugin);
+ InternalSession iSession = InternalSession.from(session);
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(iSession, plugin.getDelegate());
if (pluginArtifact == null) {
pluginArtifact = toArtifact(plugin, session);
@@ -217,9 +220,9 @@ private DependencyResult resolveInternal(
}
DependencyRequest depRequest = new DependencyRequest(request, resolutionFilter);
- depRequest.setTrace(trace);
+ depRequest.setTrace(trace.trace());
- request.setTrace(RequestTrace.newChild(trace, depRequest));
+ request.setTrace(RequestTrace.newChild(trace.trace(), depRequest));
node = repoSystem.collectDependencies(pluginSession, request).getRoot();
@@ -239,6 +242,8 @@ private DependencyResult resolveInternal(
.flatMap(r -> r.getExceptions().stream()))
.collect(Collectors.toList());
throw new PluginResolutionException(plugin, exceptions, e);
+ } finally {
+ RequestTraceHelper.exit(trace);
}
}
}
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java
index 8bcea49685..c616533cea 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/prefix/internal/DefaultPluginPrefixResolver.java
@@ -62,7 +62,7 @@
@Named
@Singleton
public class DefaultPluginPrefixResolver implements PluginPrefixResolver {
- private static final String REPOSITORY_CONTEXT = "plugin";
+ private static final String REPOSITORY_CONTEXT = org.apache.maven.api.services.RequestTrace.CONTEXT_PLUGIN;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final BuildPluginManager pluginManager;
diff --git a/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java b/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
index 9082b30887..b2afbb073e 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/plugin/version/internal/DefaultPluginVersionResolver.java
@@ -72,7 +72,7 @@
@Named
@Singleton
public class DefaultPluginVersionResolver implements PluginVersionResolver {
- private static final String REPOSITORY_CONTEXT = "plugin";
+ private static final String REPOSITORY_CONTEXT = org.apache.maven.api.services.RequestTrace.CONTEXT_PLUGIN;
private static final Object CACHE_KEY = new Object();
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 ade3a7dde8..117b81fa45 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
@@ -84,6 +84,7 @@
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.RequestTrace;
import org.apache.maven.api.services.TypeRegistry;
import org.apache.maven.api.services.VersionParser;
import org.apache.maven.api.services.VersionRangeResolver;
@@ -900,4 +901,20 @@ public DependencyScope requireDependencyScope(String id) {
public PathScope requirePathScope(String id) {
return getService(PathScopeRegistry.class).require(id);
}
+
+ @Override
+ public void setCurrentTrace(RequestTrace trace) {
+ getTraceHolder().set(trace);
+ }
+
+ @Override
+ public RequestTrace getCurrentTrace() {
+ return getTraceHolder().get();
+ }
+
+ @SuppressWarnings("unchecked")
+ private ThreadLocal<RequestTrace> getTraceHolder() {
+ org.eclipse.aether.SessionData data = session.getData();
+ return (ThreadLocal<RequestTrace>) data.computeIfAbsent(RequestTrace.class, ThreadLocal::new);
+ }
}
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 a64be28b86..b83d649206 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
@@ -51,6 +51,7 @@ public ArtifactResolverResult resolve(ArtifactResolverRequest request)
throws ArtifactResolverException, IllegalArgumentException {
nonNull(request, "request");
InternalSession session = InternalSession.from(request.getSession());
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request);
try {
Map<DownloadedArtifact, Path> paths = new HashMap<>();
ArtifactManager artifactManager = session.getService(ArtifactManager.class);
@@ -68,7 +69,8 @@ public ArtifactResolverResult resolve(ArtifactResolverRequest request)
DownloadedArtifact resolved = session.getArtifact(DownloadedArtifact.class, aetherArtifact);
paths.put(resolved, path);
} else {
- requests.add(new ArtifactRequest(aetherArtifact, repositories, null));
+ requests.add(
+ new ArtifactRequest(aetherArtifact, repositories, trace.context()).setTrace(trace.trace()));
}
}
if (!requests.isEmpty()) {
@@ -80,19 +82,29 @@ public ArtifactResolverResult resolve(ArtifactResolverRequest request)
paths.put(artifact, path);
}
}
- return new DefaultArtifactResolverResult(paths);
+ return new DefaultArtifactResolverResult(request, paths);
} catch (ArtifactResolutionException e) {
throw new ArtifactResolverException("Unable to resolve artifact: " + e.getMessage(), e);
+ } finally {
+ RequestTraceHelper.exit(trace);
}
}
static class DefaultArtifactResolverResult implements ArtifactResolverResult {
+
+ final ArtifactResolverRequest request;
final Map<DownloadedArtifact, Path> paths;
- DefaultArtifactResolverResult(Map<DownloadedArtifact, Path> paths) {
+ DefaultArtifactResolverResult(ArtifactResolverRequest request, Map<DownloadedArtifact, Path> paths) {
+ this.request = request;
this.paths = paths;
}
+ @Override
+ public ArtifactResolverRequest getRequest() {
+ return request;
+ }
+
@Override
public Collection<DownloadedArtifact> getArtifacts() {
return paths.keySet();
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java
index 4b4fc43e51..984c2c90a9 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolver.java
@@ -75,58 +75,64 @@ public DependencyResolverResult collect(@Nonnull DependencyResolverRequest reque
throws DependencyResolverException, IllegalArgumentException {
nonNull(request, "request");
InternalSession session = InternalSession.from(request.getSession());
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request);
+ try {
+ Artifact rootArtifact;
+ DependencyCoordinates root;
+ Collection<DependencyCoordinates> dependencies;
+ Collection<DependencyCoordinates> managedDependencies;
+ List<RemoteRepository> remoteRepositories;
+ if (request.getProject().isPresent()) {
+ Project project = request.getProject().get();
+ rootArtifact = project.getPomArtifact();
+ root = null;
+ dependencies = project.getDependencies();
+ managedDependencies = project.getManagedDependencies();
+ remoteRepositories = request.getRepositories() != null
+ ? request.getRepositories()
+ : session.getService(ProjectManager.class).getRemoteProjectRepositories(project);
+ } else {
+ rootArtifact = request.getRootArtifact().orElse(null);
+ root = request.getRoot().orElse(null);
+ dependencies = request.getDependencies();
+ managedDependencies = request.getManagedDependencies();
+ remoteRepositories =
+ request.getRepositories() != null ? request.getRepositories() : session.getRemoteRepositories();
+ }
+ ResolutionScope resolutionScope = null;
+ if (request.getPathScope() != null) {
+ resolutionScope = session.getSession()
+ .getScopeManager()
+ .getResolutionScope(request.getPathScope().id())
+ .orElseThrow();
+ }
+ CollectRequest collectRequest = new CollectRequest()
+ .setRootArtifact(rootArtifact != null ? session.toArtifact(rootArtifact) : null)
+ .setRoot(root != null ? session.toDependency(root, false) : null)
+ .setDependencies(session.toDependencies(dependencies, false))
+ .setManagedDependencies(session.toDependencies(managedDependencies, true))
+ .setRepositories(session.toRepositories(remoteRepositories))
+ .setRequestContext(trace.context())
+ .setTrace(trace.trace());
+ collectRequest.setResolutionScope(resolutionScope);
- Artifact rootArtifact;
- DependencyCoordinates root;
- Collection<DependencyCoordinates> dependencies;
- Collection<DependencyCoordinates> managedDependencies;
- List<RemoteRepository> remoteRepositories;
- if (request.getProject().isPresent()) {
- Project project = request.getProject().get();
- rootArtifact = project.getPomArtifact();
- root = null;
- dependencies = project.getDependencies();
- managedDependencies = project.getManagedDependencies();
- remoteRepositories = request.getRepositories() != null
- ? request.getRepositories()
- : session.getService(ProjectManager.class).getRemoteProjectRepositories(project);
- } else {
- rootArtifact = request.getRootArtifact().orElse(null);
- root = request.getRoot().orElse(null);
- dependencies = request.getDependencies();
- managedDependencies = request.getManagedDependencies();
- remoteRepositories =
- request.getRepositories() != null ? request.getRepositories() : session.getRemoteRepositories();
- }
- ResolutionScope resolutionScope = null;
- if (request.getPathScope() != null) {
- resolutionScope = session.getSession()
- .getScopeManager()
- .getResolutionScope(request.getPathScope().id())
- .orElseThrow();
- }
- CollectRequest collectRequest = new CollectRequest()
- .setRootArtifact(rootArtifact != null ? session.toArtifact(rootArtifact) : null)
- .setRoot(root != null ? session.toDependency(root, false) : null)
- .setDependencies(session.toDependencies(dependencies, false))
- .setManagedDependencies(session.toDependencies(managedDependencies, true))
- .setRepositories(session.toRepositories(remoteRepositories));
- collectRequest.setResolutionScope(resolutionScope);
-
- RepositorySystemSession systemSession = session.getSession();
- if (request.getVerbose()) {
- systemSession = new DefaultRepositorySystemSession(systemSession)
- .setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, true)
- .setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, true);
- }
+ RepositorySystemSession systemSession = session.getSession();
+ if (request.getVerbose()) {
+ systemSession = new DefaultRepositorySystemSession(systemSession)
+ .setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, true)
+ .setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, true);
+ }
- try {
- final CollectResult result =
- session.getRepositorySystem().collectDependencies(systemSession, collectRequest);
- return new DefaultDependencyResolverResult(
- null, result.getExceptions(), session.getNode(result.getRoot(), request.getVerbose()), 0);
- } catch (DependencyCollectionException e) {
- throw new DependencyResolverException("Unable to collect dependencies", e);
+ try {
+ final CollectResult result =
+ session.getRepositorySystem().collectDependencies(systemSession, collectRequest);
+ return new DefaultDependencyResolverResult(
+ null, null, result.getExceptions(), session.getNode(result.getRoot(), request.getVerbose()), 0);
+ } catch (DependencyCollectionException e) {
+ throw new DependencyResolverException("Unable to collect dependencies", e);
+ }
+ } finally {
+ RequestTraceHelper.exit(trace);
}
}
@@ -162,54 +168,60 @@ private static DependencyFilter getScopeDependencyFilter(PathScope scope) {
*/
@Override
public DependencyResolverResult resolve(DependencyResolverRequest request)
- throws DependencyResolverException, DependencyResolverException, ArtifactResolverException {
+ throws DependencyResolverException, ArtifactResolverException {
InternalSession session =
InternalSession.from(nonNull(request, "request").getSession());
- DependencyResolverResult result;
- DependencyResolverResult collectorResult = collect(request);
- List<RemoteRepository> repositories = request.getRepositories() != null
- ? request.getRepositories()
- : request.getProject().isPresent()
- ? session.getService(ProjectManager.class)
- .getRemoteProjectRepositories(
- request.getProject().get())
- : session.getRemoteRepositories();
- if (request.getRequestType() == DependencyResolverRequest.RequestType.COLLECT) {
- result = collectorResult;
- } else {
- List<Node> nodes = flatten(session, collectorResult.getRoot(), request.getPathScope());
- List<ArtifactCoordinates> coordinates = nodes.stream()
- .map(Node::getDependency)
- .filter(Objects::nonNull)
- .map(Artifact::toCoordinates)
- .collect(Collectors.toList());
- Predicate<PathType> filter = request.getPathTypeFilter();
- if (request.getRequestType() == DependencyResolverRequest.RequestType.FLATTEN) {
- DefaultDependencyResolverResult flattenResult = new DefaultDependencyResolverResult(
- null, collectorResult.getExceptions(), collectorResult.getRoot(), nodes.size());
- for (Node node : nodes) {
- flattenResult.addNode(node);
- }
- result = flattenResult;
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request);
+ try {
+ DependencyResolverResult result;
+ DependencyResolverResult collectorResult = collect(request);
+ List<RemoteRepository> repositories = request.getRepositories() != null
+ ? request.getRepositories()
+ : request.getProject().isPresent()
+ ? session.getService(ProjectManager.class)
+ .getRemoteProjectRepositories(
+ request.getProject().get())
+ : session.getRemoteRepositories();
+ if (request.getRequestType() == DependencyResolverRequest.RequestType.COLLECT) {
+ result = collectorResult;
} else {
- PathModularizationCache cache = new PathModularizationCache(); // TODO: should be project-wide cache.
- DefaultDependencyResolverResult resolverResult = new DefaultDependencyResolverResult(
- cache, collectorResult.getExceptions(), collectorResult.getRoot(), nodes.size());
- ArtifactResolverResult artifactResolverResult =
- session.getService(ArtifactResolver.class).resolve(session, coordinates, repositories);
- for (Node node : nodes) {
- Dependency d = node.getDependency();
- Path path = (d != null) ? artifactResolverResult.getPath(d) : null;
- try {
- resolverResult.addDependency(node, d, filter, path);
- } catch (IOException e) {
- throw cannotReadModuleInfo(path, e);
+ List<Node> nodes = flatten(session, collectorResult.getRoot(), request.getPathScope());
+ List<ArtifactCoordinates> coordinates = nodes.stream()
+ .map(Node::getDependency)
+ .filter(Objects::nonNull)
+ .map(Artifact::toCoordinates)
+ .collect(Collectors.toList());
+ Predicate<PathType> filter = request.getPathTypeFilter();
+ if (request.getRequestType() == DependencyResolverRequest.RequestType.FLATTEN) {
+ DefaultDependencyResolverResult flattenResult = new DefaultDependencyResolverResult(
+ null, null, collectorResult.getExceptions(), collectorResult.getRoot(), nodes.size());
+ for (Node node : nodes) {
+ flattenResult.addNode(node);
+ }
+ result = flattenResult;
+ } else {
+ PathModularizationCache cache =
+ new PathModularizationCache(); // TODO: should be project-wide cache.
+ DefaultDependencyResolverResult resolverResult = new DefaultDependencyResolverResult(
+ null, cache, collectorResult.getExceptions(), collectorResult.getRoot(), nodes.size());
+ ArtifactResolverResult artifactResolverResult =
+ session.getService(ArtifactResolver.class).resolve(session, coordinates, repositories);
+ for (Node node : nodes) {
+ Dependency d = node.getDependency();
+ Path path = (d != null) ? artifactResolverResult.getPath(d) : null;
+ try {
+ resolverResult.addDependency(node, d, filter, path);
+ } catch (IOException e) {
+ throw cannotReadModuleInfo(path, e);
+ }
}
+ result = resolverResult;
}
- result = resolverResult;
}
+ return result;
+ } finally {
+ RequestTraceHelper.exit(trace);
}
- return result;
}
private static DependencyResolverException cannotReadModuleInfo(final Path path, final IOException cause) {
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java
index 9464ed7f11..fa7ace6e0d 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultDependencyResolverResult.java
@@ -52,6 +52,10 @@
* @see DefaultDependencyResolver#resolve(DependencyResolverRequest)
*/
public class DefaultDependencyResolverResult implements DependencyResolverResult {
+ /**
+ * The corresponding request.
+ */
+ private final DependencyResolverRequest request;
/**
* The exceptions that occurred while building the dependency graph.
*/
@@ -97,13 +101,19 @@ public class DefaultDependencyResolverResult implements DependencyResolverResult
* Creates an initially empty result. Callers should add path elements by calls
* to {@link #addDependency(Node, Dependency, Predicate, Path)}.
*
+ * @param request the corresponding request
* @param cache cache of module information about each dependency
* @param exceptions the exceptions that occurred while building the dependency graph
* @param root the root node of the dependency graph
* @param count estimated number of dependencies
*/
public DefaultDependencyResolverResult(
- PathModularizationCache cache, List<Exception> exceptions, Node root, int count) {
+ DependencyResolverRequest request,
+ PathModularizationCache cache,
+ List<Exception> exceptions,
+ Node root,
+ int count) {
+ this.request = request;
this.cache = cache;
this.exceptions = exceptions;
this.root = root;
@@ -333,6 +343,11 @@ private Path findArtifactPath(String group, String artifact) throws IOException
return null;
}
+ @Override
+ public DependencyResolverRequest getRequest() {
+ return request;
+ }
+
@Override
public List<Exception> getExceptions() {
return exceptions;
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java
index 175eb7bc15..6924bb15ba 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java
@@ -135,7 +135,7 @@ public SettingsBuilderResult build(SettingsBuilderRequest request) throws Settin
throw new SettingsBuilderException("Error building settings", problems);
}
- return new DefaultSettingsBuilderResult(effective, problems);
+ return new DefaultSettingsBuilderResult(request, effective, problems);
}
private Settings readSettings(
@@ -330,15 +330,24 @@ public org.apache.maven.api.model.Profile convert(Profile profile) {
*/
static class DefaultSettingsBuilderResult implements SettingsBuilderResult {
+ private final SettingsBuilderRequest request;
+
private final Settings effectiveSettings;
private final ProblemCollector<BuilderProblem> problems;
- DefaultSettingsBuilderResult(Settings effectiveSettings, ProblemCollector<BuilderProblem> problems) {
+ DefaultSettingsBuilderResult(
+ SettingsBuilderRequest request, Settings effectiveSettings, ProblemCollector<BuilderProblem> problems) {
+ this.request = request;
this.effectiveSettings = effectiveSettings;
this.problems = (problems != null) ? problems : ProblemCollector.empty();
}
+ @Override
+ public SettingsBuilderRequest getRequest() {
+ return request;
+ }
+
@Override
public Settings getEffectiveSettings() {
return effectiveSettings;
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsBuilder.java
index f2ce5abd5f..2d3360fc6e 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsBuilder.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultToolchainsBuilder.java
@@ -78,7 +78,7 @@ public ToolchainsBuilderResult build(ToolchainsBuilderRequest request) throws To
throw new ToolchainsBuilderException("Error building toolchains", problems);
}
- return new DefaultToolchainsBuilderResult(effective, problems);
+ return new DefaultToolchainsBuilderResult(request, effective, problems);
}
private PersistedToolchains readToolchains(
@@ -162,16 +162,26 @@ private PersistedToolchains interpolate(
*/
static class DefaultToolchainsBuilderResult implements ToolchainsBuilderResult {
+ private final ToolchainsBuilderRequest request;
+
private final PersistedToolchains effectiveToolchains;
private final ProblemCollector<BuilderProblem> problems;
DefaultToolchainsBuilderResult(
- PersistedToolchains effectiveToolchains, ProblemCollector<BuilderProblem> problems) {
+ ToolchainsBuilderRequest request,
+ PersistedToolchains effectiveToolchains,
+ ProblemCollector<BuilderProblem> problems) {
+ this.request = request;
this.effectiveToolchains = effectiveToolchains;
this.problems = (problems != null) ? problems : ProblemCollector.empty();
}
+ @Override
+ public ToolchainsBuilderRequest getRequest() {
+ return request;
+ }
+
@Override
public PersistedToolchains getEffectiveToolchains() {
return effectiveToolchains;
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 74c2f75b13..a189d4328a 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
@@ -58,22 +58,29 @@ public VersionRangeResolverResult resolve(VersionRangeResolverRequest request)
requireNonNull(request, "request");
InternalSession session = InternalSession.from(request.getSession());
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request);
try {
VersionRangeResult res = repositorySystem.resolveVersionRange(
session.getSession(),
new VersionRangeRequest(
- session.toArtifact(request.getArtifactCoordinates()),
- session.toRepositories(
- request.getRepositories() != null
- ? request.getRepositories()
- : session.getRemoteRepositories()),
- null));
+ session.toArtifact(request.getArtifactCoordinates()),
+ session.toRepositories(
+ request.getRepositories() != null
+ ? request.getRepositories()
+ : session.getRemoteRepositories()),
+ trace.context())
+ .setTrace(trace.trace()));
Map<String, ArtifactRepository> repos = res.getVersions().stream()
.filter(v -> res.getRepository(v) != null)
.collect(Collectors.toMap(v -> v.toString(), res::getRepository));
return new VersionRangeResolverResult() {
+ @Override
+ public VersionRangeResolverRequest getRequest() {
+ return request;
+ }
+
@Override
public List<Exception> getExceptions() {
return res.getExceptions();
@@ -98,6 +105,8 @@ public Optional<Repository> getRepository(Version version) {
};
} catch (VersionRangeResolutionException e) {
throw new VersionRangeResolverException("Unable to resolve version range", e);
+ } finally {
+ RequestTraceHelper.exit(trace);
}
}
}
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 bc824cd256..a9b4ba4748 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
@@ -53,18 +53,24 @@ public VersionResolverResult resolve(VersionResolverRequest request) throws Vers
nonNull(request, "request");
InternalSession session = InternalSession.from(request.getSession());
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(session, request);
try {
- VersionResult res = repositorySystem.resolveVersion(
- session.getSession(),
- new VersionRequest(
+ VersionRequest req = new VersionRequest(
session.toArtifact(request.getArtifactCoordinates()),
session.toRepositories(
request.getRepositories() != null
? request.getRepositories()
: session.getRemoteRepositories()),
- null));
+ trace.context())
+ .setTrace(trace.trace());
+ VersionResult res = repositorySystem.resolveVersion(session.getSession(), req);
return new VersionResolverResult() {
+ @Override
+ public VersionResolverRequest getRequest() {
+ return request;
+ }
+
@Override
public List<Exception> getExceptions() {
return res.getExceptions();
@@ -89,6 +95,8 @@ public Optional<Repository> getRepository() {
};
} catch (VersionResolutionException e) {
throw new VersionResolverException("Unable to resolve version", e);
+ } finally {
+ RequestTraceHelper.exit(trace);
}
}
}
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 ce01aa50f9..fe8a44715b 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
@@ -30,6 +30,8 @@
import org.apache.maven.api.RemoteRepository;
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.RequestTrace;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
@@ -86,4 +88,26 @@ List<org.eclipse.aether.graph.Dependency> toDependencies(
RepositorySystemSession getSession();
RepositorySystem getRepositorySystem();
+
+ /**
+ * Sets the current request trace for the session.
+ * The request trace provides contextual information about the current operation
+ * being performed and can be used for debugging and monitoring purposes.
+ * The trace is stored in thread-local storage, allowing for concurrent operations
+ * with different traces.
+ *
+ * @param trace the trace to set as current, may be null to clear the trace
+ * @see RequestTraceHelper#enter(Session, Object) For the recommended way to manage traces
+ */
+ void setCurrentTrace(@Nullable RequestTrace trace);
+
+ /**
+ * Gets the current request trace for the session from thread-local storage.
+ * Each thread maintains its own trace context, ensuring thread-safety for
+ * concurrent operations.
+ *
+ * @return the current request trace, or null if no trace is set
+ * @see RequestTraceHelper#enter(Session, Object) For the recommended way to manage traces
+ */
+ RequestTrace getCurrentTrace();
}
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/RequestTraceHelper.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/RequestTraceHelper.java
new file mode 100644
index 0000000000..44b54003f2
--- /dev/null
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/RequestTraceHelper.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.impl;
+
+import java.util.stream.Collectors;
+
+import org.apache.maven.api.Session;
+import org.apache.maven.api.services.Request;
+import org.eclipse.aether.RequestTrace;
+import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.collection.CollectStepData;
+import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
+import org.eclipse.aether.resolution.ArtifactRequest;
+import org.eclipse.aether.resolution.DependencyRequest;
+
+/**
+ * Helper class to manage request tracing for improved error logging in Maven's dependency resolution.
+ * This class provides utilities to:
+ * - Track request traces through Maven's dependency resolution process
+ * - Convert between Maven and Resolver trace formats
+ * - Generate human-readable interpretations of trace data
+ */
+public final class RequestTraceHelper {
+
+ /**
+ * Represents a resolver trace containing both Maven and Resolver-specific trace information
+ * @param session The current Maven session
+ * @param context The trace context
+ * @param trace The Resolver-specific trace
+ * @param mvnTrace The Maven-specific trace
+ */
+ public record ResolverTrace(
+ Session session, String context, RequestTrace trace, org.apache.maven.api.services.RequestTrace mvnTrace) {}
+
+ /**
+ * Creates a new trace entry and updates the session's current trace
+ * @param session The current Maven session
+ * @param data The data object to associate with the trace
+ * @return A new ResolverTrace containing both Maven and Resolver trace information
+ */
+ public static ResolverTrace enter(Session session, Object data) {
+ InternalSession iSession = InternalSession.from(session);
+ org.apache.maven.api.services.RequestTrace trace = data instanceof Request<?> req && req.getTrace() != null
+ ? req.getTrace()
+ : new org.apache.maven.api.services.RequestTrace(iSession.getCurrentTrace(), data);
+ iSession.setCurrentTrace(trace);
+ return new ResolverTrace(session, trace.context(), toResolver(trace), trace);
+ }
+
+ /**
+ * Restores the parent trace as the current trace in the session
+ * @param trace The current resolver trace to exit from
+ */
+ public static void exit(ResolverTrace trace) {
+ InternalSession iSession = InternalSession.from(trace.session());
+ iSession.setCurrentTrace(trace.mvnTrace().parent());
+ }
+
+ /**
+ * Converts a Resolver trace to a Maven trace
+ * @param context The context string for the new Maven trace
+ * @param trace The Resolver trace to convert
+ * @return A new Maven trace, or null if the input trace was null
+ */
+ public static org.apache.maven.api.services.RequestTrace toMaven(String context, RequestTrace trace) {
+ if (trace != null) {
+ return new org.apache.maven.api.services.RequestTrace(
+ context, toMaven(context, trace.getParent()), trace.getData());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Converts a Maven trace to a Resolver trace
+ * @param trace The Maven trace to convert
+ * @return A new Resolver trace, or null if the input trace was null
+ */
+ public static RequestTrace toResolver(org.apache.maven.api.services.RequestTrace trace) {
+ if (trace != null) {
+ return RequestTrace.newChild(toResolver(trace.parent()), trace.data());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Creates a human-readable interpretation of a request trace
+ * @param detailed If true, includes additional details such as dependency paths
+ * @param requestTrace The trace to interpret
+ * @return A string describing the trace context and relevant details
+ */
+ public static String interpretTrace(boolean detailed, RequestTrace requestTrace) {
+ while (requestTrace != null) {
+ Object data = requestTrace.getData();
+ if (data instanceof DependencyRequest request) {
+ return "dependency resolution for " + request;
+ } else if (data instanceof CollectRequest request) {
+ return "dependency collection for " + request;
+ } else if (data instanceof CollectStepData stepData) {
+ String msg = "dependency collection step for " + stepData.getContext();
+ if (detailed) {
+ msg += ". Path to offending node from root:\n";
+ msg += stepData.getPath().stream()
+ .map(n -> " -> " + n.toString())
+ .collect(Collectors.joining("\n"));
+ msg += "\n => " + stepData.getNode();
+ }
+ return msg;
+ } else if (data instanceof ArtifactDescriptorRequest request) {
+ return "artifact descriptor request for " + request.getArtifact();
+ } else if (data instanceof ArtifactRequest request) {
+ return "artifact request for " + request.getArtifact();
+ } else if (data instanceof org.apache.maven.api.model.Plugin plugin) {
+ return "plugin " + plugin.getId();
+ }
+ requestTrace = requestTrace.getParent();
+ }
+
+ return "n/a";
+ }
+}
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 84545c34e0..f05f505b3d 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
@@ -82,6 +82,7 @@
import org.apache.maven.api.services.ModelSource;
import org.apache.maven.api.services.ProblemCollector;
import org.apache.maven.api.services.RepositoryFactory;
+import org.apache.maven.api.services.RequestTrace;
import org.apache.maven.api.services.Source;
import org.apache.maven.api.services.SuperPomProvider;
import org.apache.maven.api.services.VersionParserException;
@@ -109,6 +110,8 @@
import org.apache.maven.api.services.xml.XmlReaderRequest;
import org.apache.maven.api.spi.ModelParserException;
import org.apache.maven.api.spi.ModelTransformer;
+import org.apache.maven.impl.InternalSession;
+import org.apache.maven.impl.RequestTraceHelper;
import org.apache.maven.impl.util.PhasingExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -217,24 +220,30 @@ protected class ModelBuilderSessionImpl implements ModelBuilderSession {
*/
@Override
public ModelBuilderResult build(ModelBuilderRequest request) throws ModelBuilderException {
- // Create or derive a session based on the request
- ModelBuilderSessionState session;
- if (mainSession == null) {
- mainSession = new ModelBuilderSessionState(request);
- session = mainSession;
- } else {
- session = mainSession.derive(
- request, new DefaultModelBuilderResult(ProblemCollector.create(mainSession.session)));
- }
- // Build the request
- if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_PROJECT) {
- // build the build poms
- session.buildBuildPom();
- } else {
- // simply build the effective model
- session.buildEffectiveModel(new LinkedHashSet<>());
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(request.getSession(), request);
+ try {
+ // Create or derive a session based on the request
+ ModelBuilderSessionState session;
+ if (mainSession == null) {
+ mainSession = new ModelBuilderSessionState(request);
+ session = mainSession;
+ } else {
+ session = mainSession.derive(
+ request,
+ new DefaultModelBuilderResult(request, ProblemCollector.create(mainSession.session)));
+ }
+ // Build the request
+ if (request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_PROJECT) {
+ // build the build poms
+ session.buildBuildPom();
+ } else {
+ // simply build the effective model
+ session.buildEffectiveModel(new LinkedHashSet<>());
+ }
+ return session.result;
+ } finally {
+ RequestTraceHelper.exit(trace);
}
- return session.result;
}
}
@@ -260,7 +269,7 @@ protected class ModelBuilderSessionState implements ModelProblemCollector {
this(
request.getSession(),
request,
- new DefaultModelBuilderResult(ProblemCollector.create(request.getSession())),
+ new DefaultModelBuilderResult(request, ProblemCollector.create(request.getSession())),
request.getSession()
.getData()
.computeIfAbsent(SessionData.key(ModelCache.class), modelCacheFactory::newInstance),
@@ -302,7 +311,7 @@ private ModelBuilderSessionState(
}
ModelBuilderSessionState derive(ModelSource source) {
- return derive(source, new DefaultModelBuilderResult(ProblemCollector.create(session)));
+ return derive(source, new DefaultModelBuilderResult(request, ProblemCollector.create(session)));
}
ModelBuilderSessionState derive(ModelSource source, DefaultModelBuilderResult result) {
@@ -313,7 +322,7 @@ ModelBuilderSessionState derive(ModelSource source, DefaultModelBuilderResult re
* Creates a new session, sharing cached datas and propagating errors.
*/
ModelBuilderSessionState derive(ModelBuilderRequest request) {
- return derive(request, new DefaultModelBuilderResult(ProblemCollector.create(session)));
+ return derive(request, new DefaultModelBuilderResult(request, ProblemCollector.create(session)));
}
ModelBuilderSessionState derive(ModelBuilderRequest request, DefaultModelBuilderResult result) {
@@ -638,16 +647,21 @@ private void buildBuildPom() throws ModelBuilderException {
// This is done through the phased executor
var allResults = results(result).toList();
List<RuntimeException> exceptions = new CopyOnWriteArrayList<>();
+ InternalSession session = InternalSession.from(this.session);
+ RequestTrace trace = session.getCurrentTrace();
try (PhasingExecutor executor = createExecutor()) {
for (DefaultModelBuilderResult r : allResults) {
executor.execute(() -> {
ModelBuilderSessionState mbs = derive(r.getSource(), r);
+ session.setCurrentTrace(trace);
try {
mbs.buildEffectiveModel(new LinkedHashSet<>());
} catch (ModelBuilderException e) {
// gathered with problem collector
} catch (RuntimeException t) {
exceptions.add(t);
+ } finally {
+ session.setCurrentTrace(null);
}
});
}
@@ -681,7 +695,7 @@ private void loadFromRoot(Path root, Path top) {
try (PhasingExecutor executor = createExecutor()) {
DefaultModelBuilderResult r = Objects.equals(top, root)
? result
- : new DefaultModelBuilderResult(ProblemCollector.create(session));
+ : new DefaultModelBuilderResult(request, ProblemCollector.create(session));
loadFilePom(executor, top, root, Set.of(), r);
}
if (result.getFileModel() == null && !Objects.equals(top, root)) {
@@ -755,12 +769,21 @@ private void loadFilePom(
DefaultModelBuilderResult cr = Objects.equals(top, subprojectFile)
? result
- : new DefaultModelBuilderResult(ProblemCollector.create(session));
+ : new DefaultModelBuilderResult(request, ProblemCollector.create(session));
if (request.isRecursive()) {
r.getChildren().add(cr);
}
- executor.execute(() -> loadFilePom(executor, top, subprojectFile, concat(parents, pom), cr));
+ InternalSession session = InternalSession.from(this.session);
+ RequestTrace trace = session.getCurrentTrace();
+ executor.execute(() -> {
+ session.setCurrentTrace(trace);
+ try {
+ loadFilePom(executor, top, subprojectFile, concat(parents, pom), cr);
+ } finally {
+ session.setCurrentTrace(null);
+ }
+ });
}
} catch (ModelBuilderException e) {
// gathered with problem collector
@@ -1881,12 +1904,17 @@ private static List<String> getSubprojects(Model activated) {
@Override
public Model buildRawModel(ModelBuilderRequest request) throws ModelBuilderException {
- ModelBuilderSessionState build = new ModelBuilderSessionState(request);
- Model model = build.readRawModel();
- if (build.hasErrors()) {
- throw build.newModelBuilderException();
+ RequestTraceHelper.ResolverTrace trace = RequestTraceHelper.enter(request.getSession(), request);
+ try {
+ ModelBuilderSessionState build = new ModelBuilderSessionState(request);
+ Model model = build.readRawModel();
+ if (build.hasErrors()) {
+ throw build.newModelBuilderException();
+ }
+ return model;
+ } finally {
+ RequestTraceHelper.exit(trace);
}
- return model;
}
static String getGroupId(Model model) {
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilderResult.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilderResult.java
index 89f4b7ae38..5f87b7d779 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilderResult.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilderResult.java
@@ -25,6 +25,7 @@
import org.apache.maven.api.model.Model;
import org.apache.maven.api.model.Profile;
+import org.apache.maven.api.services.ModelBuilderRequest;
import org.apache.maven.api.services.ModelBuilderResult;
import org.apache.maven.api.services.ModelProblem;
import org.apache.maven.api.services.ModelSource;
@@ -34,6 +35,7 @@
* Collects the output of the model builder.
*/
class DefaultModelBuilderResult implements ModelBuilderResult {
+ private ModelBuilderRequest request;
private ModelSource source;
private Model fileModel;
private Model rawModel;
@@ -44,10 +46,16 @@ class DefaultModelBuilderResult implements ModelBuilderResult {
private final ProblemCollector<ModelProblem> problemCollector;
private final List<DefaultModelBuilderResult> children = new ArrayList<>();
- DefaultModelBuilderResult(ProblemCollector<ModelProblem> problemCollector) {
+ DefaultModelBuilderResult(ModelBuilderRequest request, ProblemCollector<ModelProblem> problemCollector) {
+ this.request = request;
this.problemCollector = problemCollector;
}
+ @Override
+ public ModelBuilderRequest getRequest() {
+ return request;
+ }
+
@Override
public ModelSource getSource() {
return source;
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java
index 3343c4678f..f3928494aa 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/DefaultArtifactDescriptorReader.java
@@ -38,6 +38,7 @@
import org.apache.maven.api.services.ProblemCollector;
import org.apache.maven.api.services.model.ModelResolverException;
import org.apache.maven.impl.InternalSession;
+import org.apache.maven.impl.RequestTraceHelper;
import org.apache.maven.impl.model.ModelProblemUtils;
import org.eclipse.aether.RepositoryEvent;
import org.eclipse.aether.RepositoryEvent.EventType;
@@ -195,6 +196,7 @@ private Model loadPom(
pomArtifact.getGroupId() + ":" + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion();
ModelBuilderRequest modelRequest = ModelBuilderRequest.builder()
.session(iSession)
+ .trace(RequestTraceHelper.toMaven(request.getRequestContext(), trace))
.requestType(ModelBuilderRequest.RequestType.CONSUMER_DEPENDENCY)
.source(ModelSource.fromPath(pomArtifact.getPath(), gav))
// This merge is on purpose because otherwise user properties would override model
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/RequestTraceHelper.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/RequestTraceHelper.java
deleted file mode 100644
index 3ee54da7aa..0000000000
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/resolver/RequestTraceHelper.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.maven.impl.resolver;
-
-import java.util.stream.Collectors;
-
-import org.eclipse.aether.RequestTrace;
-import org.eclipse.aether.collection.CollectRequest;
-import org.eclipse.aether.collection.CollectStepData;
-import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
-import org.eclipse.aether.resolution.ArtifactRequest;
-import org.eclipse.aether.resolution.DependencyRequest;
-
-/**
- * Helper class to manage {@link RequestTrace} for better error logging.
- */
-public final class RequestTraceHelper {
-
- /**
- * Method that creates some informational string based on passed in {@link RequestTrace}. The contents of request
- * trace can literally be anything, but this class tries to cover "most common" cases that are happening in Maven.
- */
- public static String interpretTrace(boolean detailed, RequestTrace requestTrace) {
- while (requestTrace != null) {
- Object data = requestTrace.getData();
- if (data instanceof DependencyRequest request) {
- return "dependency resolution for " + request;
- } else if (data instanceof CollectRequest request) {
- return "dependency collection for " + request;
- } else if (data instanceof CollectStepData stepData) {
- String msg = "dependency collection step for " + stepData.getContext();
- if (detailed) {
- msg += ". Path to offending node from root:\n";
- msg += stepData.getPath().stream()
- .map(n -> " -> " + n.toString())
- .collect(Collectors.joining("\n"));
- msg += "\n => " + stepData.getNode();
- }
- return msg;
- } else if (data instanceof ArtifactDescriptorRequest request) {
- return "artifact descriptor request for " + request.getArtifact();
- } else if (data instanceof ArtifactRequest request) {
- return "artifact request for " + request.getArtifact();
- // TODO: this class is not reachable here!
- // } else if (data instanceof org.apache.maven.model.Plugin plugin) {
- // return "plugin " + plugin.getId();
- }
- requestTrace = requestTrace.getParent();
- }
-
- return "n/a";
- }
-}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/RequestTraceHelperTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/RequestTraceHelperTest.java
new file mode 100644
index 0000000000..33294298ad
--- /dev/null
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/RequestTraceHelperTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.impl;
+
+import org.apache.maven.api.services.Request;
+import org.eclipse.aether.RequestTrace;
+import org.eclipse.aether.resolution.ArtifactRequest;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class RequestTraceHelperTest {
+
+ @Test
+ void testEnterWithRequestData() {
+ InternalSession session = mock(InternalSession.class);
+ Request<?> request = mock(Request.class);
+ org.apache.maven.api.services.RequestTrace existingTrace =
+ new org.apache.maven.api.services.RequestTrace(null, "test");
+
+ when(request.getTrace()).thenReturn(existingTrace);
+
+ RequestTraceHelper.ResolverTrace result = RequestTraceHelper.enter(session, request);
+
+ assertNotNull(result);
+ assertEquals(existingTrace, result.mvnTrace());
+ verify(session).setCurrentTrace(existingTrace);
+ }
+
+ @Test
+ void testInterpretTraceWithArtifactRequest() {
+ ArtifactRequest artifactRequest = mock(ArtifactRequest.class);
+ RequestTrace trace = RequestTrace.newChild(null, artifactRequest);
+
+ String result = RequestTraceHelper.interpretTrace(false, trace);
+
+ assertTrue(result.startsWith("artifact request for "));
+ }
+
+ @Test
+ void testToMavenWithNullTrace() {
+ assertNull(RequestTraceHelper.toMaven("test", null));
+ }
+
+ @Test
+ void testToResolverWithNullTrace() {
+ assertNull(RequestTraceHelper.toResolver(null));
+ }
+
+ @Test
+ void testExitResetsParentTrace() {
+ InternalSession session = mock(InternalSession.class);
+ org.apache.maven.api.services.RequestTrace parentTrace =
+ new org.apache.maven.api.services.RequestTrace(null, "parent");
+ org.apache.maven.api.services.RequestTrace currentTrace =
+ new org.apache.maven.api.services.RequestTrace(parentTrace, "current");
+
+ RequestTraceHelper.ResolverTrace resolverTrace =
+ new RequestTraceHelper.ResolverTrace(session, "test", null, currentTrace);
+
+ RequestTraceHelper.exit(resolverTrace);
+
+ verify(session).setCurrentTrace(parentTrace);
+ }
+}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderResultTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderResultTest.java
new file mode 100644
index 0000000000..beea6fa88b
--- /dev/null
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderResultTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.impl.model;
+
+import org.apache.maven.api.model.Model;
+import org.apache.maven.api.services.BuilderProblem;
+import org.apache.maven.api.services.ModelBuilderRequest;
+import org.apache.maven.api.services.ModelProblem;
+import org.apache.maven.api.services.ModelSource;
+import org.apache.maven.api.services.ProblemCollector;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.mock;
+
+class DefaultModelBuilderResultTest {
+
+ private ModelBuilderRequest request;
+ private ProblemCollector<ModelProblem> problemCollector;
+ private DefaultModelBuilderResult result;
+ private ModelSource source;
+ private Model fileModel;
+ private Model rawModel;
+ private Model effectiveModel;
+
+ @BeforeEach
+ void setUp() {
+ request = mock(ModelBuilderRequest.class);
+ problemCollector = ProblemCollector.create(10);
+ result = new DefaultModelBuilderResult(request, problemCollector);
+
+ source = mock(ModelSource.class);
+ fileModel = mock(Model.class);
+ rawModel = mock(Model.class);
+ effectiveModel = mock(Model.class);
+ }
+
+ @Test
+ void testModelLifecycle() {
+ // Test initial state
+ assertNull(result.getSource());
+ assertNull(result.getFileModel());
+ assertNull(result.getRawModel());
+ assertNull(result.getEffectiveModel());
+ assertEquals(0L, result.getProblemCollector().problems().count());
+
+ // Set and verify source
+ result.setSource(source);
+ assertSame(source, result.getSource());
+
+ // Set and verify file model
+ result.setFileModel(fileModel);
+ assertSame(fileModel, result.getFileModel());
+
+ // Set and verify raw model
+ result.setRawModel(rawModel);
+ assertSame(rawModel, result.getRawModel());
+
+ // Set and verify effective model
+ result.setEffectiveModel(effectiveModel);
+ assertSame(effectiveModel, result.getEffectiveModel());
+ }
+
+ @Test
+ void testProblemCollection() {
+ ModelProblem problem = mock(ModelProblem.class);
+ Mockito.when(problem.getSeverity()).thenReturn(BuilderProblem.Severity.ERROR);
+ problemCollector.reportProblem(problem);
+
+ assertEquals(1, result.getProblemCollector().problems().count());
+ assertSame(problem, result.getProblemCollector().problems().findFirst().get());
+ }
+
+ @Test
+ void testChildrenManagement() {
+ DefaultModelBuilderResult child1 = new DefaultModelBuilderResult(request, problemCollector);
+ DefaultModelBuilderResult child2 = new DefaultModelBuilderResult(request, problemCollector);
+
+ result.getChildren().add(child1);
+ result.getChildren().add(child2);
+
+ assertEquals(2, result.getChildren().size());
+ assertTrue(result.getChildren().contains(child1));
+ assertTrue(result.getChildren().contains(child2));
+ }
+
+ @Test
+ void testRequestAssociation() {
+ assertSame(request, result.getRequest());
+ }
+}
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RequestTraceTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RequestTraceTest.java
new file mode 100644
index 0000000000..b9eaf6b4d0
--- /dev/null
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/standalone/RequestTraceTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.impl.standalone;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.maven.api.ArtifactCoordinates;
+import org.apache.maven.api.DownloadedArtifact;
+import org.apache.maven.api.Node;
+import org.apache.maven.api.PathScope;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.services.DependencyResolver;
+import org.apache.maven.api.services.DependencyResolverRequest;
+import org.apache.maven.api.services.ModelBuilder;
+import org.apache.maven.api.services.ModelBuilderRequest;
+import org.apache.maven.api.services.ModelBuilderResult;
+import org.apache.maven.api.services.ModelSource;
+import org.apache.maven.api.services.RequestTrace;
+import org.apache.maven.impl.InternalSession;
+import org.apache.maven.impl.RequestTraceHelper;
+import org.eclipse.aether.AbstractRepositoryListener;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositoryEvent;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class RequestTraceTest {
+
+ @Test
+ void testTraces() {
+ Session session = ApiRunner.createSession();
+
+ ModelBuilder builder = session.getService(ModelBuilder.class);
+ ModelBuilderResult result = builder.newSession()
+ .build(ModelBuilderRequest.builder()
+ .session(session)
+ .source(ModelSource.fromPath(Paths.get("pom.xml").toAbsolutePath()))
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .recursive(true)
+ .build());
+ assertNotNull(result.getEffectiveModel());
+
+ List<RepositoryEvent> events = new CopyOnWriteArrayList<>();
+ ((DefaultRepositorySystemSession) InternalSession.from(session).getSession())
+ .setRepositoryListener(new AbstractRepositoryListener() {
+ @Override
+ public void artifactResolved(RepositoryEvent event) {
+ events.add(event);
+ }
+ });
+
+ ArtifactCoordinates coords =
+ session.createArtifactCoordinates("org.apache.maven:maven-api-core:4.0.0-alpha-13");
+ DownloadedArtifact res = session.resolveArtifact(coords);
+ assertNotNull(res);
+ assertNotNull(res.getPath());
+ assertTrue(Files.exists(res.getPath()));
+
+ Node node = session.getService(DependencyResolver.class)
+ .collect(DependencyResolverRequest.builder()
+ .trace(new RequestTrace("collect", null, null))
+ .session(session)
+ .requestType(DependencyResolverRequest.RequestType.COLLECT)
+ .dependency(session.createDependencyCoordinates(coords))
+ .pathScope(PathScope.MAIN_RUNTIME)
+ .build())
+ .getRoot()
+ .getChildren()
+ .iterator()
+ .next();
+
+ for (RepositoryEvent event : events) {
+ org.eclipse.aether.RequestTrace trace = event.getTrace();
+ assertNotNull(trace);
+
+ RequestTrace rTrace = RequestTraceHelper.toMaven("collect", trace);
+ assertNotNull(rTrace);
+ assertNotNull(rTrace.parent());
+ }
+
+ assertNotNull(node);
+ assertEquals(6, node.getChildren().size());
+ }
+}