1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.prefix.internal;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.stream.Collectors;
29 import java.util.stream.Stream;
30
31 import org.apache.maven.artifact.repository.metadata.Metadata;
32 import org.apache.maven.artifact.repository.metadata.io.MetadataReader;
33 import org.apache.maven.model.Build;
34 import org.apache.maven.model.Model;
35 import org.apache.maven.model.Plugin;
36 import org.apache.maven.model.PluginManagement;
37 import org.apache.maven.plugin.BuildPluginManager;
38 import org.apache.maven.plugin.descriptor.PluginDescriptor;
39 import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
40 import org.apache.maven.plugin.prefix.PluginPrefixRequest;
41 import org.apache.maven.plugin.prefix.PluginPrefixResolver;
42 import org.apache.maven.plugin.prefix.PluginPrefixResult;
43 import org.codehaus.plexus.component.annotations.Component;
44 import org.codehaus.plexus.component.annotations.Requirement;
45 import org.codehaus.plexus.logging.Logger;
46 import org.eclipse.aether.DefaultRepositorySystemSession;
47 import org.eclipse.aether.RepositoryEvent;
48 import org.eclipse.aether.RepositoryEvent.EventType;
49 import org.eclipse.aether.RepositoryListener;
50 import org.eclipse.aether.RepositorySystem;
51 import org.eclipse.aether.RepositorySystemSession;
52 import org.eclipse.aether.RequestTrace;
53 import org.eclipse.aether.metadata.DefaultMetadata;
54 import org.eclipse.aether.repository.ArtifactRepository;
55 import org.eclipse.aether.repository.RemoteRepository;
56 import org.eclipse.aether.repository.RepositoryPolicy;
57 import org.eclipse.aether.resolution.MetadataRequest;
58 import org.eclipse.aether.resolution.MetadataResult;
59
60
61
62
63
64
65
66 @Component(role = PluginPrefixResolver.class)
67 public class DefaultPluginPrefixResolver implements PluginPrefixResolver {
68
69 private static final String REPOSITORY_CONTEXT = "plugin";
70
71 @Requirement
72 private Logger logger;
73
74 @Requirement
75 private BuildPluginManager pluginManager;
76
77 @Requirement
78 private RepositorySystem repositorySystem;
79
80 @Requirement
81 private MetadataReader metadataReader;
82
83 public PluginPrefixResult resolve(PluginPrefixRequest request) throws NoPluginFoundForPrefixException {
84 logger.debug("Resolving plugin prefix " + request.getPrefix() + " from " + request.getPluginGroups());
85
86 Model pom = request.getPom();
87 Build build = pom != null ? pom.getBuild() : null;
88 PluginManagement management = build != null ? build.getPluginManagement() : null;
89
90
91
92
93
94
95
96
97 LinkedHashMap<String, Set<String>> candidates = Stream.of(build, management)
98 .flatMap(container -> container != null ? container.getPlugins().stream() : Stream.empty())
99 .filter(p -> !request.getPluginGroups().contains(p.getGroupId()))
100 .collect(Collectors.groupingBy(
101 Plugin::getGroupId,
102 LinkedHashMap::new,
103 Collectors.mapping(Plugin::getArtifactId, Collectors.toSet())));
104 request.getPluginGroups().forEach(g -> candidates.put(g, null));
105 PluginPrefixResult result = resolveFromRepository(request, candidates);
106
107
108
109
110 if (result == null && build != null) {
111 result = resolveFromProject(request, build.getPlugins());
112 if (result == null && management != null) {
113 result = resolveFromProject(request, management.getPlugins());
114 }
115 }
116
117 if (result == null) {
118 throw new NoPluginFoundForPrefixException(
119 request.getPrefix(),
120 new ArrayList<>(candidates.keySet()),
121 request.getRepositorySession().getLocalRepository(),
122 request.getRepositories());
123 } else {
124 logger.debug("Resolved plugin prefix " + request.getPrefix() + " to " + result.getGroupId() + ":"
125 + result.getArtifactId() + " from repository "
126 + (result.getRepository() != null ? result.getRepository().getId() : "null"));
127 }
128
129 return result;
130 }
131
132 private PluginPrefixResult resolveFromProject(PluginPrefixRequest request, List<Plugin> plugins) {
133 for (Plugin plugin : plugins) {
134 try {
135 PluginDescriptor pluginDescriptor =
136 pluginManager.loadPlugin(plugin, request.getRepositories(), request.getRepositorySession());
137
138 if (request.getPrefix().equals(pluginDescriptor.getGoalPrefix())) {
139 return new DefaultPluginPrefixResult(plugin);
140 }
141 } catch (Exception e) {
142 if (logger.isDebugEnabled()) {
143 logger.warn(
144 "Failed to retrieve plugin descriptor for " + plugin.getId() + ": " + e.getMessage(), e);
145 } else {
146 logger.warn("Failed to retrieve plugin descriptor for " + plugin.getId() + ": " + e.getMessage());
147 }
148 }
149 }
150
151 return null;
152 }
153
154 private PluginPrefixResult resolveFromRepository(
155 PluginPrefixRequest request, LinkedHashMap<String, Set<String>> candidates) {
156 RequestTrace trace = RequestTrace.newChild(null, request);
157
158 List<MetadataRequest> requests = new ArrayList<>();
159
160 for (String pluginGroup : candidates.keySet()) {
161 org.eclipse.aether.metadata.Metadata metadata =
162 new DefaultMetadata(pluginGroup, "maven-metadata.xml", DefaultMetadata.Nature.RELEASE_OR_SNAPSHOT);
163
164 requests.add(new MetadataRequest(metadata, null, REPOSITORY_CONTEXT).setTrace(trace));
165
166 for (RemoteRepository repository : request.getRepositories()) {
167 requests.add(new MetadataRequest(metadata, repository, REPOSITORY_CONTEXT).setTrace(trace));
168 }
169 }
170
171
172
173 List<MetadataResult> results = repositorySystem.resolveMetadata(request.getRepositorySession(), requests);
174 requests.clear();
175
176 PluginPrefixResult result = processResults(request, trace, results, requests, candidates);
177
178 if (result != null) {
179 return result;
180 }
181
182
183
184 if (!request.getRepositorySession().isOffline() && !requests.isEmpty()) {
185 DefaultRepositorySystemSession session = new DefaultRepositorySystemSession(request.getRepositorySession());
186 session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS);
187
188 results = repositorySystem.resolveMetadata(session, requests);
189
190 return processResults(request, trace, results, null, candidates);
191 }
192
193 return null;
194 }
195
196 private PluginPrefixResult processResults(
197 PluginPrefixRequest request,
198 RequestTrace trace,
199 List<MetadataResult> results,
200 List<MetadataRequest> requests,
201 LinkedHashMap<String, Set<String>> candidates) {
202 for (MetadataResult res : results) {
203 org.eclipse.aether.metadata.Metadata metadata = res.getMetadata();
204
205 if (metadata != null) {
206 ArtifactRepository repository = res.getRequest().getRepository();
207 if (repository == null) {
208 repository = request.getRepositorySession().getLocalRepository();
209 }
210
211 PluginPrefixResult result =
212 resolveFromRepository(request, trace, metadata.getGroupId(), metadata, repository, candidates);
213
214 if (result != null) {
215 return result;
216 }
217 }
218
219 if (requests != null && !res.isUpdated()) {
220 requests.add(res.getRequest());
221 }
222 }
223
224 return null;
225 }
226
227 private PluginPrefixResult resolveFromRepository(
228 PluginPrefixRequest request,
229 RequestTrace trace,
230 String pluginGroup,
231 org.eclipse.aether.metadata.Metadata metadata,
232 ArtifactRepository repository,
233 LinkedHashMap<String, Set<String>> candidates) {
234 if (metadata != null && metadata.getFile() != null && metadata.getFile().isFile()) {
235 try {
236 Map<String, ?> options = Collections.singletonMap(MetadataReader.IS_STRICT, Boolean.FALSE);
237
238 Metadata pluginGroupMetadata = metadataReader.read(metadata.getFile(), options);
239
240 List<org.apache.maven.artifact.repository.metadata.Plugin> plugins = pluginGroupMetadata.getPlugins();
241
242 if (plugins != null) {
243 for (org.apache.maven.artifact.repository.metadata.Plugin plugin : plugins) {
244 if (request.getPrefix().equals(plugin.getPrefix())
245 && (candidates.get(pluginGroup) == null
246 || candidates.get(pluginGroup).contains(plugin.getArtifactId()))) {
247 return new DefaultPluginPrefixResult(pluginGroup, plugin.getArtifactId(), repository);
248 }
249 }
250 }
251 } catch (IOException e) {
252 invalidMetadata(request.getRepositorySession(), trace, metadata, repository, e);
253 }
254 }
255
256 return null;
257 }
258
259 private void invalidMetadata(
260 RepositorySystemSession session,
261 RequestTrace trace,
262 org.eclipse.aether.metadata.Metadata metadata,
263 ArtifactRepository repository,
264 Exception exception) {
265 RepositoryListener listener = session.getRepositoryListener();
266 if (listener != null) {
267 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INVALID);
268 event.setTrace(trace);
269 event.setMetadata(metadata);
270 event.setException(exception);
271 event.setRepository(repository);
272 listener.metadataInvalid(event.build());
273 }
274 }
275 }