1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.internal;
20
21 import java.util.Collection;
22 import java.util.LinkedHashMap;
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.model.Dependency;
29 import org.apache.maven.model.Plugin;
30 import org.apache.maven.plugin.PluginResolutionException;
31 import org.codehaus.plexus.component.annotations.Component;
32 import org.codehaus.plexus.component.annotations.Requirement;
33 import org.codehaus.plexus.logging.Logger;
34 import org.codehaus.plexus.util.StringUtils;
35 import org.eclipse.aether.DefaultRepositorySystemSession;
36 import org.eclipse.aether.RepositorySystem;
37 import org.eclipse.aether.RepositorySystemSession;
38 import org.eclipse.aether.RequestTrace;
39 import org.eclipse.aether.artifact.Artifact;
40 import org.eclipse.aether.artifact.DefaultArtifact;
41 import org.eclipse.aether.collection.CollectRequest;
42 import org.eclipse.aether.collection.DependencyCollectionException;
43 import org.eclipse.aether.collection.DependencySelector;
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.repository.RemoteRepository;
48 import org.eclipse.aether.resolution.ArtifactDescriptorException;
49 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
50 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
51 import org.eclipse.aether.resolution.ArtifactRequest;
52 import org.eclipse.aether.resolution.ArtifactResolutionException;
53 import org.eclipse.aether.resolution.DependencyRequest;
54 import org.eclipse.aether.resolution.DependencyResolutionException;
55 import org.eclipse.aether.util.artifact.JavaScopes;
56 import org.eclipse.aether.util.filter.AndDependencyFilter;
57 import org.eclipse.aether.util.filter.ScopeDependencyFilter;
58 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
59 import org.eclipse.aether.util.graph.selector.AndDependencySelector;
60 import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy;
61
62
63
64
65
66
67
68
69
70 @Component(role = PluginDependenciesResolver.class)
71 public class DefaultPluginDependenciesResolver implements PluginDependenciesResolver {
72
73 private static final String REPOSITORY_CONTEXT = "plugin";
74
75 @Requirement
76 private Logger logger;
77
78 @Requirement
79 private RepositorySystem repoSystem;
80
81 @Requirement
82 private List<MavenPluginDependenciesValidator> dependenciesValidators;
83
84 private Artifact toArtifact(Plugin plugin, RepositorySystemSession session) {
85 return new DefaultArtifact(
86 plugin.getGroupId(),
87 plugin.getArtifactId(),
88 null,
89 "jar",
90 plugin.getVersion(),
91 session.getArtifactTypeRegistry().get("maven-plugin"));
92 }
93
94 public Artifact resolve(Plugin plugin, List<RemoteRepository> repositories, RepositorySystemSession session)
95 throws PluginResolutionException {
96 RequestTrace trace = RequestTrace.newChild(null, plugin);
97
98 Artifact pluginArtifact = toArtifact(plugin, session);
99
100 try {
101 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession(session);
102 pluginSession.setArtifactDescriptorPolicy(new SimpleArtifactDescriptorPolicy(true, false));
103
104 ArtifactDescriptorRequest request =
105 new ArtifactDescriptorRequest(pluginArtifact, repositories, REPOSITORY_CONTEXT);
106 request.setTrace(trace);
107 ArtifactDescriptorResult result = repoSystem.readArtifactDescriptor(pluginSession, request);
108
109 for (MavenPluginDependenciesValidator dependenciesValidator : dependenciesValidators) {
110 dependenciesValidator.validate(session, pluginArtifact, result);
111 }
112
113 pluginArtifact = result.getArtifact();
114
115 if (logger.isWarnEnabled()) {
116 if (!result.getRelocations().isEmpty()) {
117 String message = pluginArtifact instanceof org.apache.maven.repository.internal.RelocatedArtifact
118 ? ((org.apache.maven.repository.internal.RelocatedArtifact) pluginArtifact).getMessage()
119 : null;
120 logger.warn("The artifact " + result.getRelocations().get(0) + " has been relocated to "
121 + pluginArtifact + (message != null ? ": " + message : ""));
122 }
123 }
124
125 String requiredMavenVersion = (String) result.getProperties().get("prerequisites.maven");
126 if (requiredMavenVersion != null) {
127 Map<String, String> props = new LinkedHashMap<>(pluginArtifact.getProperties());
128 props.put("requiredMavenVersion", requiredMavenVersion);
129 pluginArtifact = pluginArtifact.setProperties(props);
130 }
131 } catch (ArtifactDescriptorException e) {
132 throw new PluginResolutionException(
133 plugin, e.getResult().getExceptions(), logger.isDebugEnabled() ? e : null);
134 }
135
136 try {
137 ArtifactRequest request = new ArtifactRequest(pluginArtifact, repositories, REPOSITORY_CONTEXT);
138 request.setTrace(trace);
139 pluginArtifact = repoSystem.resolveArtifact(session, request).getArtifact();
140 } catch (ArtifactResolutionException e) {
141 throw new PluginResolutionException(
142 plugin, e.getResult().getExceptions(), logger.isDebugEnabled() ? e : null);
143 }
144
145 return pluginArtifact;
146 }
147
148
149
150
151 public DependencyNode resolveCoreExtension(
152 Plugin plugin,
153 DependencyFilter dependencyFilter,
154 List<RemoteRepository> repositories,
155 RepositorySystemSession session)
156 throws PluginResolutionException {
157 return resolveInternal(plugin, null , dependencyFilter, repositories, session);
158 }
159
160 public DependencyNode resolve(
161 Plugin plugin,
162 Artifact pluginArtifact,
163 DependencyFilter dependencyFilter,
164 List<RemoteRepository> repositories,
165 RepositorySystemSession session)
166 throws PluginResolutionException {
167 return resolveInternal(plugin, pluginArtifact, dependencyFilter, repositories, session);
168 }
169
170 private DependencyNode resolveInternal(
171 Plugin plugin,
172 Artifact pluginArtifact,
173 DependencyFilter dependencyFilter,
174 List<RemoteRepository> repositories,
175 RepositorySystemSession session)
176 throws PluginResolutionException {
177 RequestTrace trace = RequestTrace.newChild(null, plugin);
178
179 if (pluginArtifact == null) {
180 pluginArtifact = toArtifact(plugin, session);
181 }
182
183 DependencyFilter collectionFilter = new ScopeDependencyFilter("provided", "test");
184 DependencyFilter resolutionFilter = AndDependencyFilter.newInstance(collectionFilter, dependencyFilter);
185
186 DependencyNode node;
187
188 try {
189 DependencySelector selector =
190 AndDependencySelector.newInstance(session.getDependencySelector(), new WagonExcluder());
191
192 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession(session);
193 pluginSession.setDependencySelector(selector);
194 pluginSession.setDependencyGraphTransformer(session.getDependencyGraphTransformer());
195
196 CollectRequest request = new CollectRequest();
197 request.setRequestContext(REPOSITORY_CONTEXT);
198 request.setRepositories(repositories);
199 request.setRoot(new org.eclipse.aether.graph.Dependency(pluginArtifact, null));
200 for (Dependency dependency : plugin.getDependencies()) {
201 org.eclipse.aether.graph.Dependency pluginDep =
202 RepositoryUtils.toDependency(dependency, session.getArtifactTypeRegistry());
203 if (!JavaScopes.SYSTEM.equals(pluginDep.getScope())) {
204 pluginDep = pluginDep.setScope(JavaScopes.RUNTIME);
205 }
206 request.addDependency(pluginDep);
207 }
208
209 DependencyRequest depRequest = new DependencyRequest(request, resolutionFilter);
210 depRequest.setTrace(trace);
211
212 request.setTrace(RequestTrace.newChild(trace, depRequest));
213
214 node = repoSystem.collectDependencies(pluginSession, request).getRoot();
215
216 if (logger.isDebugEnabled()) {
217 node.accept(new GraphLogger());
218 }
219
220 depRequest.setRoot(node);
221 repoSystem.resolveDependencies(session, depRequest);
222 } catch (DependencyCollectionException e) {
223 throw new PluginResolutionException(
224 plugin, e.getResult().getExceptions(), logger.isDebugEnabled() ? e : null);
225 } catch (DependencyResolutionException e) {
226 throw new PluginResolutionException(
227 plugin, e.getResult().getCollectExceptions(), logger.isDebugEnabled() ? e : null);
228 }
229
230 return node;
231 }
232
233
234 class GraphLogger implements DependencyVisitor {
235
236 private String indent = "";
237
238 public boolean visitEnter(DependencyNode node) {
239 StringBuilder buffer = new StringBuilder(128);
240 buffer.append(indent);
241 org.eclipse.aether.graph.Dependency dep = node.getDependency();
242 if (dep != null) {
243 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
244
245 buffer.append(art);
246 if (StringUtils.isNotEmpty(dep.getScope())) {
247 buffer.append(':').append(dep.getScope());
248 }
249
250 if (dep.isOptional()) {
251 buffer.append(" (optional)");
252 }
253
254
255
256
257 if ((node.getManagedBits() & DependencyNode.MANAGED_SCOPE) == DependencyNode.MANAGED_SCOPE) {
258 final String premanagedScope = DependencyManagerUtils.getPremanagedScope(node);
259 buffer.append(" (scope managed from ");
260 buffer.append(Objects.toString(premanagedScope, "default"));
261 buffer.append(')');
262 }
263
264 if ((node.getManagedBits() & DependencyNode.MANAGED_VERSION) == DependencyNode.MANAGED_VERSION) {
265 final String premanagedVersion = DependencyManagerUtils.getPremanagedVersion(node);
266 buffer.append(" (version managed from ");
267 buffer.append(Objects.toString(premanagedVersion, "default"));
268 buffer.append(')');
269 }
270
271 if ((node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) == DependencyNode.MANAGED_OPTIONAL) {
272 final Boolean premanagedOptional = DependencyManagerUtils.getPremanagedOptional(node);
273 buffer.append(" (optionality managed from ");
274 buffer.append(Objects.toString(premanagedOptional, "default"));
275 buffer.append(')');
276 }
277
278 if ((node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS) == DependencyNode.MANAGED_EXCLUSIONS) {
279 final Collection<org.eclipse.aether.graph.Exclusion> premanagedExclusions =
280 DependencyManagerUtils.getPremanagedExclusions(node);
281
282 buffer.append(" (exclusions managed from ");
283 buffer.append(Objects.toString(premanagedExclusions, "default"));
284 buffer.append(')');
285 }
286
287 if ((node.getManagedBits() & DependencyNode.MANAGED_PROPERTIES) == DependencyNode.MANAGED_PROPERTIES) {
288 final Map<String, String> premanagedProperties =
289 DependencyManagerUtils.getPremanagedProperties(node);
290
291 buffer.append(" (properties managed from ");
292 buffer.append(Objects.toString(premanagedProperties, "default"));
293 buffer.append(')');
294 }
295 }
296
297 logger.debug(buffer.toString());
298 indent += " ";
299 return true;
300 }
301
302 public boolean visitLeave(DependencyNode node) {
303 indent = indent.substring(0, indent.length() - 3);
304 return true;
305 }
306 }
307 }