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