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