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