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