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
30 import org.apache.maven.model.Model;
31 import org.apache.maven.model.building.ArtifactModelSource;
32 import org.apache.maven.model.building.DefaultModelBuildingRequest;
33 import org.apache.maven.model.building.ModelBuilder;
34 import org.apache.maven.model.building.ModelBuildingException;
35 import org.apache.maven.model.building.ModelBuildingRequest;
36 import org.apache.maven.model.building.ModelProblem;
37 import org.apache.maven.model.resolution.UnresolvableModelException;
38 import org.eclipse.aether.RepositoryEvent;
39 import org.eclipse.aether.RepositoryEvent.EventType;
40 import org.eclipse.aether.RepositoryException;
41 import org.eclipse.aether.RepositorySystemSession;
42 import org.eclipse.aether.RequestTrace;
43 import org.eclipse.aether.artifact.Artifact;
44 import org.eclipse.aether.impl.ArtifactDescriptorReader;
45 import org.eclipse.aether.impl.ArtifactResolver;
46 import org.eclipse.aether.impl.RemoteRepositoryManager;
47 import org.eclipse.aether.impl.RepositoryEventDispatcher;
48 import org.eclipse.aether.impl.VersionRangeResolver;
49 import org.eclipse.aether.impl.VersionResolver;
50 import org.eclipse.aether.repository.WorkspaceReader;
51 import org.eclipse.aether.repository.WorkspaceRepository;
52 import org.eclipse.aether.resolution.ArtifactDescriptorException;
53 import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
54 import org.eclipse.aether.resolution.ArtifactDescriptorPolicyRequest;
55 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
56 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
57 import org.eclipse.aether.resolution.ArtifactRequest;
58 import org.eclipse.aether.resolution.ArtifactResolutionException;
59 import org.eclipse.aether.resolution.ArtifactResult;
60 import org.eclipse.aether.resolution.VersionRequest;
61 import org.eclipse.aether.resolution.VersionResolutionException;
62 import org.eclipse.aether.resolution.VersionResult;
63 import org.eclipse.aether.transfer.ArtifactNotFoundException;
64
65
66
67
68 @Named
69 @Singleton
70 public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader {
71 private final RemoteRepositoryManager remoteRepositoryManager;
72 private final VersionResolver versionResolver;
73 private final VersionRangeResolver versionRangeResolver;
74 private final ArtifactResolver artifactResolver;
75 private final RepositoryEventDispatcher repositoryEventDispatcher;
76 private final ModelBuilder modelBuilder;
77 private final ModelCacheFactory modelCacheFactory;
78 private final Map<String, MavenArtifactRelocationSource> artifactRelocationSources;
79 private final ArtifactDescriptorReaderDelegate delegate;
80
81 @Inject
82 public DefaultArtifactDescriptorReader(
83 RemoteRepositoryManager remoteRepositoryManager,
84 VersionResolver versionResolver,
85 VersionRangeResolver versionRangeResolver,
86 ArtifactResolver artifactResolver,
87 ModelBuilder modelBuilder,
88 RepositoryEventDispatcher repositoryEventDispatcher,
89 ModelCacheFactory modelCacheFactory,
90 Map<String, MavenArtifactRelocationSource> artifactRelocationSources) {
91 this.remoteRepositoryManager =
92 Objects.requireNonNull(remoteRepositoryManager, "remoteRepositoryManager cannot be null");
93 this.versionResolver = Objects.requireNonNull(versionResolver, "versionResolver cannot be null");
94 this.versionRangeResolver = Objects.requireNonNull(versionRangeResolver, "versionRangeResolver cannot be null");
95 this.artifactResolver = Objects.requireNonNull(artifactResolver, "artifactResolver cannot be null");
96 this.modelBuilder = Objects.requireNonNull(modelBuilder, "modelBuilder cannot be null");
97 this.repositoryEventDispatcher =
98 Objects.requireNonNull(repositoryEventDispatcher, "repositoryEventDispatcher cannot be null");
99 this.modelCacheFactory = Objects.requireNonNull(modelCacheFactory, "modelCacheFactory cannot be null");
100 this.artifactRelocationSources =
101 Objects.requireNonNull(artifactRelocationSources, "artifactRelocationSources cannot be null");
102 this.delegate = new ArtifactDescriptorReaderDelegate();
103 }
104
105 @Override
106 public ArtifactDescriptorResult readArtifactDescriptor(
107 RepositorySystemSession session, ArtifactDescriptorRequest request) throws ArtifactDescriptorException {
108 ArtifactDescriptorResult result = new ArtifactDescriptorResult(request);
109
110 Model model = loadPom(session, request, result);
111 if (model != null) {
112 Map<String, Object> config = session.getConfigProperties();
113 ArtifactDescriptorReaderDelegate delegate =
114 (ArtifactDescriptorReaderDelegate) config.get(ArtifactDescriptorReaderDelegate.class.getName());
115
116 if (delegate == null) {
117 delegate = this.delegate;
118 }
119
120 delegate.populateResult(session, result, model);
121 }
122
123 return result;
124 }
125
126 private Model loadPom(
127 RepositorySystemSession session, ArtifactDescriptorRequest request, ArtifactDescriptorResult result)
128 throws ArtifactDescriptorException {
129 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
130
131 LinkedHashSet<String> visited = new LinkedHashSet<>();
132 for (Artifact a = request.getArtifact(); ; ) {
133 Artifact pomArtifact = ArtifactDescriptorUtils.toPomArtifactUnconditionally(a);
134 try {
135 VersionRequest versionRequest =
136 new VersionRequest(a, request.getRepositories(), request.getRequestContext());
137 versionRequest.setTrace(trace);
138 VersionResult versionResult = versionResolver.resolveVersion(session, versionRequest);
139
140 a = a.setVersion(versionResult.getVersion());
141
142 versionRequest =
143 new VersionRequest(pomArtifact, request.getRepositories(), request.getRequestContext());
144 versionRequest.setTrace(trace);
145 versionResult = versionResolver.resolveVersion(session, versionRequest);
146
147 pomArtifact = pomArtifact.setVersion(versionResult.getVersion());
148 } catch (VersionResolutionException e) {
149 result.addException(e);
150 throw new ArtifactDescriptorException(result);
151 }
152
153 if (!visited.add(a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getBaseVersion())) {
154 RepositoryException exception =
155 new RepositoryException("Artifact relocations form a cycle: " + visited);
156 invalidDescriptor(session, trace, a, exception);
157 if ((getPolicy(session, a, request) & ArtifactDescriptorPolicy.IGNORE_INVALID) != 0) {
158 return null;
159 }
160 result.addException(exception);
161 throw new ArtifactDescriptorException(result);
162 }
163
164 ArtifactResult resolveResult;
165 try {
166 ArtifactRequest resolveRequest =
167 new ArtifactRequest(pomArtifact, request.getRepositories(), request.getRequestContext());
168 resolveRequest.setTrace(trace);
169 resolveResult = artifactResolver.resolveArtifact(session, resolveRequest);
170 pomArtifact = resolveResult.getArtifact();
171 result.setRepository(resolveResult.getRepository());
172 } catch (ArtifactResolutionException e) {
173 if (e.getCause() instanceof ArtifactNotFoundException) {
174 missingDescriptor(session, trace, a, (Exception) e.getCause());
175 if ((getPolicy(session, a, request) & ArtifactDescriptorPolicy.IGNORE_MISSING) != 0) {
176 return null;
177 }
178 }
179 result.addException(e);
180 throw new ArtifactDescriptorException(result);
181 }
182
183 Model model;
184
185
186 final WorkspaceReader workspace = session.getWorkspaceReader();
187 if (workspace instanceof MavenWorkspaceReader) {
188 model = ((MavenWorkspaceReader) workspace).findModel(pomArtifact);
189 if (model != null) {
190 return model;
191 }
192 }
193
194 try {
195 ModelBuildingRequest modelRequest = new DefaultModelBuildingRequest();
196 modelRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
197 modelRequest.setProcessPlugins(false);
198 modelRequest.setTwoPhaseBuilding(false);
199
200
201 modelRequest.setSystemProperties(
202 toProperties(session.getUserProperties(), session.getSystemProperties()));
203 modelRequest.setUserProperties(new Properties());
204 modelRequest.setModelCache(modelCacheFactory.createCache(session));
205 modelRequest.setModelResolver(new DefaultModelResolver(
206 session,
207 trace.newChild(modelRequest),
208 request.getRequestContext(),
209 artifactResolver,
210 versionRangeResolver,
211 remoteRepositoryManager,
212 request.getRepositories()));
213 if (resolveResult.getRepository() instanceof WorkspaceRepository) {
214 modelRequest.setPomFile(pomArtifact.getFile());
215 } else {
216 modelRequest.setModelSource(new ArtifactModelSource(
217 pomArtifact.getFile(),
218 pomArtifact.getGroupId(),
219 pomArtifact.getArtifactId(),
220 pomArtifact.getVersion()));
221 }
222
223 model = modelBuilder.build(modelRequest).getEffectiveModel();
224 } catch (ModelBuildingException e) {
225 for (ModelProblem problem : e.getProblems()) {
226 if (problem.getException() instanceof UnresolvableModelException) {
227 result.addException(problem.getException());
228 throw new ArtifactDescriptorException(result);
229 }
230 }
231 invalidDescriptor(session, trace, a, e);
232 if ((getPolicy(session, a, request) & ArtifactDescriptorPolicy.IGNORE_INVALID) != 0) {
233 return null;
234 }
235 result.addException(e);
236 throw new ArtifactDescriptorException(result);
237 }
238
239 Artifact relocatedArtifact = getRelocation(session, result, model);
240 if (relocatedArtifact != null) {
241 if (withinSameGav(relocatedArtifact, a)) {
242 result.setArtifact(relocatedArtifact);
243 return model;
244 } else {
245 result.addRelocation(a);
246 a = relocatedArtifact;
247 result.setArtifact(a);
248 }
249 } else {
250 return model;
251 }
252 }
253 }
254
255 private boolean withinSameGav(Artifact a1, Artifact a2) {
256 return Objects.equals(a1.getGroupId(), a2.getGroupId())
257 && Objects.equals(a1.getArtifactId(), a2.getArtifactId())
258 && Objects.equals(a1.getVersion(), a2.getVersion());
259 }
260
261 private Properties toProperties(Map<String, String> dominant, Map<String, String> recessive) {
262 Properties props = new Properties();
263 if (recessive != null) {
264 props.putAll(recessive);
265 }
266 if (dominant != null) {
267 props.putAll(dominant);
268 }
269 return props;
270 }
271
272 private Artifact getRelocation(
273 RepositorySystemSession session, ArtifactDescriptorResult artifactDescriptorResult, Model model)
274 throws ArtifactDescriptorException {
275 Artifact result = null;
276 for (MavenArtifactRelocationSource source : artifactRelocationSources.values()) {
277 result = source.relocatedTarget(session, artifactDescriptorResult, model);
278 if (result != null) {
279 break;
280 }
281 }
282 return result;
283 }
284
285 private void missingDescriptor(
286 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Exception exception) {
287 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DESCRIPTOR_MISSING);
288 event.setTrace(trace);
289 event.setArtifact(artifact);
290 event.setException(exception);
291
292 repositoryEventDispatcher.dispatch(event.build());
293 }
294
295 private void invalidDescriptor(
296 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Exception exception) {
297 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DESCRIPTOR_INVALID);
298 event.setTrace(trace);
299 event.setArtifact(artifact);
300 event.setException(exception);
301
302 repositoryEventDispatcher.dispatch(event.build());
303 }
304
305 private int getPolicy(RepositorySystemSession session, Artifact a, ArtifactDescriptorRequest request) {
306 ArtifactDescriptorPolicy policy = session.getArtifactDescriptorPolicy();
307 if (policy == null) {
308 return ArtifactDescriptorPolicy.STRICT;
309 }
310 return policy.getPolicy(session, new ArtifactDescriptorPolicyRequest(a, request.getRequestContext()));
311 }
312 }