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.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.stream.Collectors;
29 import java.util.stream.Stream;
30
31 import org.apache.maven.RepositoryUtils;
32 import org.apache.maven.api.DependencyScope;
33 import org.apache.maven.model.Dependency;
34 import org.apache.maven.model.Plugin;
35 import org.apache.maven.plugin.PluginResolutionException;
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.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.filter.AndDependencyFilter;
56 import org.eclipse.aether.util.filter.ScopeDependencyFilter;
57 import org.eclipse.aether.util.graph.visitor.DependencyGraphDumper;
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 =
120 pluginArtifact instanceof org.apache.maven.internal.impl.resolver.RelocatedArtifact relocated
121 ? ": " + relocated.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(
138 plugin, e.getResult().getExceptions(), logger.isDebugEnabled() ? e : null);
139 }
140
141 try {
142 ArtifactRequest request = new ArtifactRequest(pluginArtifact, repositories, REPOSITORY_CONTEXT);
143 request.setTrace(trace);
144 pluginArtifact = repoSystem.resolveArtifact(session, request).getArtifact();
145 } catch (ArtifactResolutionException e) {
146 throw new PluginResolutionException(
147 plugin, e.getResult().getExceptions(), logger.isDebugEnabled() ? e : null);
148 }
149
150 return pluginArtifact;
151 }
152
153
154
155
156 public DependencyResult resolveCoreExtension(
157 Plugin plugin,
158 DependencyFilter dependencyFilter,
159 List<RemoteRepository> repositories,
160 RepositorySystemSession session)
161 throws PluginResolutionException {
162 return resolveInternal(plugin, null , dependencyFilter, repositories, session);
163 }
164
165 public DependencyResult resolvePlugin(
166 Plugin plugin,
167 Artifact pluginArtifact,
168 DependencyFilter dependencyFilter,
169 List<RemoteRepository> repositories,
170 RepositorySystemSession session)
171 throws PluginResolutionException {
172 return resolveInternal(plugin, pluginArtifact, dependencyFilter, repositories, session);
173 }
174
175 public DependencyNode resolve(
176 Plugin plugin,
177 Artifact pluginArtifact,
178 DependencyFilter dependencyFilter,
179 List<RemoteRepository> repositories,
180 RepositorySystemSession session)
181 throws PluginResolutionException {
182 return resolveInternal(plugin, pluginArtifact, dependencyFilter, repositories, session)
183 .getRoot();
184 }
185
186 private DependencyResult resolveInternal(
187 Plugin plugin,
188 Artifact pluginArtifact,
189 DependencyFilter dependencyFilter,
190 List<RemoteRepository> repositories,
191 RepositorySystemSession session)
192 throws PluginResolutionException {
193 RequestTrace trace = RequestTrace.newChild(null, plugin);
194
195 if (pluginArtifact == null) {
196 pluginArtifact = toArtifact(plugin, session);
197 }
198
199 DependencyFilter collectionFilter = new ScopeDependencyFilter("provided", "test");
200 DependencyFilter resolutionFilter = AndDependencyFilter.newInstance(collectionFilter, dependencyFilter);
201
202 DependencyNode node;
203
204 try {
205 DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession(session);
206 pluginSession.setDependencySelector(session.getDependencySelector());
207 pluginSession.setDependencyGraphTransformer(session.getDependencyGraphTransformer());
208
209 CollectRequest request = new CollectRequest();
210 request.setRequestContext(REPOSITORY_CONTEXT);
211 request.setRepositories(repositories);
212 request.setRoot(new org.eclipse.aether.graph.Dependency(pluginArtifact, null));
213 for (Dependency dependency : plugin.getDependencies()) {
214 org.eclipse.aether.graph.Dependency pluginDep =
215 RepositoryUtils.toDependency(dependency, session.getArtifactTypeRegistry());
216 if (!DependencyScope.SYSTEM.is(pluginDep.getScope())) {
217 pluginDep = pluginDep.setScope(DependencyScope.RUNTIME.id());
218 }
219 request.addDependency(pluginDep);
220 }
221
222 DependencyRequest depRequest = new DependencyRequest(request, resolutionFilter);
223 depRequest.setTrace(trace);
224
225 request.setTrace(RequestTrace.newChild(trace, depRequest));
226
227 node = repoSystem.collectDependencies(pluginSession, request).getRoot();
228
229 if (logger.isDebugEnabled()) {
230 node.accept(new DependencyGraphDumper(logger::debug));
231 }
232
233 depRequest.setRoot(node);
234 return repoSystem.resolveDependencies(session, depRequest);
235 } catch (DependencyCollectionException e) {
236 throw new PluginResolutionException(
237 plugin, e.getResult().getExceptions(), logger.isDebugEnabled() ? e : null);
238 } catch (DependencyResolutionException e) {
239 List<Exception> exceptions = Stream.concat(
240 e.getResult().getCollectExceptions().stream(),
241 e.getResult().getArtifactResults().stream()
242 .filter(r -> !r.isResolved())
243 .flatMap(r -> r.getExceptions().stream()))
244 .collect(Collectors.toList());
245 throw new PluginResolutionException(plugin, exceptions, logger.isDebugEnabled() ? e : null);
246 }
247 }
248 }