Skip to content

Commit

Permalink
MMR Repositories can be overridden and should be exposed (#169)
Browse files Browse the repository at this point in the history
Changes:
* make sure passed in repositories are fully prepared for resolving (auth, proxy, mirror etc)
* expose repository of origin, no need to make hoops and loops (ask for irrelevant Resolver type just to get it)
* add UT and fix
  • Loading branch information
cstamas authored Feb 8, 2025
1 parent 37e0c3f commit f5c5e23
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 23 deletions.
5 changes: 5 additions & 0 deletions extensions/mmr/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
* perform it manually: inspect the effective model and based on {@link org.apache.maven.model.Relocation}
* issue another request for relocation target.</li>
* <li>Does not obey {@link RepositorySystemSession#getArtifactDescriptorPolicy()}, if asked artifact does not
* exists, it will fail.</li>
* exist, it will fail.</li>
* <li>If passed in {@link Artifact} is resolved ({@link Artifact#getFile()} returns non-{@code null} value), then
* model will be read from that file directly. Naturally, to be able to build the model, the possible
* parent and other POMs must be resolvable.</li>
Expand All @@ -44,13 +44,21 @@ public class MavenModelReader {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final MavenModelReaderImpl mavenModelReaderImpl;

/**
* Creates instance using passed in context. As context carries "root" remote repositories, they are used
* by default, but can be overridden in {@link ModelRequest}.
*/
public MavenModelReader(Context context) {
requireNonNull(context, "context");
this.mavenModelReaderImpl = new MavenModelReaderImpl(context);
}

/**
* Reads POM as {@link ModelResponse}.
* <p>
* Remark related to repositories: by default context "root" remote repositories will be used, unless
* request {@link ModelRequest#getRepositories()} returns non-null value, in which case request provided
* repositories will be used.
*/
public ModelResponse readModel(ModelRequest request)
throws VersionResolutionException, ArtifactResolutionException, ArtifactDescriptorException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import static java.util.Objects.requireNonNull;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.aether.RequestTrace;
import org.eclipse.aether.artifact.Artifact;
Expand All @@ -25,12 +27,12 @@ public static Builder builder() {
}

private final Artifact artifact;
private final List<RemoteRepository> repositories;
private final String requestContext;
private final RequestTrace trace;
private final List<RemoteRepository> repositories;

private ModelRequest(
Artifact artifact, String requestContext, RequestTrace trace, List<RemoteRepository> repositories) {
Artifact artifact, List<RemoteRepository> repositories, String requestContext, RequestTrace trace) {
this.artifact = requireNonNull(artifact);
this.requestContext = requestContext == null ? "" : requestContext;
this.trace = trace;
Expand All @@ -41,6 +43,10 @@ public Artifact getArtifact() {
return artifact;
}

public List<RemoteRepository> getRepositories() {
return repositories;
}

public String getRequestContext() {
return requestContext;
}
Expand All @@ -49,10 +55,6 @@ public RequestTrace getTrace() {
return trace;
}

public List<RemoteRepository> getRepositories() {
return repositories;
}

public Builder toBuilder() {
return new Builder(this);
}
Expand All @@ -67,39 +69,61 @@ private Builder() {}

private Builder(ModelRequest request) {
this.artifact = request.artifact;
this.repositories = request.repositories;
this.requestContext = request.requestContext;
this.trace = request.trace;
this.repositories = request.repositories;
}

public ModelRequest build() {
return new ModelRequest(artifact, requestContext, trace, repositories);
return new ModelRequest(
artifact,
repositories != null ? Collections.unmodifiableList(new ArrayList<>(repositories)) : null,
requestContext,
trace);
}

/**
* Make possible to point at a POM anywhere on file system, to have it built. Naturally, all the required
* bits like parent POM, imported POM must be still resolvable (from local or remote repositories).
*/
public Builder setPomFile(Path pomFile) {
requireNonNull(pomFile);
return setArtifact(new DefaultArtifact("irrelevant:irrelevant:irrelevant").setFile(pomFile.toFile()));
}

/**
* Sets the artifact whose POM we want to build model for. The artifact must be resolvable from local or
* remote repositories.
*/
public Builder setArtifact(Artifact artifact) {
requireNonNull(artifact);
this.artifact = artifact;
return this;
}

/**
* Optionally, user may want to override context "root" repositories with own set (ie appended or totally new
* list of repositories).
*/
public Builder setRepositories(List<RemoteRepository> repositories) {
this.repositories = repositories;
return this;
}

/**
* Sets the request context for bookkeeping purposes.
*/
public Builder setRequestContext(String requestContext) {
this.requestContext = requestContext;
return this;
}

/**
* Sets the request trace for bookkeeping purposes.
*/
public Builder setTrace(RequestTrace trace) {
this.trace = trace;
return this;
}

public Builder setRepositories(List<RemoteRepository> repositories) {
this.repositories = repositories;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;
import java.util.function.Function;
import org.apache.maven.model.Model;
import org.eclipse.aether.repository.ArtifactRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorResult;

/**
Expand All @@ -23,6 +24,7 @@
public class ModelResponse {
private final Model rawModel;
private final Model effectiveModel;
private final ArtifactRepository repository;
private final Function<Model, ArtifactDescriptorResult> converter;
private final List<String> lineage;
private final Function<String, Model> lineageFunction;
Expand All @@ -31,12 +33,14 @@ public class ModelResponse {
public ModelResponse(
Model rawModel,
Model effectiveModel,
ArtifactRepository repository,
Function<Model, ArtifactDescriptorResult> converter,
List<String> lineage,
Function<String, Model> lineageFunction,
Function<Model, Model> interpolatorFunction) {
this.rawModel = requireNonNull(rawModel);
this.effectiveModel = requireNonNull(effectiveModel);
this.repository = repository;
this.converter = requireNonNull(converter);
this.lineage = requireNonNull(lineage);
this.lineageFunction = requireNonNull(lineageFunction);
Expand All @@ -63,6 +67,13 @@ public Model getRawModel() {
return rawModel;
}

/**
* Gets the repository from which the descriptor was eventually resolved or {@code null} if unknown.
*/
public ArtifactRepository getRepository() {
return repository;
}

/**
* Returns artifact descriptor result of given model.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ public ModelResponse readModel(ModelRequest request)

private ModelResponse loadPom(RepositorySystemSession session, ModelRequest request)
throws VersionResolutionException, ArtifactResolutionException, ArtifactDescriptorException {
ArtifactDescriptorRequest artifactDescriptorRequest = new ArtifactDescriptorRequest();
artifactDescriptorRequest.setArtifact(request.getArtifact());
List<RemoteRepository> repositories = this.repositories;
if (request.getRepositories() != null) {
artifactDescriptorRequest.setRepositories(request.getRepositories());
} else {
artifactDescriptorRequest.setRepositories(this.repositories);
repositories = repositorySystem.newResolutionRepositories(session, request.getRepositories());
}

ArtifactDescriptorRequest artifactDescriptorRequest = new ArtifactDescriptorRequest();
artifactDescriptorRequest.setArtifact(request.getArtifact());
artifactDescriptorRequest.setRepositories(repositories);
artifactDescriptorRequest.setRequestContext(request.getRequestContext());
artifactDescriptorRequest.setTrace(request.getTrace());
ArtifactDescriptorResult artifactDescriptorResult = new ArtifactDescriptorResult(artifactDescriptorRequest);
Expand Down Expand Up @@ -236,6 +237,7 @@ private ModelResponse loadPom(RepositorySystemSession session, ModelRequest requ
return new ModelResponse(
modelResult.getRawModel().clone(),
modelResult.getEffectiveModel().clone(),
artifactDescriptorResult.getRepository(),
m -> {
ArtifactDescriptorResult r = new ArtifactDescriptorResult(artifactDescriptorRequest);
r.setRepository(artifactDescriptorResult.getRepository());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,50 @@
import eu.maveniverse.maven.mima.context.Context;
import eu.maveniverse.maven.mima.context.ContextOverrides;
import eu.maveniverse.maven.mima.context.Runtimes;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Stream;
import org.apache.maven.model.Model;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.repository.ArtifactRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorResult;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

public class MavenModelReaderTest {
@Test
void smoke() throws Exception {
private static Stream<RemoteRepository> repositories() {
return Arrays.stream(new RemoteRepository[] {
null, // context
ContextOverrides.CENTRAL, // central override
new RemoteRepository.Builder("foobar", "default", "https://repo1.maven.org/maven2").build() // alt central
});
}

@ParameterizedTest
@MethodSource("repositories")
void smoke(RemoteRepository overrideRepository) throws Exception {
try (Context context =
Runtimes.INSTANCE.getRuntime().create(ContextOverrides.create().build())) {
MavenModelReader reader = new MavenModelReader(context);

ModelResponse response = reader.readModel(ModelRequest.builder()
.setArtifact(new DefaultArtifact("org.apache.maven:maven-core:3.9.9"))
.setRepositories(overrideRepository != null ? Collections.singletonList(overrideRepository) : null)
.setRequestContext("test")
.build());
assertNotNull(response);
Model model;

// REPO
ArtifactRepository responseRepository = response.getRepository();
if (overrideRepository == null) {
assertEquals(context.remoteRepositories().get(0), responseRepository);
} else {
assertEquals(overrideRepository, responseRepository);
}

// RAW
model = response.getRawModel();
assertNotNull(model);
Expand Down
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<version.maven>3.9.9</version.maven>
<version.sisu>0.9.0.M3</version.sisu>
<version.slf4j>1.7.36</version.slf4j>
<version.junit>5.11.4</version.junit>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -241,7 +242,12 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.4</version>
<version>${version.junit}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${version.junit}</version>
</dependency>
</dependencies>
</dependencyManagement>
Expand Down

0 comments on commit f5c5e23

Please sign in to comment.