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;
20
21 import java.io.File;
22 import java.nio.file.Path;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.NoSuchElementException;
29 import java.util.Objects;
30 import java.util.Optional;
31 import java.util.WeakHashMap;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.concurrent.CopyOnWriteArrayList;
34 import java.util.function.Supplier;
35 import java.util.stream.Collectors;
36
37 import org.apache.maven.api.Artifact;
38 import org.apache.maven.api.ArtifactCoordinate;
39 import org.apache.maven.api.Dependency;
40 import org.apache.maven.api.DependencyCoordinate;
41 import org.apache.maven.api.DependencyScope;
42 import org.apache.maven.api.Language;
43 import org.apache.maven.api.Listener;
44 import org.apache.maven.api.LocalRepository;
45 import org.apache.maven.api.Node;
46 import org.apache.maven.api.Packaging;
47 import org.apache.maven.api.PathScope;
48 import org.apache.maven.api.PathType;
49 import org.apache.maven.api.Project;
50 import org.apache.maven.api.ProjectScope;
51 import org.apache.maven.api.RemoteRepository;
52 import org.apache.maven.api.Service;
53 import org.apache.maven.api.Session;
54 import org.apache.maven.api.SessionData;
55 import org.apache.maven.api.Type;
56 import org.apache.maven.api.Version;
57 import org.apache.maven.api.VersionConstraint;
58 import org.apache.maven.api.VersionRange;
59 import org.apache.maven.api.annotations.Nonnull;
60 import org.apache.maven.api.annotations.Nullable;
61 import org.apache.maven.api.model.Repository;
62 import org.apache.maven.api.services.*;
63 import org.eclipse.aether.DefaultRepositorySystemSession;
64 import org.eclipse.aether.RepositorySystem;
65 import org.eclipse.aether.RepositorySystemSession;
66
67 import static org.apache.maven.internal.impl.Utils.map;
68 import static org.apache.maven.internal.impl.Utils.nonNull;
69
70 public abstract class AbstractSession implements InternalSession {
71
72 protected final RepositorySystemSession session;
73 protected final RepositorySystem repositorySystem;
74 protected final List<RemoteRepository> repositories;
75 protected final Lookup lookup;
76 private final Map<Class<? extends Service>, Service> services = new ConcurrentHashMap<>();
77 private final List<Listener> listeners = new CopyOnWriteArrayList<>();
78 private final Map<org.eclipse.aether.graph.DependencyNode, Node> allNodes =
79 Collections.synchronizedMap(new WeakHashMap<>());
80 private final Map<org.eclipse.aether.artifact.Artifact, Artifact> allArtifacts =
81 Collections.synchronizedMap(new WeakHashMap<>());
82 private final Map<org.eclipse.aether.repository.RemoteRepository, RemoteRepository> allRepositories =
83 Collections.synchronizedMap(new WeakHashMap<>());
84 private final Map<org.eclipse.aether.graph.Dependency, Dependency> allDependencies =
85 Collections.synchronizedMap(new WeakHashMap<>());
86
87 public AbstractSession(
88 RepositorySystemSession session,
89 RepositorySystem repositorySystem,
90 List<RemoteRepository> repositories,
91 List<org.eclipse.aether.repository.RemoteRepository> resolverRepositories,
92 Lookup lookup) {
93 this.session = nonNull(session, "session");
94 this.repositorySystem = repositorySystem;
95 this.repositories = getRepositories(repositories, resolverRepositories);
96 this.lookup = lookup;
97 }
98
99 @Override
100 public RemoteRepository getRemoteRepository(org.eclipse.aether.repository.RemoteRepository repository) {
101 return allRepositories.computeIfAbsent(repository, DefaultRemoteRepository::new);
102 }
103
104 @Override
105 public Node getNode(org.eclipse.aether.graph.DependencyNode node) {
106 return getNode(node, false);
107 }
108
109 @Override
110 public Node getNode(org.eclipse.aether.graph.DependencyNode node, boolean verbose) {
111 return allNodes.computeIfAbsent(node, n -> new DefaultNode(this, n, verbose));
112 }
113
114 @Nonnull
115 @Override
116 public Artifact getArtifact(@Nonnull org.eclipse.aether.artifact.Artifact artifact) {
117 return allArtifacts.computeIfAbsent(artifact, a -> new DefaultArtifact(this, a));
118 }
119
120 @Nonnull
121 @Override
122 public Dependency getDependency(@Nonnull org.eclipse.aether.graph.Dependency dependency) {
123 return allDependencies.computeIfAbsent(dependency, d -> new DefaultDependency(this, d));
124 }
125
126 @Override
127 public List<org.eclipse.aether.repository.RemoteRepository> toRepositories(List<RemoteRepository> repositories) {
128 return repositories == null ? null : map(repositories, this::toRepository);
129 }
130
131 @Override
132 public org.eclipse.aether.repository.RemoteRepository toRepository(RemoteRepository repository) {
133 if (repository instanceof DefaultRemoteRepository) {
134 return ((DefaultRemoteRepository) repository).getRepository();
135 } else {
136
137 throw new UnsupportedOperationException("Not implemented yet");
138 }
139 }
140
141 @Override
142 public org.eclipse.aether.repository.LocalRepository toRepository(LocalRepository repository) {
143 if (repository instanceof DefaultLocalRepository) {
144 return ((DefaultLocalRepository) repository).getRepository();
145 } else {
146
147 throw new UnsupportedOperationException("Not implemented yet");
148 }
149 }
150
151 @Override
152 public List<org.eclipse.aether.graph.Dependency> toDependencies(
153 Collection<DependencyCoordinate> dependencies, boolean managed) {
154 return dependencies == null ? null : map(dependencies, d -> toDependency(d, managed));
155 }
156
157 static List<RemoteRepository> getRepositories(
158 List<RemoteRepository> repositories,
159 List<org.eclipse.aether.repository.RemoteRepository> resolverRepositories) {
160 if (repositories != null) {
161 return repositories;
162 } else if (resolverRepositories != null) {
163 return map(resolverRepositories, DefaultRemoteRepository::new);
164 } else {
165 throw new IllegalArgumentException("no remote repositories provided");
166 }
167 }
168
169 @Nonnull
170 @Override
171 public List<RemoteRepository> getRemoteRepositories() {
172 return Collections.unmodifiableList(repositories);
173 }
174
175 @Nonnull
176 @Override
177 public SessionData getData() {
178 org.eclipse.aether.SessionData data = session.getData();
179 return new SessionData() {
180 @Override
181 public <T> void set(@Nonnull Key<T> key, @Nullable T value) {
182 data.set(key, value);
183 }
184
185 @Override
186 public <T> boolean replace(@Nonnull Key<T> key, @Nullable T oldValue, @Nullable T newValue) {
187 return data.set(key, oldValue, newValue);
188 }
189
190 @Nullable
191 @Override
192 @SuppressWarnings("unchecked")
193 public <T> T get(@Nonnull Key<T> key) {
194 return (T) data.get(key);
195 }
196
197 @Nullable
198 @Override
199 @SuppressWarnings("unchecked")
200 public <T> T computeIfAbsent(@Nonnull Key<T> key, @Nonnull Supplier<T> supplier) {
201 return (T) data.computeIfAbsent(key, (Supplier<Object>) supplier);
202 }
203 };
204 }
205
206 @Nonnull
207 @Override
208 public LocalRepository getLocalRepository() {
209 return new DefaultLocalRepository(session.getLocalRepository());
210 }
211
212 @Nonnull
213 @Override
214 public Session withLocalRepository(@Nonnull LocalRepository localRepository) {
215 nonNull(localRepository, "localRepository");
216 if (session.getLocalRepository() != null
217 && Objects.equals(session.getLocalRepository().getBasePath(), localRepository.getPath())) {
218 return this;
219 }
220 org.eclipse.aether.repository.LocalRepository repository = toRepository(localRepository);
221 org.eclipse.aether.repository.LocalRepositoryManager localRepositoryManager =
222 repositorySystem.newLocalRepositoryManager(session, repository);
223
224 RepositorySystemSession repoSession =
225 new DefaultRepositorySystemSession(session).setLocalRepositoryManager(localRepositoryManager);
226 return newSession(repoSession, repositories);
227 }
228
229 @Nonnull
230 @Override
231 public Session withRemoteRepositories(@Nonnull List<RemoteRepository> repositories) {
232 return newSession(session, repositories);
233 }
234
235 protected abstract Session newSession(RepositorySystemSession session, List<RemoteRepository> repositories);
236
237 @Nonnull
238 @Override
239 @SuppressWarnings("unchecked")
240 public <T extends Service> T getService(Class<T> clazz) throws NoSuchElementException {
241 T t = (T) services.computeIfAbsent(clazz, this::lookup);
242 if (t == null) {
243 throw new NoSuchElementException(clazz.getName());
244 }
245 return t;
246 }
247
248 private Service lookup(Class<? extends Service> c) {
249 try {
250 return lookup.lookup(c);
251 } catch (LookupException e) {
252 NoSuchElementException nsee = new NoSuchElementException(c.getName());
253 e.initCause(e);
254 throw nsee;
255 }
256 }
257
258 @Nonnull
259 public RepositorySystemSession getSession() {
260 return session;
261 }
262
263 @Nonnull
264 public RepositorySystem getRepositorySystem() {
265 return repositorySystem;
266 }
267
268 public org.eclipse.aether.graph.Dependency toDependency(DependencyCoordinate dependency, boolean managed) {
269 org.eclipse.aether.graph.Dependency dep;
270 if (dependency instanceof DefaultDependencyCoordinate) {
271 dep = ((DefaultDependencyCoordinate) dependency).getDependency();
272 } else {
273 dep = new org.eclipse.aether.graph.Dependency(
274 new org.eclipse.aether.artifact.DefaultArtifact(
275 dependency.getGroupId(),
276 dependency.getArtifactId(),
277 dependency.getClassifier(),
278 dependency.getType().getExtension(),
279 dependency.getVersion().toString(),
280 null),
281 dependency.getScope().id());
282 }
283 if (!managed && "".equals(dep.getScope())) {
284 dep = dep.setScope(DependencyScope.COMPILE.id());
285 }
286 return dep;
287 }
288
289 @Override
290 public List<org.eclipse.aether.artifact.Artifact> toArtifacts(Collection<Artifact> artifacts) {
291 return artifacts == null ? null : map(artifacts, this::toArtifact);
292 }
293
294 @Override
295 public org.eclipse.aether.artifact.Artifact toArtifact(Artifact artifact) {
296 Path path = getService(ArtifactManager.class).getPath(artifact).orElse(null);
297 if (artifact instanceof DefaultArtifact) {
298 org.eclipse.aether.artifact.Artifact a = ((DefaultArtifact) artifact).getArtifact();
299 if (Objects.equals(path, a.getPath())) {
300 return a;
301 }
302 }
303 return new org.eclipse.aether.artifact.DefaultArtifact(
304 artifact.getGroupId(),
305 artifact.getArtifactId(),
306 artifact.getClassifier(),
307 artifact.getExtension(),
308 artifact.getVersion().toString(),
309 null,
310 path);
311 }
312
313 @Override
314 public org.eclipse.aether.artifact.Artifact toArtifact(ArtifactCoordinate coord) {
315 if (coord instanceof DefaultArtifactCoordinate) {
316 return ((DefaultArtifactCoordinate) coord).getCoordinate();
317 }
318 return new org.eclipse.aether.artifact.DefaultArtifact(
319 coord.getGroupId(),
320 coord.getArtifactId(),
321 coord.getClassifier(),
322 coord.getExtension(),
323 coord.getVersion().toString(),
324 null,
325 (File) null);
326 }
327
328 @Override
329 public void registerListener(@Nonnull Listener listener) {
330 listeners.add(nonNull(listener));
331 }
332
333 @Override
334 public void unregisterListener(@Nonnull Listener listener) {
335 listeners.remove(nonNull(listener));
336 }
337
338 @Nonnull
339 @Override
340 public Collection<Listener> getListeners() {
341 return Collections.unmodifiableCollection(listeners);
342 }
343
344
345
346
347
348
349
350
351
352
353 @Override
354 public LocalRepository createLocalRepository(Path path) {
355 return getService(RepositoryFactory.class).createLocal(path);
356 }
357
358
359
360
361
362
363 @Nonnull
364 @Override
365 public RemoteRepository createRemoteRepository(@Nonnull String id, @Nonnull String url) {
366 return getService(RepositoryFactory.class).createRemote(id, url);
367 }
368
369
370
371
372
373
374 @Nonnull
375 @Override
376 public RemoteRepository createRemoteRepository(@Nonnull Repository repository) {
377 return getService(RepositoryFactory.class).createRemote(repository);
378 }
379
380
381
382
383
384
385 @Override
386 public ArtifactCoordinate createArtifactCoordinate(
387 String groupId, String artifactId, String version, String extension) {
388 return getService(ArtifactCoordinateFactory.class).create(this, groupId, artifactId, version, extension);
389 }
390
391
392
393
394
395
396 @Override
397 public ArtifactCoordinate createArtifactCoordinate(String coordString) {
398 return getService(ArtifactCoordinateFactory.class).create(this, coordString);
399 }
400
401
402
403
404
405
406 @Override
407 public ArtifactCoordinate createArtifactCoordinate(
408 String groupId, String artifactId, String version, String classifier, String extension, String type) {
409 return getService(ArtifactCoordinateFactory.class)
410 .create(this, groupId, artifactId, version, classifier, extension, type);
411 }
412
413
414
415
416
417
418 @Override
419 public ArtifactCoordinate createArtifactCoordinate(Artifact artifact) {
420 return getService(ArtifactCoordinateFactory.class)
421 .create(
422 this,
423 artifact.getGroupId(),
424 artifact.getArtifactId(),
425 artifact.getVersion().asString(),
426 artifact.getClassifier(),
427 artifact.getExtension(),
428 null);
429 }
430
431
432
433
434
435
436 @Override
437 public Artifact createArtifact(String groupId, String artifactId, String version, String extension) {
438 return getService(ArtifactFactory.class).create(this, groupId, artifactId, version, extension);
439 }
440
441
442
443
444
445
446 @Override
447 public Artifact createArtifact(
448 String groupId, String artifactId, String version, String classifier, String extension, String type) {
449 return getService(ArtifactFactory.class)
450 .create(this, groupId, artifactId, version, classifier, extension, type);
451 }
452
453
454
455
456
457
458
459 @Override
460 public Map.Entry<Artifact, Path> resolveArtifact(ArtifactCoordinate coordinate) {
461 return getService(ArtifactResolver.class)
462 .resolve(this, Collections.singletonList(coordinate))
463 .getArtifacts()
464 .entrySet()
465 .iterator()
466 .next();
467 }
468
469
470
471
472
473
474
475 @Override
476 public Map<Artifact, Path> resolveArtifacts(ArtifactCoordinate... coordinates) {
477 return resolveArtifacts(Arrays.asList(coordinates));
478 }
479
480
481
482
483
484
485
486 @Override
487 public Map<Artifact, Path> resolveArtifacts(Collection<? extends ArtifactCoordinate> coordinates) {
488 return getService(ArtifactResolver.class).resolve(this, coordinates).getArtifacts();
489 }
490
491
492
493
494
495
496
497 @Override
498 public Map.Entry<Artifact, Path> resolveArtifact(Artifact artifact) {
499 ArtifactCoordinate coordinate =
500 getService(ArtifactCoordinateFactory.class).create(this, artifact);
501 return resolveArtifact(coordinate);
502 }
503
504 @Override
505 public Map<Artifact, Path> resolveArtifacts(Artifact... artifacts) {
506 ArtifactCoordinateFactory acf = getService(ArtifactCoordinateFactory.class);
507 List<ArtifactCoordinate> coords =
508 Arrays.stream(artifacts).map(a -> acf.create(this, a)).collect(Collectors.toList());
509 return resolveArtifacts(coords);
510 }
511
512
513
514
515
516
517
518 @Override
519 public void installArtifacts(Artifact... artifacts) {
520 installArtifacts(Arrays.asList(artifacts));
521 }
522
523
524
525
526
527
528
529 @Override
530 public void installArtifacts(Collection<Artifact> artifacts) {
531 getService(ArtifactInstaller.class).install(this, artifacts);
532 }
533
534
535
536
537
538
539
540 @Override
541 public void deployArtifact(RemoteRepository repository, Artifact... artifacts) {
542 getService(ArtifactDeployer.class).deploy(this, repository, Arrays.asList(artifacts));
543 }
544
545
546
547
548
549
550 @Override
551 public void setArtifactPath(@Nonnull Artifact artifact, @Nonnull Path path) {
552 getService(ArtifactManager.class).setPath(artifact, path);
553 }
554
555
556
557
558
559
560 @Nonnull
561 @Override
562 public Optional<Path> getArtifactPath(@Nonnull Artifact artifact) {
563 return getService(ArtifactManager.class).getPath(artifact);
564 }
565
566
567
568
569
570
571 @Override
572 public boolean isVersionSnapshot(@Nonnull String version) {
573 return getService(VersionParser.class).isSnapshot(version);
574 }
575
576
577
578
579
580
581 @Nonnull
582 @Override
583 public DependencyCoordinate createDependencyCoordinate(@Nonnull ArtifactCoordinate coordinate) {
584 return getService(DependencyCoordinateFactory.class).create(this, coordinate);
585 }
586
587
588
589
590
591
592 @Nonnull
593 @Override
594 public DependencyCoordinate createDependencyCoordinate(@Nonnull Dependency dependency) {
595 return getService(DependencyCoordinateFactory.class).create(this, dependency);
596 }
597
598
599
600
601
602
603
604 @Nonnull
605 @Override
606 public Node collectDependencies(@Nonnull Artifact artifact) {
607 return getService(DependencyCollector.class).collect(this, artifact).getRoot();
608 }
609
610
611
612
613
614
615
616 @Nonnull
617 @Override
618 public Node collectDependencies(@Nonnull Project project) {
619 return getService(DependencyCollector.class).collect(this, project).getRoot();
620 }
621
622
623
624
625
626
627
628 @Nonnull
629 @Override
630 public Node collectDependencies(@Nonnull DependencyCoordinate dependency) {
631 return getService(DependencyCollector.class).collect(this, dependency).getRoot();
632 }
633
634 @Nonnull
635 @Override
636 public List<Node> flattenDependencies(@Nonnull Node node, @Nonnull PathScope scope) {
637 return getService(DependencyResolver.class).flatten(this, node, scope);
638 }
639
640 @Override
641 public List<Path> resolveDependencies(DependencyCoordinate dependency) {
642 return getService(DependencyResolver.class).resolve(this, dependency).getPaths();
643 }
644
645 @Override
646 public List<Path> resolveDependencies(List<DependencyCoordinate> dependencies) {
647 return getService(DependencyResolver.class).resolve(this, dependencies).getPaths();
648 }
649
650 @Override
651 public List<Path> resolveDependencies(Project project, PathScope scope) {
652 return getService(DependencyResolver.class)
653 .resolve(this, project, scope)
654 .getPaths();
655 }
656
657 @Override
658 public Map<PathType, List<Path>> resolveDependencies(
659 @Nonnull DependencyCoordinate dependency,
660 @Nonnull PathScope scope,
661 @Nonnull Collection<PathType> desiredTypes) {
662 return getService(DependencyResolver.class)
663 .resolve(DependencyResolverRequest.builder()
664 .session(this)
665 .dependency(dependency)
666 .pathScope(scope)
667 .pathTypeFilter(desiredTypes)
668 .build())
669 .getDispatchedPaths();
670 }
671
672 @Override
673 public Map<PathType, List<Path>> resolveDependencies(
674 @Nonnull Project project, @Nonnull PathScope scope, @Nonnull Collection<PathType> desiredTypes) {
675 return getService(DependencyResolver.class)
676 .resolve(DependencyResolverRequest.builder()
677 .session(this)
678 .project(project)
679 .pathScope(scope)
680 .pathTypeFilter(desiredTypes)
681 .build())
682 .getDispatchedPaths();
683 }
684
685 @Override
686 public Path getPathForLocalArtifact(@Nonnull Artifact artifact) {
687 return getService(LocalRepositoryManager.class).getPathForLocalArtifact(this, getLocalRepository(), artifact);
688 }
689
690 @Override
691 public Path getPathForRemoteArtifact(RemoteRepository remote, Artifact artifact) {
692 return getService(LocalRepositoryManager.class)
693 .getPathForRemoteArtifact(this, getLocalRepository(), remote, artifact);
694 }
695
696 @Override
697 public Version parseVersion(String version) {
698 return getService(VersionParser.class).parseVersion(version);
699 }
700
701 @Override
702 public VersionRange parseVersionRange(String versionRange) {
703 return getService(VersionParser.class).parseVersionRange(versionRange);
704 }
705
706 @Override
707 public VersionConstraint parseVersionConstraint(String versionConstraint) {
708 return getService(VersionParser.class).parseVersionConstraint(versionConstraint);
709 }
710
711 @Override
712 public Version resolveVersion(ArtifactCoordinate artifact) {
713 return getService(VersionResolver.class).resolve(this, artifact).getVersion();
714 }
715
716 @Override
717 public List<Version> resolveVersionRange(ArtifactCoordinate artifact) {
718 return getService(VersionRangeResolver.class).resolve(this, artifact).getVersions();
719 }
720
721 @Override
722 public Type requireType(String id) {
723 return getService(TypeRegistry.class).require(id);
724 }
725
726 @Override
727 public Language requireLanguage(String id) {
728 return getService(LanguageRegistry.class).require(id);
729 }
730
731 @Override
732 public Packaging requirePackaging(String id) {
733 return getService(PackagingRegistry.class).require(id);
734 }
735
736 @Override
737 public ProjectScope requireProjectScope(String id) {
738 return getService(ProjectScopeRegistry.class).require(id);
739 }
740
741 @Override
742 public DependencyScope requireDependencyScope(String id) {
743 return DependencyScope.forId(nonNull(id, "id"));
744 }
745
746 @Override
747 public PathScope requirePathScope(String id) {
748 return getService(PathScopeRegistry.class).require(id);
749 }
750 }