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