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(plugin, e);
133 }
134
135 try {
136 ArtifactRequest request = new ArtifactRequest(pluginArtifact, repositories, REPOSITORY_CONTEXT);
137 request.setTrace(trace);
138 pluginArtifact = repoSystem.resolveArtifact(session, request).getArtifact();
139 } catch (ArtifactResolutionException e) {
140 throw new PluginResolutionException(plugin, e);
141 }
142
143 return pluginArtifact;
144 }
145
146
147
148
149 public DependencyNode resolveCoreExtension(
150 Plugin plugin,
151 DependencyFilter dependencyFilter,
152 List<RemoteRepository> repositories,
153 RepositorySystemSession session)
154 throws PluginResolutionException {
155 return resolveInternal(plugin, null , dependencyFilter, repositories, session);
156 }
157
158 public DependencyNode resolve(
159 Plugin plugin,
160 Artifact pluginArtifact,
161 DependencyFilter dependencyFilter,
162 List<RemoteRepository> repositories,
163 RepositorySystemSession session)
164 throws PluginResolutionException {
165 return resolveInternal(plugin, pluginArtifact, dependencyFilter, repositories, session);
166 }
167
168 private DependencyNode resolveInternal(
169 Plugin plugin,
170 Artifact pluginArtifact,
171 DependencyFilter dependencyFilter,
172 List<RemoteRepository> repositories,
173 RepositorySystemSession session)
174 throws PluginResolutionException {
175 RequestTrace trace = RequestTrace.newChild(null, plugin);
176
177 if (pluginArtifact == null) {
178 pluginArtifact = toArtifact(plugin, session);
179 }
180
181 DependencyFilter collectionFilter = new ScopeDependencyFilter("provided", "test");
182 DependencyFilter resolutionFilter = AndDependencyFilter.newInstance(collectionFilter, dependencyFilter);
183
184 DependencyNode node;
185
186 try {
187 DependencySelector selector =
188 AndDependencySelector.newInstance(session.getDependencySelector(), new WagonExcluder());
189
190 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession(session);
191 pluginSession.setDependencySelector(selector);
192 pluginSession.setDependencyGraphTransformer(session.getDependencyGraphTransformer());
193
194 CollectRequest request = new CollectRequest();
195 request.setRequestContext(REPOSITORY_CONTEXT);
196 request.setRepositories(repositories);
197 request.setRoot(new org.eclipse.aether.graph.Dependency(pluginArtifact, null));
198 for (Dependency dependency : plugin.getDependencies()) {
199 org.eclipse.aether.graph.Dependency pluginDep =
200 RepositoryUtils.toDependency(dependency, session.getArtifactTypeRegistry());
201 if (!JavaScopes.SYSTEM.equals(pluginDep.getScope())) {
202 pluginDep = pluginDep.setScope(JavaScopes.RUNTIME);
203 }
204 request.addDependency(pluginDep);
205 }
206
207 DependencyRequest depRequest = new DependencyRequest(request, resolutionFilter);
208 depRequest.setTrace(trace);
209
210 request.setTrace(RequestTrace.newChild(trace, depRequest));
211
212 node = repoSystem.collectDependencies(pluginSession, request).getRoot();
213
214 if (logger.isDebugEnabled()) {
215 node.accept(new GraphLogger());
216 }
217
218 depRequest.setRoot(node);
219 repoSystem.resolveDependencies(session, depRequest);
220 } catch (DependencyCollectionException e) {
221 throw new PluginResolutionException(plugin, e);
222 } catch (DependencyResolutionException e) {
223 throw new PluginResolutionException(plugin, e.getCause());
224 }
225
226 return node;
227 }
228
229
230 class GraphLogger implements DependencyVisitor {
231
232 private String indent = "";
233
234 public boolean visitEnter(DependencyNode node) {
235 StringBuilder buffer = new StringBuilder(128);
236 buffer.append(indent);
237 org.eclipse.aether.graph.Dependency dep = node.getDependency();
238 if (dep != null) {
239 org.eclipse.aether.artifact.Artifact art = dep.getArtifact();
240
241 buffer.append(art);
242 if (StringUtils.isNotEmpty(dep.getScope())) {
243 buffer.append(':').append(dep.getScope());
244 }
245
246 if (dep.isOptional()) {
247 buffer.append(" (optional)");
248 }
249
250
251
252
253 if ((node.getManagedBits() & DependencyNode.MANAGED_SCOPE) == DependencyNode.MANAGED_SCOPE) {
254 final String premanagedScope = DependencyManagerUtils.getPremanagedScope(node);
255 buffer.append(" (scope managed from ");
256 buffer.append(Objects.toString(premanagedScope, "default"));
257 buffer.append(')');
258 }
259
260 if ((node.getManagedBits() & DependencyNode.MANAGED_VERSION) == DependencyNode.MANAGED_VERSION) {
261 final String premanagedVersion = DependencyManagerUtils.getPremanagedVersion(node);
262 buffer.append(" (version managed from ");
263 buffer.append(Objects.toString(premanagedVersion, "default"));
264 buffer.append(')');
265 }
266
267 if ((node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) == DependencyNode.MANAGED_OPTIONAL) {
268 final Boolean premanagedOptional = DependencyManagerUtils.getPremanagedOptional(node);
269 buffer.append(" (optionality managed from ");
270 buffer.append(Objects.toString(premanagedOptional, "default"));
271 buffer.append(')');
272 }
273
274 if ((node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS) == DependencyNode.MANAGED_EXCLUSIONS) {
275 final Collection<org.eclipse.aether.graph.Exclusion> premanagedExclusions =
276 DependencyManagerUtils.getPremanagedExclusions(node);
277
278 buffer.append(" (exclusions managed from ");
279 buffer.append(Objects.toString(premanagedExclusions, "default"));
280 buffer.append(')');
281 }
282
283 if ((node.getManagedBits() & DependencyNode.MANAGED_PROPERTIES) == DependencyNode.MANAGED_PROPERTIES) {
284 final Map<String, String> premanagedProperties =
285 DependencyManagerUtils.getPremanagedProperties(node);
286
287 buffer.append(" (properties managed from ");
288 buffer.append(Objects.toString(premanagedProperties, "default"));
289 buffer.append(')');
290 }
291 }
292
293 logger.debug(buffer.toString());
294 indent += " ";
295 return true;
296 }
297
298 public boolean visitLeave(DependencyNode node) {
299 indent = indent.substring(0, indent.length() - 3);
300 return true;
301 }
302 }
303 }