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
261 final WorkspaceReader workspace = session.getWorkspaceReader();
262 if ( workspace instanceof MavenWorkspaceReader )
263 {
264 model = ( (MavenWorkspaceReader) workspace ).findModel( pomArtifact );
265 if ( model != null )
266 {
267 return model;
268 }
269 }
270
271 try
272 {
273 ModelBuildingRequest modelRequest = new DefaultModelBuildingRequest();
274 modelRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
275 modelRequest.setProcessPlugins( false );
276 modelRequest.setTwoPhaseBuilding( false );
277 modelRequest.setSystemProperties( toProperties( session.getUserProperties(),
278 session.getSystemProperties() ) );
279 modelRequest.setModelCache( DefaultModelCache.newInstance( session ) );
280 modelRequest.setModelResolver( new DefaultModelResolver( session, trace.newChild( modelRequest ),
281 request.getRequestContext(), artifactResolver,
282 versionRangeResolver, remoteRepositoryManager,
283 request.getRepositories() ) );
284 if ( resolveResult.getRepository() instanceof WorkspaceRepository )
285 {
286 modelRequest.setPomFile( pomArtifact.getFile() );
287 }
288 else
289 {
290 modelRequest.setModelSource( new FileModelSource( pomArtifact.getFile() ) );
291 }
292
293 model = modelBuilder.build( modelRequest ).getEffectiveModel();
294 }
295 catch ( ModelBuildingException e )
296 {
297 for ( ModelProblem problem : e.getProblems() )
298 {
299 if ( problem.getException() instanceof UnresolvableModelException )
300 {
301 result.addException( problem.getException() );
302 throw new ArtifactDescriptorException( result );
303 }
304 }
305 invalidDescriptor( session, trace, a, e );
306 if ( ( getPolicy( session, a, request ) & ArtifactDescriptorPolicy.IGNORE_INVALID ) != 0 )
307 {
308 return null;
309 }
310 result.addException( e );
311 throw new ArtifactDescriptorException( result );
312 }
313
314 Relocation relocation = getRelocation( model );
315
316 if ( relocation != null )
317 {
318 result.addRelocation( a );
319 a =
320 new RelocatedArtifact( a, relocation.getGroupId(), relocation.getArtifactId(),
321 relocation.getVersion() );
322 result.setArtifact( a );
323 }
324 else
325 {
326 return model;
327 }
328 }
329 }
330
331 private Properties toProperties( Map<String, String> dominant, Map<String, String> recessive )
332 {
333 Properties props = new Properties();
334 if ( recessive != null )
335 {
336 props.putAll( recessive );
337 }
338 if ( dominant != null )
339 {
340 props.putAll( dominant );
341 }
342 return props;
343 }
344
345 private Relocation getRelocation( Model model )
346 {
347 Relocation relocation = null;
348 DistributionManagement distMgmt = model.getDistributionManagement();
349 if ( distMgmt != null )
350 {
351 relocation = distMgmt.getRelocation();
352 }
353 return relocation;
354 }
355
356 private void missingDescriptor( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
357 Exception exception )
358 {
359 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DESCRIPTOR_MISSING );
360 event.setTrace( trace );
361 event.setArtifact( artifact );
362 event.setException( exception );
363
364 repositoryEventDispatcher.dispatch( event.build() );
365 }
366
367 private void invalidDescriptor( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
368 Exception exception )
369 {
370 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DESCRIPTOR_INVALID );
371 event.setTrace( trace );
372 event.setArtifact( artifact );
373 event.setException( exception );
374
375 repositoryEventDispatcher.dispatch( event.build() );
376 }
377
378 private int getPolicy( RepositorySystemSession session, Artifact a, ArtifactDescriptorRequest request )
379 {
380 ArtifactDescriptorPolicy policy = session.getArtifactDescriptorPolicy();
381 if ( policy == null )
382 {
383 return ArtifactDescriptorPolicy.STRICT;
384 }
385 return policy.getPolicy( session, new ArtifactDescriptorPolicyRequest( a, request.getRequestContext() ) );
386 }
387
388 }