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.ArtifactModelSource;
35 import org.apache.maven.model.building.DefaultModelBuildingRequest;
36 import org.apache.maven.model.building.ModelBuilder;
37 import org.apache.maven.model.building.ModelBuildingException;
38 import org.apache.maven.model.building.ModelBuildingRequest;
39 import org.apache.maven.model.building.ModelProblem;
40 import org.apache.maven.model.resolution.UnresolvableModelException;
41 import org.eclipse.aether.RepositoryEvent;
42 import org.eclipse.aether.RepositoryEvent.EventType;
43 import org.eclipse.aether.RepositoryException;
44 import org.eclipse.aether.RepositorySystemSession;
45 import org.eclipse.aether.RequestTrace;
46 import org.eclipse.aether.artifact.Artifact;
47 import org.eclipse.aether.impl.ArtifactDescriptorReader;
48 import org.eclipse.aether.impl.ArtifactResolver;
49 import org.eclipse.aether.impl.RemoteRepositoryManager;
50 import org.eclipse.aether.impl.RepositoryEventDispatcher;
51 import org.eclipse.aether.impl.VersionRangeResolver;
52 import org.eclipse.aether.impl.VersionResolver;
53 import org.eclipse.aether.repository.WorkspaceReader;
54 import org.eclipse.aether.repository.WorkspaceRepository;
55 import org.eclipse.aether.resolution.ArtifactDescriptorException;
56 import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
57 import org.eclipse.aether.resolution.ArtifactDescriptorPolicyRequest;
58 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
59 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
60 import org.eclipse.aether.resolution.ArtifactRequest;
61 import org.eclipse.aether.resolution.ArtifactResolutionException;
62 import org.eclipse.aether.resolution.ArtifactResult;
63 import org.eclipse.aether.resolution.VersionRequest;
64 import org.eclipse.aether.resolution.VersionResolutionException;
65 import org.eclipse.aether.resolution.VersionResult;
66 import org.eclipse.aether.transfer.ArtifactNotFoundException;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
69
70
71
72 @Named
73 @Singleton
74 public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader {
75 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultArtifactDescriptorReader.class);
76
77 private final RemoteRepositoryManager remoteRepositoryManager;
78 private final VersionResolver versionResolver;
79 private final VersionRangeResolver versionRangeResolver;
80 private final ArtifactResolver artifactResolver;
81 private final RepositoryEventDispatcher repositoryEventDispatcher;
82 private final ModelBuilder modelBuilder;
83 private final ModelCacheFactory modelCacheFactory;
84
85 @Inject
86 public DefaultArtifactDescriptorReader(
87 RemoteRepositoryManager remoteRepositoryManager,
88 VersionResolver versionResolver,
89 VersionRangeResolver versionRangeResolver,
90 ArtifactResolver artifactResolver,
91 ModelBuilder modelBuilder,
92 RepositoryEventDispatcher repositoryEventDispatcher,
93 ModelCacheFactory modelCacheFactory) {
94 this.remoteRepositoryManager =
95 Objects.requireNonNull(remoteRepositoryManager, "remoteRepositoryManager cannot be null");
96 this.versionResolver = Objects.requireNonNull(versionResolver, "versionResolver cannot be null");
97 this.versionRangeResolver = Objects.requireNonNull(versionRangeResolver, "versionRangeResolver cannot be null");
98 this.artifactResolver = Objects.requireNonNull(artifactResolver, "artifactResolver cannot be null");
99 this.modelBuilder = Objects.requireNonNull(modelBuilder, "modelBuilder cannot be null");
100 this.repositoryEventDispatcher =
101 Objects.requireNonNull(repositoryEventDispatcher, "repositoryEventDispatcher cannot be null");
102 this.modelCacheFactory = Objects.requireNonNull(modelCacheFactory, "modelCacheFactory cannot be null");
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 = new ArtifactDescriptorReaderDelegate();
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 Set<String> visited = new LinkedHashSet<>();
132 for (Artifact a = request.getArtifact(); ; ) {
133 Artifact pomArtifact = ArtifactDescriptorUtils.toPomArtifact(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 Relocation relocation = getRelocation(model);
240
241 if (relocation != null) {
242 result.addRelocation(a);
243 a = new RelocatedArtifact(
244 a,
245 relocation.getGroupId(),
246 relocation.getArtifactId(),
247 relocation.getVersion(),
248 relocation.getMessage());
249 result.setArtifact(a);
250 } else {
251 return model;
252 }
253 }
254 }
255
256 private Properties toProperties(Map<String, String> dominant, Map<String, String> recessive) {
257 Properties props = new Properties();
258 if (recessive != null) {
259 props.putAll(recessive);
260 }
261 if (dominant != null) {
262 props.putAll(dominant);
263 }
264 return props;
265 }
266
267 private Relocation getRelocation(Model model) {
268 Relocation relocation = null;
269 DistributionManagement distMgmt = model.getDistributionManagement();
270 if (distMgmt != null) {
271 relocation = distMgmt.getRelocation();
272 }
273 return relocation;
274 }
275
276 private void missingDescriptor(
277 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Exception exception) {
278 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DESCRIPTOR_MISSING);
279 event.setTrace(trace);
280 event.setArtifact(artifact);
281 event.setException(exception);
282
283 repositoryEventDispatcher.dispatch(event.build());
284 }
285
286 private void invalidDescriptor(
287 RepositorySystemSession session, RequestTrace trace, Artifact artifact, Exception exception) {
288 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.ARTIFACT_DESCRIPTOR_INVALID);
289 event.setTrace(trace);
290 event.setArtifact(artifact);
291 event.setException(exception);
292
293 repositoryEventDispatcher.dispatch(event.build());
294 }
295
296 private int getPolicy(RepositorySystemSession session, Artifact a, ArtifactDescriptorRequest request) {
297 ArtifactDescriptorPolicy policy = session.getArtifactDescriptorPolicy();
298 if (policy == null) {
299 return ArtifactDescriptorPolicy.STRICT;
300 }
301 return policy.getPolicy(session, new ArtifactDescriptorPolicyRequest(a, request.getRequestContext()));
302 }
303 }