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