1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.project;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import org.apache.maven.RepositoryUtils;
31 import org.apache.maven.api.DependencyScope;
32 import org.apache.maven.artifact.Artifact;
33 import org.apache.maven.model.Dependency;
34 import org.apache.maven.model.DependencyManagement;
35 import org.apache.maven.model.Exclusion;
36 import org.eclipse.aether.DefaultRepositorySystemSession;
37 import org.eclipse.aether.RepositorySystem;
38 import org.eclipse.aether.RepositorySystemSession;
39 import org.eclipse.aether.RequestTrace;
40 import org.eclipse.aether.artifact.ArtifactType;
41 import org.eclipse.aether.artifact.ArtifactTypeRegistry;
42 import org.eclipse.aether.collection.CollectRequest;
43 import org.eclipse.aether.collection.DependencyCollectionException;
44 import org.eclipse.aether.graph.DependencyFilter;
45 import org.eclipse.aether.graph.DependencyNode;
46 import org.eclipse.aether.resolution.ArtifactResult;
47 import org.eclipse.aether.resolution.DependencyRequest;
48 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
49 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
50 import org.eclipse.aether.util.graph.visitor.DependencyGraphDumper;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54
55
56 @Named
57 @Singleton
58 public class DefaultProjectDependenciesResolver implements ProjectDependenciesResolver {
59 private final Logger logger = LoggerFactory.getLogger(getClass());
60 private final RepositorySystem repoSystem;
61 private final List<RepositorySessionDecorator> decorators;
62
63 @Inject
64 public DefaultProjectDependenciesResolver(
65 RepositorySystem repoSystem, List<RepositorySessionDecorator> decorators) {
66 this.repoSystem = repoSystem;
67 this.decorators = decorators;
68 }
69
70 public DependencyResolutionResult resolve(DependencyResolutionRequest request)
71 throws DependencyResolutionException {
72 final RequestTrace trace = RequestTrace.newChild(null, request);
73
74 final DefaultDependencyResolutionResult result = new DefaultDependencyResolutionResult();
75
76 final MavenProject project = request.getMavenProject();
77 final DependencyFilter filter = request.getResolutionFilter();
78 RepositorySystemSession session = request.getRepositorySession();
79 ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry();
80
81 if (logger.isDebugEnabled()
82 && session.getConfigProperties().get(DependencyManagerUtils.CONFIG_PROP_VERBOSE) == null) {
83 DefaultRepositorySystemSession verbose = new DefaultRepositorySystemSession(session);
84 verbose.setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, Boolean.TRUE);
85 session = verbose;
86 }
87
88 for (RepositorySessionDecorator decorator : decorators) {
89 RepositorySystemSession decorated = decorator.decorate(project, session);
90 if (decorated != null) {
91 session = decorated;
92 }
93 }
94
95 CollectRequest collect = new CollectRequest();
96 collect.setRootArtifact(RepositoryUtils.toArtifact(project.getArtifact()));
97 collect.setRequestContext("project");
98 collect.setRepositories(project.getRemoteProjectRepositories());
99
100 if (project.getDependencyArtifacts() == null) {
101 for (Dependency dependency : project.getDependencies()) {
102 if (dependency.getGroupId() == null
103 || dependency.getGroupId().isEmpty()
104 || dependency.getArtifactId() == null
105 || dependency.getArtifactId().isEmpty()
106 || dependency.getVersion() == null
107 || dependency.getVersion().isEmpty()) {
108
109 continue;
110 }
111 collect.addDependency(RepositoryUtils.toDependency(dependency, stereotypes));
112 }
113 } else {
114 Map<String, Dependency> dependencies = new HashMap<>();
115 for (Dependency dependency : project.getDependencies()) {
116 String classifier = dependency.getClassifier();
117 if (classifier == null) {
118 ArtifactType type = stereotypes.get(dependency.getType());
119 if (type != null) {
120 classifier = type.getClassifier();
121 }
122 }
123 String key = ArtifactIdUtils.toVersionlessId(
124 dependency.getGroupId(), dependency.getArtifactId(), dependency.getType(), classifier);
125 dependencies.put(key, dependency);
126 }
127 for (Artifact artifact : project.getDependencyArtifacts()) {
128 String key = artifact.getDependencyConflictId();
129 Dependency dependency = dependencies.get(key);
130 Collection<Exclusion> exclusions = dependency != null ? dependency.getExclusions() : null;
131 org.eclipse.aether.graph.Dependency dep = RepositoryUtils.toDependency(artifact, exclusions);
132 if (!DependencyScope.SYSTEM.is(dep.getScope())
133 && dep.getArtifact().getFile() != null) {
134
135 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
136 art = art.setFile(null).setVersion(art.getBaseVersion());
137 dep = dep.setArtifact(art);
138 }
139 collect.addDependency(dep);
140 }
141 }
142
143 DependencyManagement depMgmt = project.getDependencyManagement();
144 if (depMgmt != null) {
145 for (Dependency dependency : depMgmt.getDependencies()) {
146 collect.addManagedDependency(RepositoryUtils.toDependency(dependency, stereotypes));
147 }
148 }
149
150 DependencyRequest depRequest = new DependencyRequest(collect, filter);
151 depRequest.setTrace(trace);
152
153 DependencyNode node;
154 try {
155 collect.setTrace(RequestTrace.newChild(trace, depRequest));
156 node = repoSystem.collectDependencies(session, collect).getRoot();
157 result.setDependencyGraph(node);
158 } catch (DependencyCollectionException e) {
159 result.setDependencyGraph(e.getResult().getRoot());
160 result.setCollectionErrors(e.getResult().getExceptions());
161
162 throw new DependencyResolutionException(
163 result,
164 "Could not collect dependencies for project " + project.getId(),
165 logger.isDebugEnabled() ? e : null);
166 }
167
168 depRequest.setRoot(node);
169
170 if (logger.isWarnEnabled()) {
171 for (DependencyNode child : node.getChildren()) {
172 if (!child.getRelocations().isEmpty()) {
173 org.eclipse.aether.artifact.Artifact artifact =
174 child.getDependency().getArtifact();
175 String message =
176 artifact instanceof org.apache.maven.internal.impl.resolver.RelocatedArtifact relocated
177 ? relocated.getMessage()
178 : null;
179 logger.warn("The artifact " + child.getRelocations().get(0) + " has been relocated to " + artifact
180 + (message != null ? ": " + message : ""));
181 }
182 }
183 }
184
185 if (logger.isDebugEnabled()) {
186 node.accept(new DependencyGraphDumper(logger::debug));
187 }
188
189 try {
190 process(result, repoSystem.resolveDependencies(session, depRequest).getArtifactResults());
191 } catch (org.eclipse.aether.resolution.DependencyResolutionException e) {
192 process(result, e.getResult().getArtifactResults());
193
194 throw new DependencyResolutionException(
195 result,
196 "Could not resolve dependencies for project " + project.getId(),
197 logger.isDebugEnabled() ? e : null);
198 }
199
200 return result;
201 }
202
203 private void process(DefaultDependencyResolutionResult result, Collection<ArtifactResult> results) {
204 for (ArtifactResult ar : results) {
205 DependencyNode node = ar.getRequest().getDependencyNode();
206 if (ar.isResolved()) {
207 result.addResolvedDependency(node.getDependency());
208 } else {
209 result.setResolutionErrors(node.getDependency(), ar.getExceptions());
210 }
211 }
212 }
213 }