Skip to content

Commit

Permalink
Introduce lookup (#92)
Browse files Browse the repository at this point in the history
Introduce a `Lookup` on context to be able to reach some Resolver components. Add demo doing it as well (and demo runs with "static" and "sisu" standalone runtimes, but also embedded in maven as "maven-plugin").

Fixes #94
  • Loading branch information
cstamas authored Apr 8, 2024
1 parent 93e3baf commit 36aca85
Show file tree
Hide file tree
Showing 14 changed files with 749 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public final class Context implements Closeable {

private final HTTPProxy httpProxy;

private final Lookup lookup;

private final Runnable managedCloser;

public Context(
Expand All @@ -68,6 +70,7 @@ public Context(
RepositorySystemSession repositorySystemSession,
List<RemoteRepository> remoteRepositories,
HTTPProxy httpProxy,
Lookup lookup,
Runnable managedCloser) {
this.closed = new AtomicBoolean(false);
this.runtime = requireNonNull(runtime);
Expand All @@ -79,6 +82,7 @@ public Context(
this.repositorySystem = requireNonNull(repositorySystem);
this.remoteRepositories = requireNonNull(remoteRepositories);
this.httpProxy = httpProxy;
this.lookup = requireNonNull(lookup);
this.managedCloser = managedCloser;
}

Expand Down Expand Up @@ -150,6 +154,15 @@ public HTTPProxy httpProxy() {
return httpProxy;
}

/**
* Returns {@link Lookup} instance usable to look up resolver components, never {@code null}.
*
* @since 2.4.10
*/
public Lookup lookup() {
return lookup;
}

/**
* Returns a new {@link Context} instance, that is customized using passed in {@link ContextOverrides}, using this
* instance as "base".
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package eu.maveniverse.maven.mima.context;

import java.util.Optional;

/**
* A simple "lookup" that allows to lookup various components. Lookup shares lifecycle with {@link Context}.
* <p>
* Note: this component offers access to Resolver internals, but it is up to caller to know really how to use
* this feature (for example due compatibility reasons). Ideally, you do not want to use this, or use it only
* in some "advanced scenarios".
*
* @since 2.4.10
*/
public interface Lookup {
/**
* Performs lookup for component with passed in type, and returns it as optional, never {@code null}.
*/
<T> Optional<T> lookup(Class<T> type);

/**
* Performs lookup for component with passed in type and name, and returns it as optional, never {@code null}.
*/
<T> Optional<T> lookup(Class<T> type, String name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package eu.maveniverse.maven.mima.context.internal;

import static java.util.Objects.requireNonNull;

import eu.maveniverse.maven.mima.context.Lookup;
import java.util.*;

/**
* A {@link Lookup} implementation that is able to iterate through several lookups, applying "first deliver wins"
* strategy.
*
* @since 2.4.10
*/
public final class IteratingLookup implements Lookup {
private final Collection<Lookup> lookups;

public IteratingLookup(Lookup... lookups) {
this(Arrays.asList(lookups));
}

public IteratingLookup(Collection<Lookup> lookups) {
this.lookups = requireNonNull(lookups);
}

@Override
public <T> Optional<T> lookup(Class<T> type) {
for (Lookup lookup : lookups) {
Optional<T> result = lookup.lookup(type);
if (result.isPresent()) {
return result;
}
}
return Optional.empty();
}

@Override
public <T> Optional<T> lookup(Class<T> type, String name) {
for (Lookup lookup : lookups) {
Optional<T> result = lookup.lookup(type, name);
if (result.isPresent()) {
return result;
}
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ protected Context customizeContext(
session,
context.repositorySystem().newResolutionRepositories(session, remoteRepositories),
context.httpProxy(),
context.lookup(),
null); // derived context: close should NOT shut down repositorySystem
}

Expand Down
18 changes: 18 additions & 0 deletions demo/library/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@
<groupId>eu.maveniverse.maven.mima</groupId>
<artifactId>context</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>
<version>1.9.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-spi</artifactId>
<version>1.9.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId>
<version>1.9.18</version>
<scope>provided</scope>
</dependency>
<!-- runtime dependency (dormant outside of Maven) -->
<dependency>
<groupId>eu.maveniverse.maven.mima.runtime</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This is an imaginary library class that wants to:
* <ul>
* <li>use Resolver API and components</li>
* <li>needs to work standalone, but also embedded in Maven (ie as a plugin dependency)</li>
* </ul>
*/
public class Classpath {

private final Logger logger = LoggerFactory.getLogger(getClass());
Expand All @@ -42,8 +52,24 @@ public String classpath(ContextOverrides overrides, String artifactStr) throws D
}
}

/**
* Implements the "logic" of this theoretical library:
* <ul>
* <li>Logs at INFO the effective policy of all involved remote repositories (uses Resolver component)</li>
* <li>Resolves the artifact (uses Resolver API)</li>
* <li>Logs at INFO the SHA-1 hashes of all resolved artifacts (uses Resolver component)</li>
* <li>Returns the classpath string of resolved artifact</li>
* </ul>
*/
private String doClasspath(Context context, Artifact artifact) throws DependencyResolutionException {
logger.info("doClasspath: {}", context.remoteRepositories());

RemoteRepositoryManager remoteRepositoryManager = context.lookup().lookup(RemoteRepositoryManager.class).orElseThrow(() -> new IllegalStateException("component not found"));
for (RemoteRepository repository : context.remoteRepositories()) {
RepositoryPolicy policy = remoteRepositoryManager.getPolicy(context.repositorySystemSession(), repository, !artifact.isSnapshot(), artifact.isSnapshot());
logger.info("Repository {} effective policy: {}", repository.getId(), policy);
}

Dependency dependency = new Dependency(artifact, "runtime");
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRoot(dependency);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import eu.maveniverse.maven.mima.context.internal.MavenSystemHomeImpl;
import eu.maveniverse.maven.mima.context.internal.MavenUserHomeImpl;
import eu.maveniverse.maven.mima.context.internal.RuntimeSupport;
import eu.maveniverse.maven.mima.runtime.maven.internal.PlexusLookup;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
Expand All @@ -26,6 +27,7 @@
import org.apache.maven.execution.MavenSession;
import org.apache.maven.rtinfo.RuntimeInformation;
import org.apache.maven.settings.Proxy;
import org.codehaus.plexus.PlexusContainer;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;

Expand All @@ -34,17 +36,23 @@
public final class MavenRuntime extends RuntimeSupport {
private final RepositorySystem repositorySystem;

private final PlexusContainer plexusContainer;

private final Provider<MavenSession> mavenSessionProvider;

@Inject
public MavenRuntime(
RepositorySystem repositorySystem, Provider<MavenSession> mavenSessionProvider, RuntimeInformation rt) {
RepositorySystem repositorySystem,
PlexusContainer plexusContainer,
Provider<MavenSession> mavenSessionProvider,
RuntimeInformation rt) {
super(
"embedded-maven",
discoverArtifactVersion("eu.maveniverse.maven.mima.runtime", "embedded-maven", UNKNOWN),
10,
mavenVersion(rt));
this.repositorySystem = repositorySystem;
this.plexusContainer = plexusContainer;
this.mavenSessionProvider = mavenSessionProvider;
}

Expand Down Expand Up @@ -100,6 +108,7 @@ public Context create(ContextOverrides overrides) {
session,
repositorySystem.newResolutionRepositories(session, effective.getRepositories()),
toHTTPProxy(mavenSession.getSettings().getActiveProxy()),
new PlexusLookup(plexusContainer),
null),
false); // unmanaged context: close should NOT shut down repositorySystem
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package eu.maveniverse.maven.mima.runtime.maven.internal;

import static java.util.Objects.requireNonNull;

import eu.maveniverse.maven.mima.context.Lookup;
import java.util.Optional;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;

public final class PlexusLookup implements Lookup {
private final PlexusContainer plexusContainer;

public PlexusLookup(PlexusContainer plexusContainer) {
this.plexusContainer = requireNonNull(plexusContainer);
}

@Override
public <T> Optional<T> lookup(Class<T> type) {
try {
return Optional.of(plexusContainer.lookup(type));
} catch (ComponentLookupException e) {
return Optional.empty();
}
}

@Override
public <T> Optional<T> lookup(Class<T> type, String name) {
try {
return Optional.of(plexusContainer.lookup(type, name));
} catch (ComponentLookupException e) {
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import eu.maveniverse.maven.mima.context.Context;
import eu.maveniverse.maven.mima.context.ContextOverrides;
import eu.maveniverse.maven.mima.context.HTTPProxy;
import eu.maveniverse.maven.mima.context.Lookup;
import eu.maveniverse.maven.mima.context.MavenSystemHome;
import eu.maveniverse.maven.mima.context.MavenUserHome;
import eu.maveniverse.maven.mima.context.internal.MavenSystemHomeImpl;
Expand Down Expand Up @@ -135,6 +136,7 @@ protected Context buildContext(
SettingsBuilder settingsBuilder,
SettingsDecrypter settingsDecrypter,
ProfileSelector profileSelector,
Lookup lookup,
Runnable managedCloser) {
try {
ContextOverrides alteredOverrides = preBoot.getOverrides();
Expand Down Expand Up @@ -236,6 +238,7 @@ protected Context buildContext(
session,
repositorySystem.newResolutionRepositories(session, new ArrayList<>(remoteRepositories.values())),
httpProxy,
lookup,
managedCloser);
} catch (Exception e) {
throw new IllegalStateException("Cannot create context from scratch", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
import eu.maveniverse.maven.mima.runtime.shared.PreBoot;
import eu.maveniverse.maven.mima.runtime.shared.StandaloneRuntimeSupport;
import eu.maveniverse.maven.mima.runtime.standalonesisu.internal.SisuBooter;
import eu.maveniverse.maven.mima.runtime.standalonesisu.internal.SisuLookup;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.apache.maven.model.profile.ProfileSelector;
import org.apache.maven.settings.building.SettingsBuilder;
import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.sisu.inject.MutableBeanLocator;

@Singleton
@Named
Expand All @@ -32,21 +34,25 @@ public final class StandaloneSisuRuntime extends StandaloneRuntimeSupport {

private final ProfileSelector profileSelector;

private final MutableBeanLocator locator;

public StandaloneSisuRuntime() {
this(null, null, null, null);
this(null, null, null, null, null);
}

@Inject
public StandaloneSisuRuntime(
RepositorySystem repositorySystem,
SettingsBuilder settingsBuilder,
SettingsDecrypter settingsDecrypter,
ProfileSelector profileSelector) {
ProfileSelector profileSelector,
MutableBeanLocator locator) {
super("standalone-sisu", 30);
this.repositorySystem = repositorySystem;
this.settingsBuilder = settingsBuilder;
this.settingsDecrypter = settingsDecrypter;
this.profileSelector = profileSelector;
this.locator = locator;
}

@Override
Expand All @@ -67,10 +73,18 @@ public Context create(ContextOverrides overrides) {
booter.settingsBuilder,
booter.settingsDecrypter,
booter.profileSelector,
new SisuLookup(booter.locator),
booter::close);
} else {
return buildContext(
this, preBoot, repositorySystem, settingsBuilder, settingsDecrypter, profileSelector, null);
this,
preBoot,
repositorySystem,
settingsBuilder,
settingsDecrypter,
profileSelector,
new SisuLookup(locator),
null);
}
}
}
Loading

0 comments on commit 36aca85

Please sign in to comment.