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 java.util.Collection;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Objects;
26
27 import org.apache.maven.RepositoryUtils;
28 import org.apache.maven.artifact.Artifact;
29 import org.apache.maven.model.Dependency;
30 import org.apache.maven.model.DependencyManagement;
31 import org.apache.maven.model.Exclusion;
32 import org.codehaus.plexus.component.annotations.Component;
33 import org.codehaus.plexus.component.annotations.Requirement;
34 import org.codehaus.plexus.logging.Logger;
35 import org.codehaus.plexus.util.StringUtils;
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.graph.DependencyVisitor;
47 import org.eclipse.aether.resolution.ArtifactResult;
48 import org.eclipse.aether.resolution.DependencyRequest;
49 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
50 import org.eclipse.aether.util.artifact.JavaScopes;
51 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
52
53
54
55
56 @Component(role = ProjectDependenciesResolver.class)
57 public class DefaultProjectDependenciesResolver implements ProjectDependenciesResolver {
58
59 @Requirement
60 private Logger logger;
61
62 @Requirement
63 private RepositorySystem repoSystem;
64
65 @Requirement
66 private List<RepositorySessionDecorator> decorators;
67
68 public DependencyResolutionResult resolve(DependencyResolutionRequest request)
69 throws DependencyResolutionException {
70 final RequestTrace trace = RequestTrace.newChild(null, request);
71
72 final DefaultDependencyResolutionResult result = new DefaultDependencyResolutionResult();
73
74 final MavenProject project = request.getMavenProject();
75 final DependencyFilter filter = request.getResolutionFilter();
76 RepositorySystemSession session = request.getRepositorySession();
77 ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry();
78
79 if (logger.isDebugEnabled()
80 && session.getConfigProperties().get(DependencyManagerUtils.CONFIG_PROP_VERBOSE) == null) {
81 DefaultRepositorySystemSession verbose = new DefaultRepositorySystemSession(session);
82 verbose.setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, Boolean.TRUE);
83 session = verbose;
84 }
85
86 for (RepositorySessionDecorator decorator : decorators) {
87 RepositorySystemSession decorated = decorator.decorate(project, session);
88 if (decorated != null) {
89 session = decorated;
90 }
91 }
92
93 CollectRequest collect = new CollectRequest();
94 collect.setRootArtifact(RepositoryUtils.toArtifact(project.getArtifact()));
95 collect.setRequestContext("project");
96 collect.setRepositories(project.getRemoteProjectRepositories());
97
98 if (project.getDependencyArtifacts() == null) {
99 for (Dependency dependency : project.getDependencies()) {
100 if (StringUtils.isEmpty(dependency.getGroupId())
101 || StringUtils.isEmpty(dependency.getArtifactId())
102 || StringUtils.isEmpty(dependency.getVersion())) {
103
104 continue;
105 }
106 collect.addDependency(RepositoryUtils.toDependency(dependency, stereotypes));
107 }
108 } else {
109 Map<String, Dependency> dependencies = new HashMap<>();
110 for (Dependency dependency : project.getDependencies()) {
111 String classifier = dependency.getClassifier();
112 if (classifier == null) {
113 ArtifactType type = stereotypes.get(dependency.getType());
114 if (type != null) {
115 classifier = type.getClassifier();
116 }
117 }
118 String key = ArtifactIdUtils.toVersionlessId(
119 dependency.getGroupId(), dependency.getArtifactId(), dependency.getType(), classifier);
120 dependencies.put(key, dependency);
121 }
122 for (Artifact artifact : project.getDependencyArtifacts()) {
123 String key = artifact.getDependencyConflictId();
124 Dependency dependency = dependencies.get(key);
125 Collection<Exclusion> exclusions = dependency != null ? dependency.getExclusions() : null;
126 org.eclipse.aether.graph.Dependency dep = RepositoryUtils.toDependency(artifact, exclusions);
127 if (!JavaScopes.SYSTEM.equals(dep.getScope())
128 && dep.getArtifact().getFile() != null) {
129
130 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
131 art = art.setFile(null).setVersion(art.getBaseVersion());
132 dep = dep.setArtifact(art);
133 }
134 collect.addDependency(dep);
135 }
136 }
137
138 DependencyManagement depMgmt = project.getDependencyManagement();
139 if (depMgmt != null) {
140 for (Dependency dependency : depMgmt.getDependencies()) {
141 collect.addManagedDependency(RepositoryUtils.toDependency(dependency, stereotypes));
142 }
143 }
144
145 DependencyRequest depRequest = new DependencyRequest(collect, filter);
146 depRequest.setTrace(trace);
147
148 DependencyNode node;
149 try {
150 collect.setTrace(RequestTrace.newChild(trace, depRequest));
151 node = repoSystem.collectDependencies(session, collect).getRoot();
152 result.setDependencyGraph(node);
153 } catch (DependencyCollectionException e) {
154 result.setDependencyGraph(e.getResult().getRoot());
155 result.setCollectionErrors(e.getResult().getExceptions());
156
157 throw new DependencyResolutionException(
158 result, "Could not resolve dependencies for project " + project.getId() + ": " + e.getMessage(), e);
159 }
160
161 depRequest.setRoot(node);
162
163 if (logger.isWarnEnabled()) {
164 for (DependencyNode child : node.getChildren()) {
165 if (!child.getRelocations().isEmpty()) {
166 org.eclipse.aether.artifact.Artifact relocated =
167 child.getDependency().getArtifact();
168 String message = relocated instanceof org.apache.maven.repository.internal.RelocatedArtifact
169 ? ((org.apache.maven.repository.internal.RelocatedArtifact) relocated).getMessage()
170 : null;
171 logger.warn("The artifact " + child.getRelocations().get(0) + " has been relocated to " + relocated
172 + (message != null ? ": " + message : ""));
173 }
174 }
175 }
176
177 if (logger.isDebugEnabled()) {
178 node.accept(new GraphLogger(project));
179 }
180
181 try {
182 process(result, repoSystem.resolveDependencies(session, depRequest).getArtifactResults());
183 } catch (org.eclipse.aether.resolution.DependencyResolutionException e) {
184 process(result, e.getResult().getArtifactResults());
185
186 throw new DependencyResolutionException(
187 result, "Could not resolve dependencies for project " + project.getId() + ": " + e.getMessage(), e);
188 }
189
190 return result;
191 }
192
193 private void process(DefaultDependencyResolutionResult result, Collection<ArtifactResult> results) {
194 for (ArtifactResult ar : results) {
195 DependencyNode node = ar.getRequest().getDependencyNode();
196 if (ar.isResolved()) {
197 result.addResolvedDependency(node.getDependency());
198 } else {
199 result.setResolutionErrors(node.getDependency(), ar.getExceptions());
200 }
201 }
202 }
203
204
205 class GraphLogger implements DependencyVisitor {
206
207 private final MavenProject project;
208
209 private String indent = "";
210
211 GraphLogger(MavenProject project) {
212 this.project = project;
213 }
214
215 public boolean visitEnter(DependencyNode node) {
216 StringBuilder buffer = new StringBuilder(128);
217 buffer.append(indent);
218 org.eclipse.aether.graph.Dependency dep = node.getDependency();
219 if (dep != null) {
220 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
221
222 buffer.append(art);
223 if (StringUtils.isNotEmpty(dep.getScope())) {
224 buffer.append(':').append(dep.getScope());
225 }
226
227 if (dep.isOptional()) {
228 buffer.append(" (optional)");
229 }
230
231
232
233
234 if ((node.getManagedBits() & DependencyNode.MANAGED_SCOPE) == DependencyNode.MANAGED_SCOPE) {
235 final String premanagedScope = DependencyManagerUtils.getPremanagedScope(node);
236 buffer.append(" (scope managed from ");
237 buffer.append(Objects.toString(premanagedScope, "default"));
238 buffer.append(')');
239 }
240
241 if ((node.getManagedBits() & DependencyNode.MANAGED_VERSION) == DependencyNode.MANAGED_VERSION) {
242 final String premanagedVersion = DependencyManagerUtils.getPremanagedVersion(node);
243 buffer.append(" (version managed from ");
244 buffer.append(Objects.toString(premanagedVersion, "default"));
245 buffer.append(')');
246 }
247
248 if ((node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) == DependencyNode.MANAGED_OPTIONAL) {
249 final Boolean premanagedOptional = DependencyManagerUtils.getPremanagedOptional(node);
250 buffer.append(" (optionality managed from ");
251 buffer.append(Objects.toString(premanagedOptional, "default"));
252 buffer.append(')');
253 }
254
255 if ((node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS) == DependencyNode.MANAGED_EXCLUSIONS) {
256 final Collection<org.eclipse.aether.graph.Exclusion> premanagedExclusions =
257 DependencyManagerUtils.getPremanagedExclusions(node);
258
259 buffer.append(" (exclusions managed from ");
260 buffer.append(Objects.toString(premanagedExclusions, "default"));
261 buffer.append(')');
262 }
263
264 if ((node.getManagedBits() & DependencyNode.MANAGED_PROPERTIES) == DependencyNode.MANAGED_PROPERTIES) {
265 final Map<String, String> premanagedProperties =
266 DependencyManagerUtils.getPremanagedProperties(node);
267
268 buffer.append(" (properties managed from ");
269 buffer.append(Objects.toString(premanagedProperties, "default"));
270 buffer.append(')');
271 }
272 } else {
273 buffer.append(project.getGroupId());
274 buffer.append(':').append(project.getArtifactId());
275 buffer.append(':').append(project.getPackaging());
276 buffer.append(':').append(project.getVersion());
277 }
278
279 logger.debug(buffer.toString());
280 indent += " ";
281 return true;
282 }
283
284 public boolean visitLeave(DependencyNode node) {
285 indent = indent.substring(0, indent.length() - 3);
286 return true;
287 }
288 }
289 }