1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.internal.impl;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collection;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Objects;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 import java.util.concurrent.atomic.AtomicInteger;
33 import java.util.function.Consumer;
34 import java.util.stream.Collectors;
35
36 import org.eclipse.aether.ConfigurationProperties;
37 import org.eclipse.aether.RepositorySystem;
38 import org.eclipse.aether.RepositorySystemSession;
39 import org.eclipse.aether.RequestTrace;
40 import org.eclipse.aether.SyncContext;
41 import org.eclipse.aether.artifact.Artifact;
42 import org.eclipse.aether.collection.CollectRequest;
43 import org.eclipse.aether.collection.CollectResult;
44 import org.eclipse.aether.collection.DependencyCollectionException;
45 import org.eclipse.aether.deployment.DeployRequest;
46 import org.eclipse.aether.deployment.DeployResult;
47 import org.eclipse.aether.deployment.DeploymentException;
48 import org.eclipse.aether.graph.DependencyFilter;
49 import org.eclipse.aether.graph.DependencyNode;
50 import org.eclipse.aether.graph.DependencyVisitor;
51 import org.eclipse.aether.impl.ArtifactDescriptorReader;
52 import org.eclipse.aether.impl.ArtifactResolver;
53 import org.eclipse.aether.impl.DependencyCollector;
54 import org.eclipse.aether.impl.Deployer;
55 import org.eclipse.aether.impl.Installer;
56 import org.eclipse.aether.impl.LocalRepositoryProvider;
57 import org.eclipse.aether.impl.MetadataResolver;
58 import org.eclipse.aether.impl.RemoteRepositoryManager;
59 import org.eclipse.aether.impl.RepositorySystemLifecycle;
60 import org.eclipse.aether.impl.VersionRangeResolver;
61 import org.eclipse.aether.impl.VersionResolver;
62 import org.eclipse.aether.installation.InstallRequest;
63 import org.eclipse.aether.installation.InstallResult;
64 import org.eclipse.aether.installation.InstallationException;
65 import org.eclipse.aether.internal.impl.session.DefaultSessionBuilder;
66 import org.eclipse.aether.repository.Authentication;
67 import org.eclipse.aether.repository.LocalRepository;
68 import org.eclipse.aether.repository.LocalRepositoryManager;
69 import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
70 import org.eclipse.aether.repository.Proxy;
71 import org.eclipse.aether.repository.RemoteRepository;
72 import org.eclipse.aether.resolution.ArtifactDescriptorException;
73 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
74 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
75 import org.eclipse.aether.resolution.ArtifactRequest;
76 import org.eclipse.aether.resolution.ArtifactResolutionException;
77 import org.eclipse.aether.resolution.ArtifactResult;
78 import org.eclipse.aether.resolution.DependencyRequest;
79 import org.eclipse.aether.resolution.DependencyResolutionException;
80 import org.eclipse.aether.resolution.DependencyResult;
81 import org.eclipse.aether.resolution.MetadataRequest;
82 import org.eclipse.aether.resolution.MetadataResult;
83 import org.eclipse.aether.resolution.VersionRangeRequest;
84 import org.eclipse.aether.resolution.VersionRangeResolutionException;
85 import org.eclipse.aether.resolution.VersionRangeResult;
86 import org.eclipse.aether.resolution.VersionRequest;
87 import org.eclipse.aether.resolution.VersionResolutionException;
88 import org.eclipse.aether.resolution.VersionResult;
89 import org.eclipse.aether.spi.artifact.decorator.ArtifactDecorator;
90 import org.eclipse.aether.spi.artifact.decorator.ArtifactDecoratorFactory;
91 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
92 import org.eclipse.aether.util.ConfigUtils;
93 import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor;
94 import org.eclipse.aether.util.graph.visitor.LevelOrderDependencyNodeConsumerVisitor;
95 import org.eclipse.aether.util.graph.visitor.PostorderDependencyNodeConsumerVisitor;
96 import org.eclipse.aether.util.graph.visitor.PreorderDependencyNodeConsumerVisitor;
97 import org.eclipse.aether.util.repository.ChainedLocalRepositoryManager;
98
99 import static java.util.Objects.requireNonNull;
100 import static java.util.stream.Collectors.toList;
101
102
103
104
105 @Singleton
106 @Named
107 public class DefaultRepositorySystem implements RepositorySystem {
108 private final AtomicBoolean shutdown;
109
110 private final AtomicInteger sessionIdCounter;
111
112 private final VersionResolver versionResolver;
113
114 private final VersionRangeResolver versionRangeResolver;
115
116 private final ArtifactResolver artifactResolver;
117
118 private final MetadataResolver metadataResolver;
119
120 private final ArtifactDescriptorReader artifactDescriptorReader;
121
122 private final DependencyCollector dependencyCollector;
123
124 private final Installer installer;
125
126 private final Deployer deployer;
127
128 private final LocalRepositoryProvider localRepositoryProvider;
129
130 private final SyncContextFactory syncContextFactory;
131
132 private final RemoteRepositoryManager remoteRepositoryManager;
133
134 private final RepositorySystemLifecycle repositorySystemLifecycle;
135
136 protected final Map<String, ArtifactDecoratorFactory> artifactDecoratorFactories;
137
138 @SuppressWarnings("checkstyle:parameternumber")
139 @Inject
140 public DefaultRepositorySystem(
141 VersionResolver versionResolver,
142 VersionRangeResolver versionRangeResolver,
143 ArtifactResolver artifactResolver,
144 MetadataResolver metadataResolver,
145 ArtifactDescriptorReader artifactDescriptorReader,
146 DependencyCollector dependencyCollector,
147 Installer installer,
148 Deployer deployer,
149 LocalRepositoryProvider localRepositoryProvider,
150 SyncContextFactory syncContextFactory,
151 RemoteRepositoryManager remoteRepositoryManager,
152 RepositorySystemLifecycle repositorySystemLifecycle,
153 Map<String, ArtifactDecoratorFactory> artifactDecoratorFactories) {
154 this.shutdown = new AtomicBoolean(false);
155 this.sessionIdCounter = new AtomicInteger(0);
156 this.versionResolver = requireNonNull(versionResolver, "version resolver cannot be null");
157 this.versionRangeResolver = requireNonNull(versionRangeResolver, "version range resolver cannot be null");
158 this.artifactResolver = requireNonNull(artifactResolver, "artifact resolver cannot be null");
159 this.metadataResolver = requireNonNull(metadataResolver, "metadata resolver cannot be null");
160 this.artifactDescriptorReader =
161 requireNonNull(artifactDescriptorReader, "artifact descriptor reader cannot be null");
162 this.dependencyCollector = requireNonNull(dependencyCollector, "dependency collector cannot be null");
163 this.installer = requireNonNull(installer, "installer cannot be null");
164 this.deployer = requireNonNull(deployer, "deployer cannot be null");
165 this.localRepositoryProvider =
166 requireNonNull(localRepositoryProvider, "local repository provider cannot be null");
167 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null");
168 this.remoteRepositoryManager =
169 requireNonNull(remoteRepositoryManager, "remote repository provider cannot be null");
170 this.repositorySystemLifecycle =
171 requireNonNull(repositorySystemLifecycle, "repository system lifecycle cannot be null");
172 this.artifactDecoratorFactories =
173 requireNonNull(artifactDecoratorFactories, "artifact decorator factories cannot be null");
174 }
175
176 @Override
177 public VersionResult resolveVersion(RepositorySystemSession session, VersionRequest request)
178 throws VersionResolutionException {
179 validateSession(session);
180 requireNonNull(request, "request cannot be null");
181
182 return versionResolver.resolveVersion(session, request);
183 }
184
185 @Override
186 public VersionRangeResult resolveVersionRange(RepositorySystemSession session, VersionRangeRequest request)
187 throws VersionRangeResolutionException {
188 validateSession(session);
189 requireNonNull(request, "request cannot be null");
190
191 return versionRangeResolver.resolveVersionRange(session, request);
192 }
193
194 @Override
195 public ArtifactDescriptorResult readArtifactDescriptor(
196 RepositorySystemSession session, ArtifactDescriptorRequest request) throws ArtifactDescriptorException {
197 validateSession(session);
198 requireNonNull(request, "request cannot be null");
199
200 ArtifactDescriptorResult descriptorResult = artifactDescriptorReader.readArtifactDescriptor(session, request);
201 for (ArtifactDecorator decorator : Utils.getArtifactDecorators(session, artifactDecoratorFactories)) {
202 descriptorResult.setArtifact(decorator.decorateArtifact(descriptorResult));
203 }
204 return descriptorResult;
205 }
206
207 @Override
208 public ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request)
209 throws ArtifactResolutionException {
210 validateSession(session);
211 requireNonNull(request, "request cannot be null");
212
213 return artifactResolver.resolveArtifact(session, request);
214 }
215
216 @Override
217 public List<ArtifactResult> resolveArtifacts(
218 RepositorySystemSession session, Collection<? extends ArtifactRequest> requests)
219 throws ArtifactResolutionException {
220 validateSession(session);
221 requireNonNull(requests, "requests cannot be null");
222
223 return artifactResolver.resolveArtifacts(session, requests);
224 }
225
226 @Override
227 public List<MetadataResult> resolveMetadata(
228 RepositorySystemSession session, Collection<? extends MetadataRequest> requests) {
229 validateSession(session);
230 requireNonNull(requests, "requests cannot be null");
231
232 return metadataResolver.resolveMetadata(session, requests);
233 }
234
235 @Override
236 public CollectResult collectDependencies(RepositorySystemSession session, CollectRequest request)
237 throws DependencyCollectionException {
238 validateSession(session);
239 requireNonNull(request, "request cannot be null");
240
241 return dependencyCollector.collectDependencies(session, request);
242 }
243
244 @Override
245 public DependencyResult resolveDependencies(RepositorySystemSession session, DependencyRequest request)
246 throws DependencyResolutionException {
247 validateSession(session);
248 requireNonNull(request, "request cannot be null");
249
250 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
251
252 DependencyResult result = new DependencyResult(request);
253
254 DependencyCollectionException dce = null;
255 ArtifactResolutionException are = null;
256
257 if (request.getRoot() != null) {
258 result.setRoot(request.getRoot());
259 } else if (request.getCollectRequest() != null) {
260 CollectResult collectResult;
261 try {
262 request.getCollectRequest().setTrace(trace);
263 collectResult = dependencyCollector.collectDependencies(session, request.getCollectRequest());
264 } catch (DependencyCollectionException e) {
265 dce = e;
266 collectResult = e.getResult();
267 }
268 result.setRoot(collectResult.getRoot());
269 result.setCycles(collectResult.getCycles());
270 result.setCollectExceptions(collectResult.getExceptions());
271 } else {
272 throw new NullPointerException("dependency node and collect request cannot be null");
273 }
274
275 final List<DependencyNode> dependencyNodes =
276 doFlattenDependencyNodes(session, result.getRoot(), request.getFilter());
277
278 final List<ArtifactRequest> requests = dependencyNodes.stream()
279 .map(n -> {
280 if (n.getDependency() != null) {
281 ArtifactRequest artifactRequest = new ArtifactRequest(n);
282 artifactRequest.setTrace(trace);
283 return artifactRequest;
284 } else {
285 return null;
286 }
287 })
288 .filter(Objects::nonNull)
289 .collect(Collectors.toList());
290 List<ArtifactResult> results;
291 try {
292 results = artifactResolver.resolveArtifacts(session, requests);
293 } catch (ArtifactResolutionException e) {
294 are = e;
295 results = e.getResults();
296 }
297 result.setDependencyNodeResults(dependencyNodes);
298 result.setArtifactResults(results);
299
300 updateNodesWithResolvedArtifacts(results);
301
302 if (dce != null) {
303 throw new DependencyResolutionException(result, dce);
304 } else if (are != null) {
305 throw new DependencyResolutionException(result, are);
306 }
307
308 return result;
309 }
310
311 @Override
312 public List<DependencyNode> flattenDependencyNodes(
313 RepositorySystemSession session, DependencyNode root, DependencyFilter dependencyFilter) {
314 validateSession(session);
315 requireNonNull(root, "root cannot be null");
316
317 return doFlattenDependencyNodes(session, root, dependencyFilter);
318 }
319
320 private List<DependencyNode> doFlattenDependencyNodes(
321 RepositorySystemSession session, DependencyNode root, DependencyFilter dependencyFilter) {
322 final ArrayList<DependencyNode> dependencyNodes = new ArrayList<>();
323 if (root != null) {
324 DependencyVisitor builder = getDependencyVisitor(session, dependencyNodes::add);
325 DependencyVisitor visitor =
326 (dependencyFilter != null) ? new FilteringDependencyVisitor(builder, dependencyFilter) : builder;
327 root.accept(visitor);
328 }
329 return dependencyNodes;
330 }
331
332 private DependencyVisitor getDependencyVisitor(
333 RepositorySystemSession session, Consumer<DependencyNode> nodeConsumer) {
334 String strategy = ConfigUtils.getString(
335 session,
336 ConfigurationProperties.REPOSITORY_SYSTEM_DEPENDENCY_VISITOR_PREORDER,
337 ConfigurationProperties.REPOSITORY_SYSTEM_DEPENDENCY_VISITOR);
338 switch (strategy) {
339 case PreorderDependencyNodeConsumerVisitor.NAME:
340 return new PreorderDependencyNodeConsumerVisitor(nodeConsumer);
341 case PostorderDependencyNodeConsumerVisitor.NAME:
342 return new PostorderDependencyNodeConsumerVisitor(nodeConsumer);
343 case LevelOrderDependencyNodeConsumerVisitor.NAME:
344 return new LevelOrderDependencyNodeConsumerVisitor(nodeConsumer);
345 default:
346 throw new IllegalArgumentException("Invalid dependency visitor strategy: " + strategy);
347 }
348 }
349
350 private void updateNodesWithResolvedArtifacts(List<ArtifactResult> results) {
351 for (ArtifactResult result : results) {
352 Artifact artifact = result.getArtifact();
353 if (artifact != null) {
354 result.getRequest().getDependencyNode().setArtifact(artifact);
355 }
356 }
357 }
358
359 @Override
360 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException {
361 validateSession(session);
362 requireNonNull(request, "request cannot be null");
363
364 return installer.install(session, request);
365 }
366
367 @Override
368 public DeployResult deploy(RepositorySystemSession session, DeployRequest request) throws DeploymentException {
369 validateSession(session);
370 requireNonNull(request, "request cannot be null");
371
372 return deployer.deploy(session, request);
373 }
374
375 @Override
376 public LocalRepositoryManager newLocalRepositoryManager(
377 RepositorySystemSession session, LocalRepository localRepository) {
378 requireNonNull(session, "session cannot be null");
379 requireNonNull(localRepository, "localRepository cannot be null");
380 validateSystem();
381
382 return createLocalRepositoryManager(session, localRepository);
383 }
384
385 @Override
386 public LocalRepositoryManager newLocalRepositoryManager(
387 RepositorySystemSession session, LocalRepository... localRepositories) {
388 requireNonNull(session, "session cannot be null");
389 requireNonNull(localRepositories, "localRepositories cannot be null");
390 validateSystem();
391
392 return createLocalRepositoryManager(session, Arrays.asList(localRepositories));
393 }
394
395 @Override
396 public LocalRepositoryManager newLocalRepositoryManager(
397 RepositorySystemSession session, List<LocalRepository> localRepositories) {
398 requireNonNull(session, "session cannot be null");
399 requireNonNull(localRepositories, "localRepositories cannot be null");
400 validateSystem();
401
402 return createLocalRepositoryManager(session, localRepositories);
403 }
404
405 private LocalRepositoryManager createLocalRepositoryManager(
406 RepositorySystemSession session, List<LocalRepository> localRepositories) {
407 if (localRepositories.isEmpty()) {
408 throw new IllegalArgumentException("empty localRepositories");
409 } else if (localRepositories.size() == 1) {
410 return createLocalRepositoryManager(session, localRepositories.get(0));
411 } else {
412 LocalRepositoryManager head = createLocalRepositoryManager(session, localRepositories.get(0));
413 List<LocalRepositoryManager> tail = localRepositories.subList(1, localRepositories.size()).stream()
414 .map(l -> createLocalRepositoryManager(session, l))
415 .collect(toList());
416 return new ChainedLocalRepositoryManager(head, tail, session);
417 }
418 }
419
420 private LocalRepositoryManager createLocalRepositoryManager(
421 RepositorySystemSession session, LocalRepository localRepository) {
422 try {
423 return localRepositoryProvider.newLocalRepositoryManager(session, localRepository);
424 } catch (NoLocalRepositoryManagerException e) {
425 throw new IllegalArgumentException(e.getMessage(), e);
426 }
427 }
428
429 @Override
430 public SyncContext newSyncContext(RepositorySystemSession session, boolean shared) {
431 validateSession(session);
432 return syncContextFactory.newInstance(session, shared);
433 }
434
435 @Override
436 public List<RemoteRepository> newResolutionRepositories(
437 RepositorySystemSession session, List<RemoteRepository> repositories) {
438 validateSession(session);
439 validateRepositories(repositories);
440
441 repositories = remoteRepositoryManager.aggregateRepositories(session, new ArrayList<>(), repositories, true);
442 return repositories;
443 }
444
445 @Override
446 public RemoteRepository newDeploymentRepository(RepositorySystemSession session, RemoteRepository repository) {
447 validateSession(session);
448 requireNonNull(repository, "repository cannot be null");
449
450 RemoteRepository.Builder builder = new RemoteRepository.Builder(repository);
451 Authentication auth = session.getAuthenticationSelector().getAuthentication(repository);
452 builder.setAuthentication(auth);
453 Proxy proxy = session.getProxySelector().getProxy(repository);
454 builder.setProxy(proxy);
455 return builder.build();
456 }
457
458 @Override
459 public void addOnSystemEndedHandler(Runnable handler) {
460 validateSystem();
461 repositorySystemLifecycle.addOnSystemEndedHandler(handler);
462 }
463
464 @Override
465 public RepositorySystemSession.SessionBuilder createSessionBuilder() {
466 validateSystem();
467 return new DefaultSessionBuilder(
468 this, repositorySystemLifecycle, () -> "id-" + sessionIdCounter.incrementAndGet());
469 }
470
471 @Override
472 public void shutdown() {
473 if (shutdown.compareAndSet(false, true)) {
474 repositorySystemLifecycle.systemEnded();
475 }
476 }
477
478 private void validateSession(RepositorySystemSession session) {
479 requireNonNull(session, "repository system session cannot be null");
480 invalidSession(session.getLocalRepositoryManager(), "local repository manager");
481 invalidSession(session.getSystemProperties(), "system properties");
482 invalidSession(session.getUserProperties(), "user properties");
483 invalidSession(session.getConfigProperties(), "config properties");
484 invalidSession(session.getMirrorSelector(), "mirror selector");
485 invalidSession(session.getProxySelector(), "proxy selector");
486 invalidSession(session.getAuthenticationSelector(), "authentication selector");
487 invalidSession(session.getArtifactTypeRegistry(), "artifact type registry");
488 invalidSession(session.getData(), "data");
489 validateSystem();
490 }
491
492 private void validateSystem() {
493 if (shutdown.get()) {
494 throw new IllegalStateException("repository system is already shut down");
495 }
496 }
497
498 private void validateRepositories(List<RemoteRepository> repositories) {
499 requireNonNull(repositories, "repositories cannot be null");
500 for (RemoteRepository repository : repositories) {
501 requireNonNull(repository, "repository cannot be null");
502 }
503 }
504
505 private void invalidSession(Object obj, String name) {
506 requireNonNull(obj, "repository system session's " + name + " cannot be null");
507 }
508 }