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