1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl.standalone;
20
21 import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import java.time.Instant;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Objects;
30 import java.util.Optional;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.stream.Collectors;
33
34 import org.apache.maven.api.Artifact;
35 import org.apache.maven.api.Lifecycle;
36 import org.apache.maven.api.Packaging;
37 import org.apache.maven.api.ProducedArtifact;
38 import org.apache.maven.api.Project;
39 import org.apache.maven.api.RemoteRepository;
40 import org.apache.maven.api.Session;
41 import org.apache.maven.api.Type;
42 import org.apache.maven.api.Version;
43 import org.apache.maven.api.di.Provides;
44 import org.apache.maven.api.model.PluginContainer;
45 import org.apache.maven.api.model.Profile;
46 import org.apache.maven.api.services.ArtifactManager;
47 import org.apache.maven.api.services.LifecycleRegistry;
48 import org.apache.maven.api.services.Lookup;
49 import org.apache.maven.api.services.MavenException;
50 import org.apache.maven.api.services.PackagingRegistry;
51 import org.apache.maven.api.services.RepositoryFactory;
52 import org.apache.maven.api.services.SettingsBuilder;
53 import org.apache.maven.api.services.TypeRegistry;
54 import org.apache.maven.api.services.model.ProfileActivator;
55 import org.apache.maven.api.settings.Settings;
56 import org.apache.maven.api.spi.ModelParser;
57 import org.apache.maven.api.spi.TypeProvider;
58 import org.apache.maven.di.Injector;
59 import org.apache.maven.di.Key;
60 import org.apache.maven.di.impl.DIException;
61 import org.apache.maven.internal.impl.AbstractSession;
62 import org.apache.maven.internal.impl.DefaultArtifactCoordinatesFactory;
63 import org.apache.maven.internal.impl.DefaultArtifactDeployer;
64 import org.apache.maven.internal.impl.DefaultArtifactFactory;
65 import org.apache.maven.internal.impl.DefaultArtifactInstaller;
66 import org.apache.maven.internal.impl.DefaultArtifactResolver;
67 import org.apache.maven.internal.impl.DefaultChecksumAlgorithmService;
68 import org.apache.maven.internal.impl.DefaultDependencyCoordinatesFactory;
69 import org.apache.maven.internal.impl.DefaultDependencyResolver;
70 import org.apache.maven.internal.impl.DefaultLocalRepositoryManager;
71 import org.apache.maven.internal.impl.DefaultMessageBuilderFactory;
72 import org.apache.maven.internal.impl.DefaultModelUrlNormalizer;
73 import org.apache.maven.internal.impl.DefaultModelVersionParser;
74 import org.apache.maven.internal.impl.DefaultModelXmlFactory;
75 import org.apache.maven.internal.impl.DefaultPluginConfigurationExpander;
76 import org.apache.maven.internal.impl.DefaultRepositoryFactory;
77 import org.apache.maven.internal.impl.DefaultSettingsBuilder;
78 import org.apache.maven.internal.impl.DefaultSettingsXmlFactory;
79 import org.apache.maven.internal.impl.DefaultSuperPomProvider;
80 import org.apache.maven.internal.impl.DefaultToolchainsBuilder;
81 import org.apache.maven.internal.impl.DefaultToolchainsXmlFactory;
82 import org.apache.maven.internal.impl.DefaultTransportProvider;
83 import org.apache.maven.internal.impl.DefaultUrlNormalizer;
84 import org.apache.maven.internal.impl.DefaultVersionParser;
85 import org.apache.maven.internal.impl.ExtensibleEnumRegistries;
86 import org.apache.maven.internal.impl.InternalSession;
87 import org.apache.maven.internal.impl.model.BuildModelTransformer;
88 import org.apache.maven.internal.impl.model.DefaultDependencyManagementImporter;
89 import org.apache.maven.internal.impl.model.DefaultDependencyManagementInjector;
90 import org.apache.maven.internal.impl.model.DefaultInheritanceAssembler;
91 import org.apache.maven.internal.impl.model.DefaultLifecycleBindingsInjector;
92 import org.apache.maven.internal.impl.model.DefaultModelBuilder;
93 import org.apache.maven.internal.impl.model.DefaultModelInterpolator;
94 import org.apache.maven.internal.impl.model.DefaultModelNormalizer;
95 import org.apache.maven.internal.impl.model.DefaultModelPathTranslator;
96 import org.apache.maven.internal.impl.model.DefaultModelProcessor;
97 import org.apache.maven.internal.impl.model.DefaultModelValidator;
98 import org.apache.maven.internal.impl.model.DefaultModelVersionProcessor;
99 import org.apache.maven.internal.impl.model.DefaultPathTranslator;
100 import org.apache.maven.internal.impl.model.DefaultPluginManagementInjector;
101 import org.apache.maven.internal.impl.model.DefaultProfileInjector;
102 import org.apache.maven.internal.impl.model.DefaultProfileSelector;
103 import org.apache.maven.internal.impl.model.DefaultRootLocator;
104 import org.apache.maven.internal.impl.model.ProfileActivationFilePathInterpolator;
105 import org.apache.maven.internal.impl.resolver.DefaultVersionRangeResolver;
106 import org.apache.maven.internal.impl.resolver.DefaultVersionResolver;
107 import org.apache.maven.internal.impl.resolver.MavenVersionScheme;
108 import org.apache.maven.internal.impl.resolver.type.DefaultTypeProvider;
109 import org.eclipse.aether.DefaultRepositorySystemSession;
110 import org.eclipse.aether.RepositorySystem;
111 import org.eclipse.aether.RepositorySystemSession;
112 import org.eclipse.aether.impl.RemoteRepositoryManager;
113 import org.eclipse.aether.repository.LocalRepository;
114 import org.eclipse.aether.repository.LocalRepositoryManager;
115
116 public class ApiRunner {
117
118
119
120
121 public static Session createSession() {
122 Injector injector = Injector.create();
123 injector.bindInstance(Injector.class, injector);
124 injector.bindImplicit(ApiRunner.class);
125 injector.bindImplicit(DefaultArtifactCoordinatesFactory.class);
126 injector.bindImplicit(DefaultArtifactDeployer.class);
127 injector.bindImplicit(DefaultArtifactFactory.class);
128 injector.bindImplicit(DefaultArtifactInstaller.class);
129 injector.bindImplicit(DefaultArtifactResolver.class);
130 injector.bindImplicit(DefaultChecksumAlgorithmService.class);
131 injector.bindImplicit(DefaultDependencyResolver.class);
132 injector.bindImplicit(DefaultDependencyCoordinatesFactory.class);
133 injector.bindImplicit(DefaultLocalRepositoryManager.class);
134 injector.bindImplicit(DefaultMessageBuilderFactory.class);
135 injector.bindImplicit(DefaultModelXmlFactory.class);
136 injector.bindImplicit(DefaultRepositoryFactory.class);
137 injector.bindImplicit(DefaultSettingsBuilder.class);
138 injector.bindImplicit(DefaultSettingsXmlFactory.class);
139 injector.bindImplicit(DefaultToolchainsBuilder.class);
140 injector.bindImplicit(DefaultToolchainsXmlFactory.class);
141 injector.bindImplicit(DefaultTransportProvider.class);
142 injector.bindImplicit(DefaultVersionParser.class);
143 injector.bindImplicit(DefaultVersionRangeResolver.class);
144 injector.bindImplicit(org.apache.maven.internal.impl.DefaultVersionParser.class);
145 injector.bindImplicit(org.apache.maven.internal.impl.DefaultVersionRangeResolver.class);
146 injector.bindImplicit(DefaultVersionResolver.class);
147 injector.bindImplicit(ExtensibleEnumRegistries.class);
148 injector.bindImplicit(DefaultTypeProvider.class);
149
150 injector.bindImplicit(MavenVersionScheme.class);
151 injector.bindImplicit(BuildModelTransformer.class);
152 injector.bindImplicit(DefaultDependencyManagementImporter.class);
153 injector.bindImplicit(DefaultDependencyManagementInjector.class);
154 injector.bindImplicit(DefaultModelBuilder.class);
155 injector.bindImplicit(DefaultModelProcessor.class);
156 injector.bindImplicit(DefaultModelValidator.class);
157 injector.bindImplicit(DefaultModelVersionProcessor.class);
158 injector.bindImplicit(DefaultModelNormalizer.class);
159 injector.bindImplicit(DefaultModelInterpolator.class);
160 injector.bindImplicit(DefaultPathTranslator.class);
161 injector.bindImplicit(DefaultRootLocator.class);
162 injector.bindImplicit(DefaultModelPathTranslator.class);
163 injector.bindImplicit(DefaultUrlNormalizer.class);
164 injector.bindImplicit(DefaultModelUrlNormalizer.class);
165 injector.bindImplicit(DefaultSuperPomProvider.class);
166 injector.bindImplicit(DefaultInheritanceAssembler.class);
167 injector.bindImplicit(DefaultProfileInjector.class);
168 injector.bindImplicit(DefaultProfileSelector.class);
169 injector.bindImplicit(DefaultPluginManagementInjector.class);
170 injector.bindImplicit(DefaultLifecycleBindingsInjector.class);
171 injector.bindImplicit(DefaultPluginConfigurationExpander.class);
172 injector.bindImplicit(ProfileActivationFilePathInterpolator.class);
173 injector.bindImplicit(DefaultModelVersionParser.class);
174
175 injector.bindImplicit(ProfileActivator.class);
176 injector.bindImplicit(ModelParser.class);
177
178 return injector.getInstance(Session.class);
179 }
180
181 static class DefaultSession extends AbstractSession {
182
183 private final Map<String, String> systemProperties;
184 private Instant startTime = Instant.now();
185
186 DefaultSession(RepositorySystemSession session, RepositorySystem repositorySystem, Lookup lookup) {
187 this(session, repositorySystem, Collections.emptyList(), null, lookup);
188 }
189
190 protected DefaultSession(
191 RepositorySystemSession session,
192 RepositorySystem repositorySystem,
193 List<RemoteRepository> repositories,
194 List<org.eclipse.aether.repository.RemoteRepository> resolverRepositories,
195 Lookup lookup) {
196 super(session, repositorySystem, repositories, resolverRepositories, lookup);
197 systemProperties = System.getenv().entrySet().stream()
198 .collect(Collectors.toMap(e -> "env." + e.getKey(), e -> e.getValue()));
199 System.getProperties().forEach((k, v) -> systemProperties.put(k.toString(), v.toString()));
200 }
201
202 @Override
203 protected Session newSession(RepositorySystemSession session, List<RemoteRepository> repositories) {
204 return new DefaultSession(session, repositorySystem, repositories, null, lookup);
205 }
206
207 @Override
208 public Settings getSettings() {
209 return Settings.newInstance();
210 }
211
212 @Override
213 public Map<String, String> getUserProperties() {
214 return Map.of();
215 }
216
217 @Override
218 public Map<String, String> getSystemProperties() {
219 return systemProperties;
220 }
221
222 @Override
223 public Map<String, String> getEffectiveProperties(Project project) {
224 HashMap<String, String> result = new HashMap<>(getSystemProperties());
225 if (project != null) {
226 result.putAll(project.getModel().getProperties());
227 }
228 result.putAll(getUserProperties());
229 return result;
230 }
231
232 @Override
233 public Version getMavenVersion() {
234 return null;
235 }
236
237 @Override
238 public int getDegreeOfConcurrency() {
239 return 0;
240 }
241
242 @Override
243 public Instant getStartTime() {
244 return startTime;
245 }
246
247 @Override
248 public Path getTopDirectory() {
249 return null;
250 }
251
252 @Override
253 public Path getRootDirectory() {
254 return null;
255 }
256
257 @Override
258 public List<Project> getProjects() {
259 return List.of();
260 }
261
262 @Override
263 public Map<String, Object> getPluginContext(Project project) {
264 throw new UnsupportedInStandaloneModeException();
265 }
266 }
267
268 @Provides
269 static Lookup newLookup(Injector injector) {
270 return new Lookup() {
271 @Override
272 public <T> T lookup(Class<T> type) {
273 try {
274 return injector.getInstance(type);
275 } catch (DIException e) {
276 throw new MavenException("Unable to locate instance of type " + type, e);
277 }
278 }
279
280 @Override
281 public <T> T lookup(Class<T> type, String name) {
282 try {
283 return injector.getInstance(Key.of(type, name));
284 } catch (DIException e) {
285 throw new MavenException("Unable to locate instance of type " + type, e);
286 }
287 }
288
289 @Override
290 public <T> Optional<T> lookupOptional(Class<T> type) {
291 try {
292 return Optional.of(injector.getInstance(type));
293 } catch (DIException e) {
294 return Optional.empty();
295 }
296 }
297
298 @Override
299 public <T> Optional<T> lookupOptional(Class<T> type, String name) {
300 try {
301 return Optional.of(injector.getInstance(Key.of(type, name)));
302 } catch (DIException e) {
303 return Optional.empty();
304 }
305 }
306
307 @Override
308 public <T> List<T> lookupList(Class<T> type) {
309 return injector.getInstance(new Key<List<T>>() {});
310 }
311
312 @Override
313 public <T> Map<String, T> lookupMap(Class<T> type) {
314 return injector.getInstance(new Key<Map<String, T>>() {});
315 }
316 };
317 }
318
319 @Provides
320 static ArtifactManager newArtifactManager() {
321 return new ArtifactManager() {
322 private final Map<Artifact, Path> paths = new ConcurrentHashMap<>();
323
324 @Override
325 public Optional<Path> getPath(Artifact artifact) {
326 return Optional.ofNullable(paths.get(artifact));
327 }
328
329 @Override
330 public void setPath(ProducedArtifact artifact, Path path) {
331 paths.put(artifact, path);
332 }
333 };
334 }
335
336 @Provides
337 static PackagingRegistry newPackagingRegistry(TypeRegistry typeRegistry) {
338 return id -> Optional.of(new DumbPackaging(id, typeRegistry.require(id), Map.of()));
339 }
340
341 @Provides
342 static TypeRegistry newTypeRegistry(List<TypeProvider> providers) {
343 return new TypeRegistry() {
344 @Override
345 public Optional<Type> lookup(String id) {
346 return providers.stream()
347 .flatMap(p -> p.provides().stream())
348 .filter(t -> Objects.equals(id, t.id()))
349 .findAny();
350 }
351 };
352 }
353
354 @Provides
355 static LifecycleRegistry newLifecycleRegistry() {
356 return new LifecycleRegistry() {
357
358 @Override
359 public Iterator<Lifecycle> iterator() {
360 return Collections.emptyIterator();
361 }
362
363 @Override
364 public Optional<Lifecycle> lookup(String id) {
365 return Optional.empty();
366 }
367
368 @Override
369 public List<String> computePhases(Lifecycle lifecycle) {
370 return List.of();
371 }
372 };
373 }
374
375 @Provides
376 static RepositorySystemSupplier newRepositorySystemSupplier() {
377 return new RepositorySystemSupplier();
378 }
379
380 @Provides
381 static RepositorySystem newRepositorySystem(RepositorySystemSupplier repositorySystemSupplier) {
382 return repositorySystemSupplier.getRepositorySystem();
383 }
384
385 @Provides
386 static RemoteRepositoryManager newRemoteRepositoryManager(RepositorySystemSupplier repositorySystemSupplier) {
387 return repositorySystemSupplier.getRemoteRepositoryManager();
388 }
389
390 @Provides
391 static Session newSession(RepositorySystem system, Lookup lookup) {
392 Map<String, String> properties = new HashMap<>();
393
394 System.getenv().forEach((k, v) -> properties.put("env." + k, v));
395
396 System.getProperties().forEach((k, v) -> properties.put(k.toString(), v.toString()));
397
398
399
400
401
402
403
404
405
406
407 Path userHome = Paths.get(properties.get("user.home"));
408 Path mavenUserHome = userHome.resolve(".m2");
409 Path mavenSystemHome = properties.containsKey("maven.home")
410 ? Paths.get(properties.get("maven.home"))
411 : properties.containsKey("env.MAVEN_HOME") ? Paths.get(properties.get("env.MAVEN_HOME")) : null;
412
413 DefaultRepositorySystemSession rsession = new DefaultRepositorySystemSession(h -> false);
414 rsession.setSystemProperties(properties);
415 rsession.setConfigProperties(properties);
416
417 DefaultSession session = new DefaultSession(
418 rsession,
419 system,
420 List.of(lookup.lookup(RepositoryFactory.class)
421 .createRemote("central", "https://repo.maven.apache.org/maven2")),
422 null,
423 lookup);
424
425 Settings settings = session.getService(SettingsBuilder.class)
426 .build(
427 session,
428 mavenSystemHome != null ? mavenSystemHome.resolve("settings.xml") : null,
429 mavenUserHome.resolve("settings.xml"))
430 .getEffectiveSettings();
431
432 settings.getProfiles();
433
434
435 String localRepository = settings.getLocalRepository() != null
436 ? settings.getLocalRepository()
437 : mavenUserHome.resolve("repository").toString();
438 LocalRepositoryManager llm = system.newLocalRepositoryManager(rsession, new LocalRepository(localRepository));
439 rsession.setLocalRepositoryManager(llm);
440
441
442
443
444 DefaultSession defaultSession = new DefaultSession(
445 rsession,
446 system,
447 List.of(lookup.lookup(RepositoryFactory.class)
448 .createRemote("central", "https://repo.maven.apache.org/maven2")),
449 null,
450 lookup);
451
452 Profile profile = session.getService(SettingsBuilder.class)
453 .convert(org.apache.maven.api.settings.Profile.newBuilder()
454 .repositories(settings.getRepositories())
455 .pluginRepositories(settings.getPluginRepositories())
456 .build());
457 RepositoryFactory repositoryFactory = session.getService(RepositoryFactory.class);
458 List<RemoteRepository> repositories = profile.getRepositories().stream()
459 .map(repositoryFactory::createRemote)
460 .toList();
461 InternalSession s = (InternalSession) session.withRemoteRepositories(repositories);
462 InternalSession.associate(rsession, s);
463 return s;
464
465
466
467
468
469
470
471
472
473 }
474
475 static class UnsupportedInStandaloneModeException extends MavenException {}
476
477 record DumbPackaging(String id, Type type, Map<String, PluginContainer> plugins) implements Packaging {}
478 }