1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.artifact.resolver;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.File;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.LinkedHashMap;
29 import java.util.LinkedHashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.concurrent.Executor;
35 import java.util.concurrent.ExecutorService;
36 import java.util.concurrent.LinkedBlockingQueue;
37 import java.util.concurrent.ThreadFactory;
38 import java.util.concurrent.ThreadPoolExecutor;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.atomic.AtomicInteger;
41 import java.util.regex.Matcher;
42
43 import org.apache.maven.RepositoryUtils;
44 import org.apache.maven.artifact.Artifact;
45 import org.apache.maven.artifact.factory.ArtifactFactory;
46 import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
47 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
48 import org.apache.maven.artifact.metadata.ResolutionGroup;
49 import org.apache.maven.artifact.repository.ArtifactRepository;
50 import org.apache.maven.artifact.repository.LegacyLocalRepositoryManager;
51 import org.apache.maven.artifact.repository.RepositoryRequest;
52 import org.apache.maven.artifact.repository.metadata.Snapshot;
53 import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
54 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
55 import org.apache.maven.execution.MavenSession;
56 import org.apache.maven.plugin.LegacySupport;
57 import org.apache.maven.repository.legacy.metadata.DefaultMetadataResolutionRequest;
58 import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest;
59 import org.apache.maven.repository.legacy.resolver.conflict.ConflictResolver;
60 import org.apache.maven.wagon.events.TransferListener;
61 import org.codehaus.plexus.PlexusContainer;
62 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
63 import org.codehaus.plexus.logging.Logger;
64 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
65 import org.eclipse.aether.RepositorySystem;
66 import org.eclipse.aether.RepositorySystemSession;
67 import org.eclipse.aether.repository.LocalRepositoryManager;
68 import org.eclipse.aether.resolution.ArtifactRequest;
69 import org.eclipse.aether.resolution.ArtifactResult;
70
71
72
73 @Named
74 @Singleton
75 @Deprecated
76 public class DefaultArtifactResolver implements ArtifactResolver, Disposable {
77 @Inject
78 private Logger logger;
79
80 @Inject
81 protected ArtifactFactory artifactFactory;
82
83 @Inject
84 private ArtifactCollector artifactCollector;
85
86 @Inject
87 private ResolutionErrorHandler resolutionErrorHandler;
88
89 @Inject
90 private ArtifactMetadataSource source;
91
92 @Inject
93 private PlexusContainer container;
94
95 @Inject
96 private LegacySupport legacySupport;
97
98 private final Executor executor;
99
100 public DefaultArtifactResolver() {
101 int threads = Integer.getInteger("maven.artifact.threads", 5);
102 if (threads <= 1) {
103 executor = Runnable::run;
104 } else {
105 executor = new ThreadPoolExecutor(
106 threads, threads, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), new DaemonThreadCreator());
107 }
108 }
109
110 private RepositorySystemSession getSession(ArtifactRepository localRepository) {
111 return LegacyLocalRepositoryManager.overlay(localRepository, legacySupport.getRepositorySession(), null);
112 }
113
114 private void injectSession1(RepositoryRequest request, MavenSession session) {
115 if (session != null) {
116 request.setOffline(session.isOffline());
117 request.setForceUpdate(session.getRequest().isUpdateSnapshots());
118 }
119 }
120
121 private void injectSession2(ArtifactResolutionRequest request, MavenSession session) {
122 injectSession1(request, session);
123
124 if (session != null) {
125 request.setServers(session.getRequest().getServers());
126 request.setMirrors(session.getRequest().getMirrors());
127 request.setProxies(session.getRequest().getProxies());
128 }
129 }
130
131 @Override
132 public void resolve(
133 Artifact artifact,
134 List<ArtifactRepository> remoteRepositories,
135 ArtifactRepository localRepository,
136 TransferListener resolutionListener)
137 throws ArtifactResolutionException, ArtifactNotFoundException {
138 resolve(artifact, remoteRepositories, getSession(localRepository));
139 }
140
141 @Override
142 public void resolveAlways(
143 Artifact artifact, List<ArtifactRepository> remoteRepositories, ArtifactRepository localRepository)
144 throws ArtifactResolutionException, ArtifactNotFoundException {
145 resolve(artifact, remoteRepositories, getSession(localRepository));
146 }
147
148 private void resolve(
149 Artifact artifact, List<ArtifactRepository> remoteRepositories, RepositorySystemSession session)
150 throws ArtifactResolutionException, ArtifactNotFoundException {
151 if (artifact == null) {
152 return;
153 }
154
155 if (Artifact.SCOPE_SYSTEM.equals(artifact.getScope())) {
156 File systemFile = artifact.getFile();
157
158 if (systemFile == null) {
159 throw new ArtifactNotFoundException("System artifact: " + artifact + " has no file attached", artifact);
160 }
161
162 if (!systemFile.exists()) {
163 throw new ArtifactNotFoundException(
164 "System artifact: " + artifact + " not found in path: " + systemFile, artifact);
165 }
166
167 if (!systemFile.isFile()) {
168 throw new ArtifactNotFoundException(
169 "System artifact: " + artifact + " is not a file: " + systemFile, artifact);
170 }
171
172 artifact.setResolved(true);
173
174 return;
175 }
176
177 if (!artifact.isResolved()) {
178 ArtifactResult result;
179
180 try {
181 ArtifactRequest artifactRequest = new ArtifactRequest();
182 artifactRequest.setArtifact(RepositoryUtils.toArtifact(artifact));
183 artifactRequest.setRepositories(RepositoryUtils.toRepos(remoteRepositories));
184
185
186 LocalRepositoryManager lrm = session.getLocalRepositoryManager();
187 String path = lrm.getPathForLocalArtifact(artifactRequest.getArtifact());
188 artifact.setFile(new File(lrm.getRepository().getBasedir(), path));
189
190 RepositorySystem repoSystem = container.lookup(RepositorySystem.class);
191 result = repoSystem.resolveArtifact(session, artifactRequest);
192 } catch (ComponentLookupException e) {
193 throw new IllegalStateException("Unable to lookup " + RepositorySystem.class.getName());
194 } catch (org.eclipse.aether.resolution.ArtifactResolutionException e) {
195 if (e.getCause() instanceof org.eclipse.aether.transfer.ArtifactNotFoundException) {
196 throw new ArtifactNotFoundException(e.getMessage(), artifact, remoteRepositories, e);
197 } else {
198 throw new ArtifactResolutionException(e.getMessage(), artifact, remoteRepositories, e);
199 }
200 }
201
202 artifact.selectVersion(result.getArtifact().getVersion());
203 artifact.setFile(result.getArtifact().getFile());
204 artifact.setResolved(true);
205
206 if (artifact.isSnapshot()) {
207 Matcher matcher = Artifact.VERSION_FILE_PATTERN.matcher(artifact.getVersion());
208 if (matcher.matches()) {
209 Snapshot snapshot = new Snapshot();
210 snapshot.setTimestamp(matcher.group(2));
211 try {
212 snapshot.setBuildNumber(Integer.parseInt(matcher.group(3)));
213 artifact.addMetadata(new SnapshotArtifactRepositoryMetadata(artifact, snapshot));
214 } catch (NumberFormatException e) {
215 logger.warn("Invalid artifact version " + artifact.getVersion() + ": " + e.getMessage());
216 }
217 }
218 }
219 }
220 }
221
222 @Override
223 public ArtifactResolutionResult resolveTransitively(
224 Set<Artifact> artifacts,
225 Artifact originatingArtifact,
226 ArtifactRepository localRepository,
227 List<ArtifactRepository> remoteRepositories,
228 ArtifactMetadataSource source,
229 ArtifactFilter filter)
230 throws ArtifactResolutionException, ArtifactNotFoundException {
231 return resolveTransitively(
232 artifacts,
233 originatingArtifact,
234 Collections.emptyMap(),
235 localRepository,
236 remoteRepositories,
237 source,
238 filter);
239 }
240
241 @Override
242 public ArtifactResolutionResult resolveTransitively(
243 Set<Artifact> artifacts,
244 Artifact originatingArtifact,
245 Map<String, Artifact> managedVersions,
246 ArtifactRepository localRepository,
247 List<ArtifactRepository> remoteRepositories,
248 ArtifactMetadataSource source)
249 throws ArtifactResolutionException, ArtifactNotFoundException {
250 return resolveTransitively(
251 artifacts, originatingArtifact, managedVersions, localRepository, remoteRepositories, source, null);
252 }
253
254 @Override
255 public ArtifactResolutionResult resolveTransitively(
256 Set<Artifact> artifacts,
257 Artifact originatingArtifact,
258 Map<String, Artifact> managedVersions,
259 ArtifactRepository localRepository,
260 List<ArtifactRepository> remoteRepositories,
261 ArtifactMetadataSource source,
262 ArtifactFilter filter)
263 throws ArtifactResolutionException, ArtifactNotFoundException {
264 return resolveTransitively(
265 artifacts,
266 originatingArtifact,
267 managedVersions,
268 localRepository,
269 remoteRepositories,
270 source,
271 filter,
272 null);
273 }
274
275 @Override
276 public ArtifactResolutionResult resolveTransitively(
277 Set<Artifact> artifacts,
278 Artifact originatingArtifact,
279 List<ArtifactRepository> remoteRepositories,
280 ArtifactRepository localRepository,
281 ArtifactMetadataSource source)
282 throws ArtifactResolutionException, ArtifactNotFoundException {
283 return resolveTransitively(artifacts, originatingArtifact, localRepository, remoteRepositories, source, null);
284 }
285
286 @Override
287 public ArtifactResolutionResult resolveTransitively(
288 Set<Artifact> artifacts,
289 Artifact originatingArtifact,
290 List<ArtifactRepository> remoteRepositories,
291 ArtifactRepository localRepository,
292 ArtifactMetadataSource source,
293 List<ResolutionListener> listeners)
294 throws ArtifactResolutionException, ArtifactNotFoundException {
295 return resolveTransitively(
296 artifacts,
297 originatingArtifact,
298 Collections.emptyMap(),
299 localRepository,
300 remoteRepositories,
301 source,
302 null,
303 listeners);
304 }
305
306 @Override
307 @SuppressWarnings("checkstyle:parameternumber")
308 public ArtifactResolutionResult resolveTransitively(
309 Set<Artifact> artifacts,
310 Artifact originatingArtifact,
311 Map<String, Artifact> managedVersions,
312 ArtifactRepository localRepository,
313 List<ArtifactRepository> remoteRepositories,
314 ArtifactMetadataSource source,
315 ArtifactFilter filter,
316 List<ResolutionListener> listeners)
317 throws ArtifactResolutionException, ArtifactNotFoundException {
318 return resolveTransitively(
319 artifacts,
320 originatingArtifact,
321 managedVersions,
322 localRepository,
323 remoteRepositories,
324 source,
325 filter,
326 listeners,
327 null);
328 }
329
330 @SuppressWarnings("checkstyle:parameternumber")
331 public ArtifactResolutionResult resolveTransitively(
332 Set<Artifact> artifacts,
333 Artifact originatingArtifact,
334 Map<String, Artifact> managedVersions,
335 ArtifactRepository localRepository,
336 List<ArtifactRepository> remoteRepositories,
337 ArtifactMetadataSource source,
338 ArtifactFilter filter,
339 List<ResolutionListener> listeners,
340 List<ConflictResolver> conflictResolvers)
341 throws ArtifactResolutionException, ArtifactNotFoundException {
342 ArtifactResolutionRequest request = new ArtifactResolutionRequest()
343 .setArtifact(originatingArtifact)
344 .setResolveRoot(false)
345 .
346
347 setArtifactDependencies(artifacts)
348 .setManagedVersionMap(managedVersions)
349 .setLocalRepository(localRepository)
350 .setRemoteRepositories(remoteRepositories)
351 .setCollectionFilter(filter)
352 .setListeners(listeners);
353
354 injectSession2(request, legacySupport.getSession());
355
356 return resolveWithExceptions(request);
357 }
358
359 public ArtifactResolutionResult resolveWithExceptions(ArtifactResolutionRequest request)
360 throws ArtifactResolutionException, ArtifactNotFoundException {
361 ArtifactResolutionResult result = resolve(request);
362
363
364
365
366
367 resolutionErrorHandler.throwErrors(request, result);
368
369 return result;
370 }
371
372
373
374
375
376 @Override
377 @SuppressWarnings("checkstyle:methodlength")
378 public ArtifactResolutionResult resolve(ArtifactResolutionRequest request) {
379 Artifact rootArtifact = request.getArtifact();
380 Set<Artifact> artifacts = request.getArtifactDependencies();
381 Map<String, Artifact> managedVersions = request.getManagedVersionMap();
382 List<ResolutionListener> listeners = request.getListeners();
383 ArtifactFilter collectionFilter = request.getCollectionFilter();
384 ArtifactFilter resolutionFilter = request.getResolutionFilter();
385 RepositorySystemSession session = getSession(request.getLocalRepository());
386
387
388
389 if (source == null) {
390 try {
391 source = container.lookup(ArtifactMetadataSource.class);
392 } catch (ComponentLookupException e) {
393
394 }
395 }
396
397 if (listeners == null) {
398 listeners = new ArrayList<>();
399
400 if (logger.isDebugEnabled()) {
401 listeners.add(new DebugResolutionListener(logger));
402 }
403
404 listeners.add(new WarningResolutionListener(logger));
405 }
406
407 ArtifactResolutionResult result = new ArtifactResolutionResult();
408
409
410
411
412
413
414 if (request.isResolveRoot() ) {
415 try {
416 resolve(rootArtifact, request.getRemoteRepositories(), session);
417 } catch (ArtifactResolutionException e) {
418 result.addErrorArtifactException(e);
419 return result;
420 } catch (ArtifactNotFoundException e) {
421 result.addMissingArtifact(request.getArtifact());
422 return result;
423 }
424 }
425
426 ArtifactResolutionRequest collectionRequest = request;
427
428 if (request.isResolveTransitively()) {
429 MetadataResolutionRequest metadataRequest = new DefaultMetadataResolutionRequest(request);
430
431 metadataRequest.setArtifact(rootArtifact);
432 metadataRequest.setResolveManagedVersions(managedVersions == null);
433
434 try {
435 ResolutionGroup resolutionGroup = source.retrieve(metadataRequest);
436
437 if (managedVersions == null) {
438 managedVersions = resolutionGroup.getManagedVersions();
439 }
440
441 Set<Artifact> directArtifacts = resolutionGroup.getArtifacts();
442
443 if (artifacts == null || artifacts.isEmpty()) {
444 artifacts = directArtifacts;
445 } else {
446 List<Artifact> allArtifacts = new ArrayList<>();
447 allArtifacts.addAll(artifacts);
448 allArtifacts.addAll(directArtifacts);
449
450 Map<String, Artifact> mergedArtifacts = new LinkedHashMap<>();
451 for (Artifact artifact : allArtifacts) {
452 String conflictId = artifact.getDependencyConflictId();
453 if (!mergedArtifacts.containsKey(conflictId)) {
454 mergedArtifacts.put(conflictId, artifact);
455 }
456 }
457
458 artifacts = new LinkedHashSet<>(mergedArtifacts.values());
459 }
460
461 collectionRequest = new ArtifactResolutionRequest(request);
462 collectionRequest.setServers(request.getServers());
463 collectionRequest.setMirrors(request.getMirrors());
464 collectionRequest.setProxies(request.getProxies());
465 collectionRequest.setRemoteRepositories(resolutionGroup.getResolutionRepositories());
466 } catch (ArtifactMetadataRetrievalException e) {
467 ArtifactResolutionException are = new ArtifactResolutionException(
468 "Unable to get dependency information for " + rootArtifact.getId() + ": " + e.getMessage(),
469 rootArtifact,
470 metadataRequest.getRemoteRepositories(),
471 e);
472 result.addMetadataResolutionException(are);
473 return result;
474 }
475 }
476
477 if (artifacts == null || artifacts.isEmpty()) {
478 if (request.isResolveRoot()) {
479 result.addArtifact(rootArtifact);
480 }
481 return result;
482 }
483
484
485 result = artifactCollector.collect(
486 artifacts, rootArtifact, managedVersions, collectionRequest, source, collectionFilter, listeners, null);
487
488
489
490
491
492 if (result.hasMetadataResolutionExceptions()
493 || result.hasVersionRangeViolations()
494 || result.hasCircularDependencyExceptions()) {
495 return result;
496 }
497
498 if (result.getArtifactResolutionNodes() != null) {
499 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
500
501 CountDownLatch latch =
502 new CountDownLatch(result.getArtifactResolutionNodes().size());
503
504 for (ResolutionNode node : result.getArtifactResolutionNodes()) {
505 Artifact artifact = node.getArtifact();
506
507 if (resolutionFilter == null || resolutionFilter.include(artifact)) {
508 executor.execute(new ResolveTask(
509 classLoader, latch, artifact, session, node.getRemoteRepositories(), result));
510 } else {
511 latch.countDown();
512 }
513 }
514 try {
515 latch.await();
516 } catch (InterruptedException e) {
517 result.addErrorArtifactException(
518 new ArtifactResolutionException("Resolution interrupted", rootArtifact, e));
519 }
520 }
521
522
523
524 if (request.isResolveRoot()) {
525
526 Set<Artifact> allArtifacts = new LinkedHashSet<>();
527 allArtifacts.add(rootArtifact);
528 allArtifacts.addAll(result.getArtifacts());
529 result.setArtifacts(allArtifacts);
530 }
531
532 return result;
533 }
534
535 @Override
536 public void resolve(
537 Artifact artifact, List<ArtifactRepository> remoteRepositories, ArtifactRepository localRepository)
538 throws ArtifactResolutionException, ArtifactNotFoundException {
539 resolve(artifact, remoteRepositories, localRepository, null);
540 }
541
542
543
544
545 @Deprecated
546 static final class DaemonThreadCreator implements ThreadFactory {
547 static final String THREADGROUP_NAME = "org.apache.maven.artifact.resolver.DefaultArtifactResolver";
548
549 static final ThreadGroup GROUP = new ThreadGroup(THREADGROUP_NAME);
550
551 static final AtomicInteger THREAD_NUMBER = new AtomicInteger(1);
552
553 @Override
554 public Thread newThread(Runnable r) {
555 Thread newThread = new Thread(GROUP, r, "resolver-" + THREAD_NUMBER.getAndIncrement());
556 newThread.setDaemon(true);
557 newThread.setContextClassLoader(null);
558 return newThread;
559 }
560 }
561
562 private class ResolveTask implements Runnable {
563
564 private final ClassLoader classLoader;
565
566 private final CountDownLatch latch;
567
568 private final Artifact artifact;
569
570 private final RepositorySystemSession session;
571
572 private final List<ArtifactRepository> remoteRepositories;
573
574 private final ArtifactResolutionResult result;
575
576 ResolveTask(
577 ClassLoader classLoader,
578 CountDownLatch latch,
579 Artifact artifact,
580 RepositorySystemSession session,
581 List<ArtifactRepository> remoteRepositories,
582 ArtifactResolutionResult result) {
583 this.classLoader = classLoader;
584 this.latch = latch;
585 this.artifact = artifact;
586 this.session = session;
587 this.remoteRepositories = remoteRepositories;
588 this.result = result;
589 }
590
591 @Override
592 public void run() {
593 ClassLoader old = Thread.currentThread().getContextClassLoader();
594 try {
595 Thread.currentThread().setContextClassLoader(classLoader);
596 resolve(artifact, remoteRepositories, session);
597 } catch (ArtifactNotFoundException anfe) {
598
599
600
601 synchronized (result) {
602 result.addMissingArtifact(artifact);
603 }
604 } catch (ArtifactResolutionException e) {
605
606
607
608 synchronized (result) {
609 result.addErrorArtifactException(e);
610 }
611 } finally {
612 latch.countDown();
613 Thread.currentThread().setContextClassLoader(old);
614 }
615 }
616 }
617
618 @Override
619 public void dispose() {
620 if (executor instanceof ExecutorService executorService) {
621 executorService.shutdownNow();
622 }
623 }
624 }