15 | * Note: this component offers access to Resolver internals, but it is up to caller to know really how to use
16 | * this feature (for example due compatibility reasons). Ideally, you do not want to use this, or use it only
17 | * in some "advanced scenarios".
18 | *
19 | * @since 2.4.10
20 | */
21 | public interface Lookup {
22 | /**
23 | * Performs lookup for component with passed in type, and returns it as optional, never {@code null}.
24 | */
25 |
22 | * For internal use only in runtimes.
23 | */
24 | public final class PreBoot {
25 | private final ContextOverrides overrides;
26 |
27 | private final MavenUserHomeImpl mavenUserHome;
28 |
29 | private final MavenSystemHomeImpl mavenSystemHome;
30 |
31 | private final Path baseDir;
32 |
33 | public PreBoot(
34 | ContextOverrides overrides,
35 | MavenUserHomeImpl mavenUserHome,
36 | MavenSystemHomeImpl mavenSystemHome,
37 | Path baseDir) {
38 | this.overrides = requireNonNull(overrides);
39 | this.mavenUserHome = requireNonNull(mavenUserHome);
40 | this.mavenSystemHome = mavenSystemHome; // nullable
41 | this.baseDir = requireNonNull(baseDir);
42 | }
43 |
44 | public ContextOverrides getOverrides() {
45 | return overrides;
46 | }
47 |
48 | public MavenUserHomeImpl getMavenUserHome() {
49 | return mavenUserHome;
50 | }
51 |
52 | public MavenSystemHomeImpl getMavenSystemHome() {
53 | return mavenSystemHome;
54 | }
55 |
56 | public Path getBaseDir() {
57 | return baseDir;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/runtime/embedded-maven/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
21 | * Configuration not applied, which should be handled by caller/user of this factory:
22 | *
29 | * Differences between {@link #createResolutionClient(RemoteRepository)} and {@link #createDeploymentClient(RemoteRepository)}
30 | * are exactly the same as in Maven/Resolver. See corresponding Javadoc.
31 | *
32 | * @see MavenHttpClient4FactoryImpl
33 | */
34 | public class MavenHttpClient4Factory {
35 | protected final Context context;
36 | protected final MavenHttpClient4FactoryImpl factory;
37 |
38 | /**
39 | * Creates instance using passed in context.
40 | */
41 | public MavenHttpClient4Factory(Context context) {
42 | this.context = requireNonNull(context);
43 | this.factory = new MavenHttpClient4FactoryImpl(context.repositorySystem());
44 | }
45 |
46 | /**
47 | * Creates {@link HttpClientBuilder} preconfigured from Maven environment for resolving.
48 | */
49 | public HttpClientBuilder createResolutionClient(RemoteRepository repository) {
50 | return factory.createResolutionClient(context.repositorySystemSession(), repository);
51 | }
52 |
53 | /**
54 | * Creates {@link HttpClientBuilder} preconfigured from Maven environment for deployment.
55 | */
56 | public HttpClientBuilder createDeploymentClient(RemoteRepository repository) {
57 | return factory.createDeploymentClient(context.repositorySystemSession(), repository);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/demo/library/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
21 | * One example would be something similar like done in Toolbox: getting raw model, modify it, interpolate it and finally
22 | * transform it to {@link ArtifactDescriptorResult} for friendlier after-processing in Resolver.
23 | */
24 | public class ModelResponse {
25 | private final Model rawModel;
26 | private final Model effectiveModel;
27 | private final ArtifactRepository repository;
28 | private final Function
53 | * If you intend to modify model but need to keep "original" as well, use method {@link Model#clone()} to clone the
54 | * model instance, otherwise you will end up with modified model in this result instance.
55 | */
56 | public Model getEffectiveModel() {
57 | return effectiveModel;
58 | }
59 |
60 | /**
61 | * Returns the "raw" (as is on disk) model.
62 | *
63 | * If you intend to modify model but need to keep "original" as well, use method {@link Model#clone()} to clone the
64 | * model instance, otherwise you will end up with modified model in this result instance.
65 | */
66 | public Model getRawModel() {
67 | return rawModel;
68 | }
69 |
70 | /**
71 | * Gets the repository from which the descriptor was eventually resolved or {@code null} if unknown.
72 | */
73 | public ArtifactRepository getRepository() {
74 | return repository;
75 | }
76 |
77 | /**
78 | * Returns artifact descriptor result of given model.
79 | */
80 | public ArtifactDescriptorResult toArtifactDescriptorResult(Model model) {
81 | requireNonNull(model);
82 | return converter.apply(model);
83 | }
84 |
85 | /**
86 | * Returns the model "lineage" keys, first in list represents "current" model, last the Super POM, and parents in
87 | * middle.
88 | */
89 | public List
29 | * This component resembles {@link org.eclipse.aether.RepositorySystem#readArtifactDescriptor(RepositorySystemSession, org.eclipse.aether.resolution.ArtifactDescriptorRequest)}
30 | * somewhat, but have notable differences:
31 | *
45 | * Note: this extension and all classes in it are EXPERIMENTAL, use on your own risk!
46 | */
47 | public class MavenModelReader {
48 | private final Logger logger = LoggerFactory.getLogger(getClass());
49 | private final Context context;
50 | private final MavenModelReaderImpl mavenModelReaderImpl;
51 |
52 | /**
53 | * Creates instance using passed in context. As context carries "root" remote repositories, they are used
54 | * by default, but can be overridden in {@link ModelRequest}.
55 | */
56 | public MavenModelReader(Context context) {
57 | this.context = requireNonNull(context);
58 | this.mavenModelReaderImpl = new MavenModelReaderImpl(
59 | context.repositorySystem(),
60 | context.lookup()
61 | .lookup(RemoteRepositoryManager.class)
62 | .orElseThrow(() -> new IllegalStateException("RemoteRepositoryManager not available")),
63 | context.lookup()
64 | .lookup(RepositoryEventDispatcher.class)
65 | .orElseThrow(() -> new IllegalStateException("RepositoryEventDispatcher not available")),
66 | context.lookup()
67 | .lookup(ModelBuilder.class)
68 | .orElseThrow(() -> new IllegalStateException("ModelBuilder not available")),
69 | context.lookup()
70 | .lookup(StringVisitorModelInterpolator.class)
71 | .orElseThrow(() -> new IllegalStateException("StringVisitorModelInterpolator not available")),
72 | context.remoteRepositories());
73 | }
74 |
75 | /**
76 | * Reads POM as {@link ModelResponse}.
77 | *
78 | * Remark related to repositories: by default context "root" remote repositories will be used, unless
79 | * request {@link ModelRequest#getRepositories()} returns non-null value, in which case request provided
80 | * repositories will be used.
81 | */
82 | public ModelResponse readModel(ModelRequest request)
83 | throws VersionResolutionException, ArtifactResolutionException, ArtifactDescriptorException {
84 | requireNonNull(request, "request");
85 | return mavenModelReaderImpl.readModel(context.repositorySystemSession(), request);
86 | }
87 |
88 | /**
89 | * Just to allow easier testing.
90 | */
91 | public MavenModelReaderImpl getImpl() {
92 | return mavenModelReaderImpl;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/runtime/standalone-sisu-uber/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
25 | * The very first context instance application creates using {@link Runtime#create(ContextOverrides)} is called "root
26 | * context", and creation of it can be considered "heavy" operation (runtime dependent). Root context should be kept
27 | * open as long as application is expected to make use of Resolver.
28 | *
29 | * Context instances may be customized with {@link #customize(ContextOverrides)} method, in that case the returned
30 | * context is "derived" from this context. In those cases the context instances should be handled "as nested", so
31 | * closed in opposite order as they were obtained. Creating customized contexts can be considered "light" operation,
32 | * as they merely alter the {@link RepositorySystemSession} instance and repositories, while the
33 | * {@link RepositorySystem} is just inherited from this instance (is not reconstructed).
34 | *
35 | * @see Runtimes#getRuntime()
36 | * @see Runtime#create(ContextOverrides)
37 | */
38 | public final class Context implements Closeable {
39 | private final AtomicBoolean closed;
40 |
41 | private final RuntimeSupport runtime;
42 |
43 | private final ContextOverrides contextOverrides;
44 |
45 | private final Path basedir;
46 |
47 | private final MavenUserHome mavenUserHome;
48 |
49 | private final MavenSystemHome mavenSystemHome;
50 |
51 | private final RepositorySystem repositorySystem;
52 |
53 | private final RepositorySystemSession repositorySystemSession;
54 |
55 | private final List
23 | *
28 | *
32 | *
41 | * The purpose of this extension is to provide insight into Maven models without the need to fiddle
42 | * with any of those things like Model builder and so on. Usages like some "analysis" or "introspection"
43 | * or "validation" come to mind for start.
44 | *
45 | *
48 | */
49 | public class Classpath {
50 |
51 | private final Logger logger = LoggerFactory.getLogger(getClass());
52 |
53 | public String model(ContextOverrides overrides, String artifactStr)
54 | throws VersionResolutionException, ArtifactResolutionException, ArtifactDescriptorException, IOException {
55 | requireNonNull(artifactStr);
56 | Runtime runtime = Runtimes.INSTANCE.getRuntime();
57 | logger.debug("Runtimes.getRuntime: {}", runtime);
58 |
59 | try (Context context = runtime.create(overrides)) {
60 | MavenModelReader mmr = new MavenModelReader(context);
61 | ModelResponse response = mmr.readModel(ModelRequest.builder()
62 | .setArtifact(new DefaultArtifact(artifactStr))
63 | .setRequestContext("classpath-demo")
64 | .build());
65 | Model model = response.getEffectiveModel();
66 | try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
67 | String encoding = model.getModelEncoding();
68 | if (encoding == null || encoding.length() <= 0) {
69 | encoding = "UTF-8";
70 | }
71 |
72 | try (Writer out = new OutputStreamWriter(outputStream, Charset.forName(encoding))) {
73 | new MavenXpp3Writer().write(out, model);
74 | }
75 | return outputStream.toString(encoding);
76 | }
77 | }
78 | }
79 |
80 | public String classpath(ContextOverrides overrides, String artifactStr) throws DependencyResolutionException {
81 | requireNonNull(artifactStr);
82 | Runtime runtime = Runtimes.INSTANCE.getRuntime();
83 | logger.debug("Runtimes.getRuntime: {}", runtime);
84 |
85 | // ad-hoc: create context w/ or w/o overrides
86 | // other way is to make this class manage context or manage context outside it
87 | // depends what you need: one shot or reuse of MIMA instance
88 | try (Context context = runtime.create(overrides)) {
89 | DefaultArtifact artifact = new DefaultArtifact(artifactStr);
90 | logger.info("doClasspath: {}", context.remoteRepositories());
91 |
92 | RemoteRepositoryManager remoteRepositoryManager = context.lookup()
93 | .lookup(RemoteRepositoryManager.class)
94 | .orElseThrow(() -> new IllegalStateException("component not found"));
95 | for (RemoteRepository repository : context.remoteRepositories()) {
96 | RepositoryPolicy policy = remoteRepositoryManager.getPolicy(
97 | context.repositorySystemSession(), repository, !artifact.isSnapshot(), artifact.isSnapshot());
98 | logger.info("Repository {} effective policy: {}", repository.getId(), policy);
99 | }
100 |
101 | Dependency dependency = new Dependency(artifact, "runtime");
102 | CollectRequest collectRequest = new CollectRequest();
103 | collectRequest.setRoot(dependency);
104 | collectRequest.setRepositories(context.remoteRepositories());
105 |
106 | DependencyRequest dependencyRequest = new DependencyRequest();
107 | dependencyRequest.setCollectRequest(collectRequest);
108 |
109 | DependencyNode rootNode = context.repositorySystem()
110 | .resolveDependencies(context.repositorySystemSession(), dependencyRequest)
111 | .getRoot();
112 |
113 | PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
114 | rootNode.accept(nlg);
115 | return nlg.getClassPath();
116 | }
117 | }
118 |
119 | public static void main(String... args) {
120 | if (args.length != 1) {
121 | throw new IllegalArgumentException("g:a:v");
122 | }
123 | Classpath classpath = new Classpath();
124 | try {
125 | ContextOverrides overrides =
126 | ContextOverrides.create().withUserSettings(true).build();
127 |
128 | String cp = classpath.classpath(overrides, args[0]);
129 | System.out.println("Classpath of " + args[0] + " is:");
130 | System.out.println(cp);
131 | } catch (DependencyResolutionException e) {
132 | System.err.println("Error: " + e.getMessage());
133 | }
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/context/src/main/java/eu/maveniverse/maven/mima/context/Context.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2023-2024 Maveniverse Org.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Eclipse Public License v2.0
5 | * which accompanies this distribution, and is available at
6 | * https://www.eclipse.org/legal/epl-v20.html
7 | */
8 | package eu.maveniverse.maven.mima.context;
9 |
10 | import static java.util.Objects.requireNonNull;
11 |
12 | import eu.maveniverse.maven.mima.context.internal.RuntimeSupport;
13 | import java.io.Closeable;
14 | import java.nio.file.Path;
15 | import java.util.List;
16 | import java.util.concurrent.atomic.AtomicBoolean;
17 | import org.eclipse.aether.RepositorySystem;
18 | import org.eclipse.aether.RepositorySystemSession;
19 | import org.eclipse.aether.repository.RemoteRepository;
20 |
21 | /**
22 | * The MIMA context holds references to {@link RepositorySystem}, {@link RepositorySystemSession} and list of
23 | * {@link RemoteRepository}. Context is {@link Closeable}, ideally used in try-with-resource constructs.
24 | *