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,
159 "Could not collect dependencies for project " + project.getId(),
160 logger.isDebugEnabled() ? e : null);
161 }
162
163 depRequest.setRoot(node);
164
165 if (logger.isWarnEnabled()) {
166 for (DependencyNode child : node.getChildren()) {
167 if (!child.getRelocations().isEmpty()) {
168 org.eclipse.aether.artifact.Artifact relocated =
169 child.getDependency().getArtifact();
170 String message = relocated instanceof org.apache.maven.repository.internal.RelocatedArtifact
171 ? ((org.apache.maven.repository.internal.RelocatedArtifact) relocated).getMessage()
172 : null;
173 logger.warn("The artifact " + child.getRelocations().get(0) + " has been relocated to " + relocated
174 + (message != null ? ": " + message : ""));
175 }
176 }
177 }
178
179 if (logger.isDebugEnabled()) {
180 node.accept(new GraphLogger(project));
181 }
182
183 try {
184 process(result, repoSystem.resolveDependencies(session, depRequest).getArtifactResults());
185 } catch (org.eclipse.aether.resolution.DependencyResolutionException e) {
186 process(result, e.getResult().getArtifactResults());
187
188 throw new DependencyResolutionException(
189 result,
190 "Could not resolve dependencies for project " + project.getId(),
191 logger.isDebugEnabled() ? e : null);
192 }
193
194 return result;
195 }
196
197 private void process(DefaultDependencyResolutionResult result, Collection<ArtifactResult> results) {
198 for (ArtifactResult ar : results) {
199 DependencyNode node = ar.getRequest().getDependencyNode();
200 if (ar.isResolved()) {
201 result.addResolvedDependency(node.getDependency());
202 } else {
203 result.setResolutionErrors(node.getDependency(), ar.getExceptions());
204 }
205 }
206 }
207
208
209 class GraphLogger implements DependencyVisitor {
210
211 private final MavenProject project;
212
213 private String indent = "";
214
215 GraphLogger(MavenProject project) {
216 this.project = project;
217 }
218
219 public boolean visitEnter(DependencyNode node) {
220 StringBuilder buffer = new StringBuilder(128);
221 buffer.append(indent);
222 org.eclipse.aether.graph.Dependency dep = node.getDependency();
223 if (dep != null) {
224 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
225
226 buffer.append(art);
227 if (StringUtils.isNotEmpty(dep.getScope())) {
228 buffer.append(':').append(dep.getScope());
229 }
230
231 if (dep.isOptional()) {
232 buffer.append(" (optional)");
233 }
234
235
236
237
238 if ((node.getManagedBits() & DependencyNode.MANAGED_SCOPE) == DependencyNode.MANAGED_SCOPE) {
239 final String premanagedScope = DependencyManagerUtils.getPremanagedScope(node);
240 buffer.append(" (scope managed from ");
241 buffer.append(Objects.toString(premanagedScope, "default"));
242 buffer.append(')');
243 }
244
245 if ((node.getManagedBits() & DependencyNode.MANAGED_VERSION) == DependencyNode.MANAGED_VERSION) {
246 final String premanagedVersion = DependencyManagerUtils.getPremanagedVersion(node);
247 buffer.append(" (version managed from ");
248 buffer.append(Objects.toString(premanagedVersion, "default"));
249 buffer.append(')');
250 }
251
252 if ((node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) == DependencyNode.MANAGED_OPTIONAL) {
253 final Boolean premanagedOptional = DependencyManagerUtils.getPremanagedOptional(node);
254 buffer.append(" (optionality managed from ");
255 buffer.append(Objects.toString(premanagedOptional, "default"));
256 buffer.append(')');
257 }
258
259 if ((node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS) == DependencyNode.MANAGED_EXCLUSIONS) {
260 final Collection<org.eclipse.aether.graph.Exclusion> premanagedExclusions =
261 DependencyManagerUtils.getPremanagedExclusions(node);
262
263 buffer.append(" (exclusions managed from ");
264 buffer.append(Objects.toString(premanagedExclusions, "default"));
265 buffer.append(')');
266 }
267
268 if ((node.getManagedBits() & DependencyNode.MANAGED_PROPERTIES) == DependencyNode.MANAGED_PROPERTIES) {
269 final Map<String, String> premanagedProperties =
270 DependencyManagerUtils.getPremanagedProperties(node);
271
272 buffer.append(" (properties managed from ");
273 buffer.append(Objects.toString(premanagedProperties, "default"));
274 buffer.append(')');
275 }
276 } else {
277 buffer.append(project.getGroupId());
278 buffer.append(':').append(project.getArtifactId());
279 buffer.append(':').append(project.getPackaging());
280 buffer.append(':').append(project.getVersion());
281 }
282
283 logger.debug(buffer.toString());
284 indent += " ";
285 return true;
286 }
287
288 public boolean visitLeave(DependencyNode node) {
289 indent = indent.substring(0, indent.length() - 3);
290 return true;
291 }
292 }
293 }