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.ArtifactModelSource;
36 import org.apache.maven.model.building.DefaultModelBuildingRequest;
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.eclipse.aether.RepositoryEvent;
43 import org.eclipse.aether.RepositoryEvent.EventType;
44 import org.eclipse.aether.RepositoryException;
45 import org.eclipse.aether.RepositorySystemSession;
46 import org.eclipse.aether.RequestTrace;
47 import org.eclipse.aether.artifact.Artifact;
48 import org.eclipse.aether.impl.ArtifactDescriptorReader;
49 import org.eclipse.aether.impl.ArtifactResolver;
50 import org.eclipse.aether.impl.RemoteRepositoryManager;
51 import org.eclipse.aether.impl.RepositoryEventDispatcher;
52 import org.eclipse.aether.impl.VersionRangeResolver;
53 import org.eclipse.aether.impl.VersionResolver;
54 import org.eclipse.aether.repository.WorkspaceReader;
55 import org.eclipse.aether.repository.WorkspaceRepository;
56 import org.eclipse.aether.resolution.ArtifactDescriptorException;
57 import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
58 import org.eclipse.aether.resolution.ArtifactDescriptorPolicyRequest;
59 import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
60 import org.eclipse.aether.resolution.ArtifactDescriptorResult;
61 import org.eclipse.aether.resolution.ArtifactRequest;
62 import org.eclipse.aether.resolution.ArtifactResolutionException;
63 import org.eclipse.aether.resolution.ArtifactResult;
64 import org.eclipse.aether.resolution.VersionRequest;
65 import org.eclipse.aether.resolution.VersionResolutionException;
66 import org.eclipse.aether.resolution.VersionResult;
67 import org.eclipse.aether.transfer.ArtifactNotFoundException;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71
72
73
74 @Named
75 @Singleton
76 public class DefaultArtifactDescriptorReader implements ArtifactDescriptorReader
77 {
78 private static final Logger LOGGER = LoggerFactory.getLogger( DefaultArtifactDescriptorReader.class );
79
80 private final RemoteRepositoryManager remoteRepositoryManager;
81 private final VersionResolver versionResolver;
82 private final VersionRangeResolver versionRangeResolver;
83 private final ArtifactResolver artifactResolver;
84 private final RepositoryEventDispatcher repositoryEventDispatcher;
85 private final ModelBuilder modelBuilder;
86 private final ModelCacheFactory modelCacheFactory;
87
88 @Inject
89 public DefaultArtifactDescriptorReader(
90 RemoteRepositoryManager remoteRepositoryManager,
91 VersionResolver versionResolver,
92 VersionRangeResolver versionRangeResolver,
93 ArtifactResolver artifactResolver,
94 ModelBuilder modelBuilder,
95 RepositoryEventDispatcher repositoryEventDispatcher,
96 ModelCacheFactory modelCacheFactory )
97 {
98 this.remoteRepositoryManager = Objects.requireNonNull( remoteRepositoryManager,
99 "remoteRepositoryManager cannot be null" );
100 this.versionResolver = Objects.requireNonNull( versionResolver, "versionResolver cannot be null" );
101 this.versionRangeResolver =
102 Objects.requireNonNull( versionRangeResolver, "versionRangeResolver cannot be null" );
103 this.artifactResolver = Objects.requireNonNull( artifactResolver, "artifactResolver cannot be null" );
104 this.modelBuilder = Objects.requireNonNull( modelBuilder, "modelBuilder cannot be null" );
105 this.repositoryEventDispatcher = Objects.requireNonNull( repositoryEventDispatcher,
106 "repositoryEventDispatcher cannot be null" );
107 this.modelCacheFactory = Objects.requireNonNull( modelCacheFactory,
108 "modelCacheFactory cannot be null" );
109 }
110
111 public ArtifactDescriptorResult readArtifactDescriptor( RepositorySystemSession session,
112 ArtifactDescriptorRequest request )
113 throws ArtifactDescriptorException
114 {
115 ArtifactDescriptorResult result = new ArtifactDescriptorResult( request );
116
117 Model model = loadPom( session, request, result );
118 if ( model != null )
119 {
120 Map<String, Object> config = session.getConfigProperties();
121 ArtifactDescriptorReaderDelegate delegate =
122 (ArtifactDescriptorReaderDelegate) config.get( ArtifactDescriptorReaderDelegate.class.getName() );
123
124 if ( delegate == null )
125 {
126 delegate = new ArtifactDescriptorReaderDelegate();
127 }
128
129 delegate.populateResult( session, result, model );
130 }
131
132 return result;
133 }
134
135 private Model loadPom( RepositorySystemSession session, ArtifactDescriptorRequest request,
136 ArtifactDescriptorResult result )
137 throws ArtifactDescriptorException
138 {
139 RequestTrace trace = RequestTrace.newChild( request.getTrace(), request );
140
141 Set<String> visited = new LinkedHashSet<>();
142 for ( Artifact a = request.getArtifact();; )
143 {
144 Artifact pomArtifact = ArtifactDescriptorUtils.toPomArtifact( a );
145 try
146 {
147 VersionRequest versionRequest =
148 new VersionRequest( a, request.getRepositories(), request.getRequestContext() );
149 versionRequest.setTrace( trace );
150 VersionResult versionResult = versionResolver.resolveVersion( session, versionRequest );
151
152 a = a.setVersion( versionResult.getVersion() );
153
154 versionRequest =
155 new VersionRequest( pomArtifact, request.getRepositories(), request.getRequestContext() );
156 versionRequest.setTrace( trace );
157 versionResult = versionResolver.resolveVersion( session, versionRequest );
158
159 pomArtifact = pomArtifact.setVersion( versionResult.getVersion() );
160 }
161 catch ( VersionResolutionException e )
162 {
163 result.addException( e );
164 throw new ArtifactDescriptorException( result );
165 }
166
167 if ( !visited.add( a.getGroupId() + ':' + a.getArtifactId() + ':' + a.getBaseVersion() ) )
168 {
169 RepositoryException exception =
170 new RepositoryException( "Artifact relocations form a cycle: " + visited );
171 invalidDescriptor( session, trace, a, exception );
172 if ( ( getPolicy( session, a, request ) & ArtifactDescriptorPolicy.IGNORE_INVALID ) != 0 )
173 {
174 return null;
175 }
176 result.addException( exception );
177 throw new ArtifactDescriptorException( result );
178 }
179
180 ArtifactResult resolveResult;
181 try
182 {
183 ArtifactRequest resolveRequest =
184 new ArtifactRequest( pomArtifact, request.getRepositories(), request.getRequestContext() );
185 resolveRequest.setTrace( trace );
186 resolveResult = artifactResolver.resolveArtifact( session, resolveRequest );
187 pomArtifact = resolveResult.getArtifact();
188 result.setRepository( resolveResult.getRepository() );
189 }
190 catch ( ArtifactResolutionException e )
191 {
192 if ( e.getCause() instanceof ArtifactNotFoundException )
193 {
194 missingDescriptor( session, trace, a, (Exception) e.getCause() );
195 if ( ( getPolicy( session, a, request ) & ArtifactDescriptorPolicy.IGNORE_MISSING ) != 0 )
196 {
197 return null;
198 }
199 }
200 result.addException( e );
201 throw new ArtifactDescriptorException( result );
202 }
203
204 Model model;
205
206
207 final WorkspaceReader workspace = session.getWorkspaceReader();
208 if ( workspace instanceof MavenWorkspaceReader )
209 {
210 model = ( (MavenWorkspaceReader) workspace ).findModel( pomArtifact );
211 if ( model != null )
212 {
213 return model;
214 }
215 }
216
217 try
218 {
219 ModelBuildingRequest modelRequest = new DefaultModelBuildingRequest();
220 modelRequest.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
221 modelRequest.setProcessPlugins( false );
222 modelRequest.setTwoPhaseBuilding( false );
223 modelRequest.setSystemProperties( toProperties( session.getSystemProperties() ) );
224 modelRequest.setUserProperties( toProperties( session.getUserProperties() ) );
225 modelRequest.setModelCache( modelCacheFactory.createCache( session ) );
226 modelRequest.setModelResolver( new DefaultModelResolver( session, trace.newChild( modelRequest ),
227 request.getRequestContext(), artifactResolver,
228 versionRangeResolver, remoteRepositoryManager,
229 request.getRepositories() ) );
230 if ( resolveResult.getRepository() instanceof WorkspaceRepository )
231 {
232 modelRequest.setPomFile( pomArtifact.getFile() );
233 }
234 else
235 {
236 modelRequest.setModelSource( new ArtifactModelSource( pomArtifact.getFile(),
237 pomArtifact.getGroupId(),
238 pomArtifact.getArtifactId(),
239 pomArtifact.getVersion() ) );
240 }
241
242 model = modelBuilder.build( modelRequest ).getEffectiveModel();
243 }
244 catch ( ModelBuildingException e )
245 {
246 for ( ModelProblem problem : e.getProblems() )
247 {
248 if ( problem.getException() instanceof UnresolvableModelException )
249 {
250 result.addException( problem.getException() );
251 throw new ArtifactDescriptorException( result );
252 }
253 }
254 invalidDescriptor( session, trace, a, e );
255 if ( ( getPolicy( session, a, request ) & ArtifactDescriptorPolicy.IGNORE_INVALID ) != 0 )
256 {
257 return null;
258 }
259 result.addException( e );
260 throw new ArtifactDescriptorException( result );
261 }
262
263 Relocation relocation = getRelocation( model );
264
265 if ( relocation != null )
266 {
267 result.addRelocation( a );
268 a =
269 new RelocatedArtifact( a, relocation.getGroupId(), relocation.getArtifactId(),
270 relocation.getVersion(), relocation.getMessage() );
271 result.setArtifact( a );
272 }
273 else
274 {
275 return model;
276 }
277 }
278 }
279
280 private Properties toProperties( Map<String, String> map )
281 {
282 Properties props = new Properties();
283 props.putAll( map );
284 return props;
285 }
286
287 private Relocation getRelocation( Model model )
288 {
289 Relocation relocation = null;
290 DistributionManagement distMgmt = model.getDistributionManagement();
291 if ( distMgmt != null )
292 {
293 relocation = distMgmt.getRelocation();
294 }
295 return relocation;
296 }
297
298 private void missingDescriptor( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
299 Exception exception )
300 {
301 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DESCRIPTOR_MISSING );
302 event.setTrace( trace );
303 event.setArtifact( artifact );
304 event.setException( exception );
305
306 repositoryEventDispatcher.dispatch( event.build() );
307 }
308
309 private void invalidDescriptor( RepositorySystemSession session, RequestTrace trace, Artifact artifact,
310 Exception exception )
311 {
312 RepositoryEvent.Builder event = new RepositoryEvent.Builder( session, EventType.ARTIFACT_DESCRIPTOR_INVALID );
313 event.setTrace( trace );
314 event.setArtifact( artifact );
315 event.setException( exception );
316
317 repositoryEventDispatcher.dispatch( event.build() );
318 }
319
320 private int getPolicy( RepositorySystemSession session, Artifact a, ArtifactDescriptorRequest request )
321 {
322 ArtifactDescriptorPolicy policy = session.getArtifactDescriptorPolicy();
323 if ( policy == null )
324 {
325 return ArtifactDescriptorPolicy.STRICT;
326 }
327 return policy.getPolicy( session, new ArtifactDescriptorPolicyRequest( a, request.getRequestContext() ) );
328 }
329
330 }