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