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