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