1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.repository.internal;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.util.LinkedHashSet;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Properties;
29 import java.util.Set;
30
31 import org.apache.maven.model.DistributionManagement;
32 import org.apache.maven.model.Model;
33 import org.apache.maven.model.Relocation;
34 import org.apache.maven.model.building.DefaultModelBuilderFactory;
35 import org.apache.maven.model.building.DefaultModelBuildingRequest;
36 import org.apache.maven.model.building.FileModelSource;
37 import org.apache.maven.model.building.ModelBuilder;
38 import org.apache.maven.model.building.ModelBuildingException;
39 import org.apache.maven.model.building.ModelBuildingRequest;
40 import org.apache.maven.model.building.ModelProblem;
41 import org.apache.maven.model.resolution.UnresolvableModelException;
42 import org.eclipse.aether.RepositoryEvent;
43 import org.eclipse.aether.RepositoryEvent.EventType;
44 import org.eclipse.aether.RepositoryException;
45 import org.eclipse.aether.RepositorySystemSession;
46 import org.eclipse.aether.RequestTrace;
47 import org.eclipse.aether.artifact.Artifact;
48 import org.eclipse.aether.impl.ArtifactDescriptorReader;
49 import org.eclipse.aether.impl.ArtifactResolver;
50 import org.eclipse.aether.impl.RemoteRepositoryManager;
51 import org.eclipse.aether.impl.RepositoryEventDispatcher;
52 import org.eclipse.aether.impl.VersionRangeResolver;
53 import org.eclipse.aether.impl.VersionResolver;
54 import org.eclipse.aether.repository.WorkspaceReader;
55 import org.eclipse.aether.repository.WorkspaceRepository;
56 import org.eclipse.aether.resolution.ArtifactDescriptorException;
57 import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
58 import org.eclipse.aether.resolution.ArtifactDescriptorPolicyRequest;
59 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
60 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
61 import org.eclipse.aether.resolution.ArtifactRequest;
62 import org.eclipse.aether.resolution.ArtifactResolutionException;
63 import org.eclipse.aether.resolution.ArtifactResult;
64 import org.eclipse.aether.resolution.VersionRequest;
65 import org.eclipse.aether.resolution.VersionResolutionException;
66 import org.eclipse.aether.resolution.VersionResult;
67 import org.eclipse.aether.spi.locator.Service;
68 import org.eclipse.aether.spi.locator.ServiceLocator;
69 import org.eclipse.aether.transfer.ArtifactNotFoundException;
70
71
72
73
74 @Named
75 @Singleton
76 public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader, Service {
77 private RemoteRepositoryManager remoteRepositoryManager;
78
79 private VersionResolver versionResolver;
80
81 private VersionRangeResolver versionRangeResolver;
82
83 private ArtifactResolver artifactResolver;
84
85 private RepositoryEventDispatcher repositoryEventDispatcher;
86
87 private ModelBuilder modelBuilder;
88
89 private ModelCacheFactory modelCacheFactory;
90
91 public DefaultArtifactDescriptorReader() {
92
93 }
94
95 @Inject
96 DefaultArtifactDescriptorReader(
97 RemoteRepositoryManager remoteRepositoryManager,
98 VersionResolver versionResolver,
99 VersionRangeResolver versionRangeResolver,
100 ArtifactResolver artifactResolver,
101 ModelBuilder modelBuilder,
102 RepositoryEventDispatcher repositoryEventDispatcher,
103 ModelCacheFactory modelCacheFactory) {
104 setRemoteRepositoryManager(remoteRepositoryManager);
105 setVersionResolver(versionResolver);
106 setVersionRangeResolver(versionRangeResolver);
107 setArtifactResolver(artifactResolver);
108 setModelBuilder(modelBuilder);
109 setRepositoryEventDispatcher(repositoryEventDispatcher);
110 setModelCacheFactory(modelCacheFactory);
111 }
112
113 public void initService(ServiceLocator locator) {
114 setRemoteRepositoryManager(locator.getService(RemoteRepositoryManager.class));
115 setVersionResolver(locator.getService(VersionResolver.class));
116 setVersionRangeResolver(locator.getService(VersionRangeResolver.class));
117 setArtifactResolver(locator.getService(ArtifactResolver.class));
118 modelBuilder = locator.getService(ModelBuilder.class);
119 if (modelBuilder == null) {
120 setModelBuilder(new DefaultModelBuilderFactory().newInstance());
121 }
122 setRepositoryEventDispatcher(locator.getService(RepositoryEventDispatcher.class));
123 setModelCacheFactory(locator.getService(ModelCacheFactory.class));
124 }
125
126 public DefaultArtifactDescriptorReader setRemoteRepositoryManager(RemoteRepositoryManager remoteRepositoryManager) {
127 this.remoteRepositoryManager =
128 Objects.requireNonNull(remoteRepositoryManager, "remoteRepositoryManager cannot be null");
129 return this;
130 }
131
132 public DefaultArtifactDescriptorReader setVersionResolver(VersionResolver versionResolver) {
133 this.versionResolver = Objects.requireNonNull(versionResolver, "versionResolver cannot be null");
134 return this;
135 }
136
137
138 public DefaultArtifactDescriptorReader setVersionRangeResolver(VersionRangeResolver versionRangeResolver) {
139 this.versionRangeResolver = Objects.requireNonNull(versionRangeResolver, "versionRangeResolver cannot be null");
140 return this;
141 }
142
143 public DefaultArtifactDescriptorReader setArtifactResolver(ArtifactResolver artifactResolver) {
144 this.artifactResolver = Objects.requireNonNull(artifactResolver, "artifactResolver cannot be null");
145 return this;
146 }
147
148 public DefaultArtifactDescriptorReader setRepositoryEventDispatcher(
149 RepositoryEventDispatcher repositoryEventDispatcher) {
150 this.repositoryEventDispatcher =
151 Objects.requireNonNull(repositoryEventDispatcher, "repositoryEventDispatcher cannot be null");
152 return this;
153 }
154
155 public DefaultArtifactDescriptorReader setModelBuilder(ModelBuilder modelBuilder) {
156 this.modelBuilder = Objects.requireNonNull(modelBuilder, "modelBuilder cannot be null");
157 return this;
158 }
159
160 public DefaultArtifactDescriptorReader setModelCacheFactory(ModelCacheFactory modelCacheFactory) {
161 this.modelCacheFactory = Objects.requireNonNull(modelCacheFactory, "modelCacheFactory cannot be null");
162 return this;
163 }
164
165 public ArtifactDescriptorResult readArtifactDescriptor(
166 RepositorySystemSession session, ArtifactDescriptorRequest request) throws ArtifactDescriptorException {
167 ArtifactDescriptorResult result = new ArtifactDescriptorResult(request);
168
169 Model model = loadPom(session, request, result);
170 if (model != null) {
171 Map<String, Object> config = session.getConfigProperties();
172 ArtifactDescriptorReaderDelegate delegate =
173 (ArtifactDescriptorReaderDelegate) config.get(ArtifactDescriptorReaderDelegate.class.getName());
174
175 if (delegate == null) {
176 delegate = new ArtifactDescriptorReaderDelegate();
177 }
178
179 delegate.populateResult(session, result, model);
180 }
181
182 return result;
183 }
184
185 private Model loadPom(
186 RepositorySystemSession session, ArtifactDescriptorRequest request, ArtifactDescriptorResult result)
187 throws ArtifactDescriptorException {
188 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
189
190 Set<String> visited = new LinkedHashSet<>();
191 for (Artifact a = request.getArtifact(); ; ) {
192 Artifact pomArtifact = ArtifactDescriptorUtils.toPomArtifact(a);
193 try {
194 VersionRequest versionRequest =
195 new VersionRequest(a, request.getRepositories(), request.getRequestContext());
196 versionRequest.setTrace(trace);
197 VersionResult versionResult = versionResolver.resolveVersion(session, versionRequest);
198
199 a = a.setVersion(versionResult.getVersion());
200
201 versionRequest =
202 new VersionRequest(pomArtifact, request.getRepositories(), request.getRequestContext());
203 versionRequest.setTrace(trace);
204 versionResult = versionResolver.resolveVersion(session, versionRequest);
205
206 pomArtifact = pomArtifact.setVersion(versionResult.getVersion());
207 } catch (VersionResolutionException e) {
208 result.addException(e);
209 throw new ArtifactDescriptorException(result);
210 }
211
212 if (!visited.add(a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getBaseVersion())) {
213 RepositoryException exception =
214 new RepositoryException("Artifact relocations form a cycle: " + visited);
215 invalidDescriptor(session, trace, a, exception);
216 if ((getPolicy(session, a, request) & ArtifactDescriptorPolicy.IGNORE_INVALID) != 0) {
217 return null;
218 }
219 result.addException(exception);
220 throw new ArtifactDescriptorException(result);
221 }
222
223 ArtifactResult resolveResult;
224 try {
225 ArtifactRequest resolveRequest =
226 new ArtifactRequest(pomArtifact, request.getRepositories(), request.getRequestContext());
227 resolveRequest.setTrace(trace);
228 resolveResult = artifactResolver.resolveArtifact(session, resolveRequest);
229 pomArtifact = resolveResult.getArtifact();
230 result.setRepository(resolveResult.getRepository());
231 } catch (ArtifactResolutionException e) {
232 if (e.getCause() instanceof ArtifactNotFoundException) {
233 missingDescriptor(session, trace, a, (Exception) e.getCause());
234 if ((getPolicy(session, a, request) & ArtifactDescriptorPolicy.IGNORE_MISSING) != 0) {
235 return null;
236 }
237 }
238 result.addException(e);
239 throw new ArtifactDescriptorException(result);
240 }
241
242 Model model;
243
244
245 final WorkspaceReader workspace = session.getWorkspaceReader();
246 if (workspace instanceof MavenWorkspaceReader) {
247 model = ((MavenWorkspaceReader) workspace).findModel(pomArtifact);
248 if (model != null) {
249 return model;
250 }
251 }
252
253 try {
254 ModelBuildingRequest modelRequest = new DefaultModelBuildingRequest();
255 modelRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
256 modelRequest.setProcessPlugins(false);
257 modelRequest.setTwoPhaseBuilding(false);
258
259
260 modelRequest.setSystemProperties(
261 toProperties(session.getUserProperties(), session.getSystemProperties()));
262 modelRequest.setUserProperties(new Properties());
263 modelRequest.setModelCache(modelCacheFactory.createCache(session));
264 modelRequest.setModelResolver(new DefaultModelResolver(
265 session,
266 trace.newChild(modelRequest),
267 request.getRequestContext(),
268 artifactResolver,
269 versionRangeResolver,
270 remoteRepositoryManager,
271 request.getRepositories()));
272 if (resolveResult.getRepository() instanceof WorkspaceRepository) {
273 modelRequest.setPomFile(pomArtifact.getFile());
274 } else {
275 modelRequest.setModelSource(new FileModelSource(pomArtifact.getFile()));
276 }
277
278 model = modelBuilder.build(modelRequest).getEffectiveModel();
279 } catch (ModelBuildingException e) {
280 for (ModelProblem problem : e.getProblems()) {
281 if (problem.getException() instanceof UnresolvableModelException) {
282 result.addException(problem.getException());
283 throw new ArtifactDescriptorException(result);
284 }
285 }
286 invalidDescriptor(session, trace, a, e);
287 if ((getPolicy(session, a, request) & ArtifactDescriptorPolicy.IGNORE_INVALID) != 0) {
288 return null;
289 }
290 result.addException(e);
291 throw new ArtifactDescriptorException(result);
292 }
293
294 Relocation relocation = getRelocation(model);
295
296 if (relocation != null) {
297 result.addRelocation(a);
298 a = new RelocatedArtifact(
299 a,
300 relocation.getGroupId(),
301 relocation.getArtifactId(),
302 relocation.getVersion(),
303 relocation.getMessage());
304 result.setArtifact(a);
305 } else {
306 return model;
307 }
308 }
309 }
310
311 private Properties toProperties(Map<String, String> dominant, Map<String, String> recessive) {
312 Properties props = new Properties();
313 if (recessive != null) {
314 props.putAll(recessive);
315 }
316 if (dominant != null) {
317 props.putAll(dominant);
318 }
319 return props;
320 }
321
322 private Relocation getRelocation(Model model) {
323 Relocation relocation = null;
324 DistributionManagement distMgmt = model.getDistributionManagement();
325 if (distMgmt != null) {
326 relocation = distMgmt.getRelocation();
327 }
328 return relocation;
329 }
330
331 private void missingDescriptor(
332 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Exception exception) {
333 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DESCRIPTOR_MISSING);
334 event.setTrace(trace);
335 event.setArtifact(artifact);
336 event.setException(exception);
337
338 repositoryEventDispatcher.dispatch(event.build());
339 }
340
341 private void invalidDescriptor(
342 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Exception exception) {
343 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DESCRIPTOR_INVALID);
344 event.setTrace(trace);
345 event.setArtifact(artifact);
346 event.setException(exception);
347
348 repositoryEventDispatcher.dispatch(event.build());
349 }
350
351 private int getPolicy(RepositorySystemSession session, Artifact a, ArtifactDescriptorRequest request) {
352 ArtifactDescriptorPolicy policy = session.getArtifactDescriptorPolicy();
353 if (policy == null) {
354 return ArtifactDescriptorPolicy.STRICT;
355 }
356 return policy.getPolicy(session, new ArtifactDescriptorPolicyRequest(a, request.getRequestContext()));
357 }
358 }