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