1 | |
package org.apache.maven.project.artifact; |
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
import java.io.File; |
23 | |
import java.util.ArrayList; |
24 | |
import java.util.Collections; |
25 | |
import java.util.HashSet; |
26 | |
import java.util.Iterator; |
27 | |
import java.util.LinkedHashSet; |
28 | |
import java.util.List; |
29 | |
import java.util.Set; |
30 | |
|
31 | |
import org.apache.maven.artifact.Artifact; |
32 | |
import org.apache.maven.artifact.factory.ArtifactFactory; |
33 | |
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException; |
34 | |
import org.apache.maven.artifact.metadata.ArtifactMetadataSource; |
35 | |
import org.apache.maven.artifact.metadata.ResolutionGroup; |
36 | |
import org.apache.maven.artifact.repository.ArtifactRepository; |
37 | |
import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata; |
38 | |
import org.apache.maven.artifact.repository.metadata.Metadata; |
39 | |
import org.apache.maven.artifact.repository.metadata.RepositoryMetadata; |
40 | |
import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager; |
41 | |
import org.apache.maven.artifact.repository.metadata.RepositoryMetadataResolutionException; |
42 | |
import org.apache.maven.artifact.resolver.filter.AndArtifactFilter; |
43 | |
import org.apache.maven.artifact.resolver.filter.ArtifactFilter; |
44 | |
import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; |
45 | |
import org.apache.maven.artifact.versioning.DefaultArtifactVersion; |
46 | |
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; |
47 | |
import org.apache.maven.artifact.versioning.VersionRange; |
48 | |
import org.apache.maven.model.Dependency; |
49 | |
import org.apache.maven.model.DistributionManagement; |
50 | |
import org.apache.maven.model.Exclusion; |
51 | |
import org.apache.maven.model.Relocation; |
52 | |
import org.apache.maven.project.DefaultProjectBuilderConfiguration; |
53 | |
import org.apache.maven.project.InvalidProjectModelException; |
54 | |
import org.apache.maven.project.MavenProject; |
55 | |
import org.apache.maven.project.MavenProjectBuilder; |
56 | |
import org.apache.maven.project.ProjectBuildingException; |
57 | |
import org.apache.maven.project.validation.ModelValidationResult; |
58 | |
import org.codehaus.plexus.logging.AbstractLogEnabled; |
59 | |
import org.codehaus.plexus.util.StringUtils; |
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | 13 | public class MavenMetadataSource |
67 | |
extends AbstractLogEnabled |
68 | |
implements ArtifactMetadataSource |
69 | |
{ |
70 | |
public static final String ROLE_HINT = "maven"; |
71 | |
|
72 | |
private MavenProjectBuilder mavenProjectBuilder; |
73 | |
|
74 | |
private ArtifactFactory artifactFactory; |
75 | |
|
76 | |
private RepositoryMetadataManager repositoryMetadataManager; |
77 | |
|
78 | |
|
79 | |
private MavenProject superProject; |
80 | |
|
81 | 13 | private Set warnedPoms = new HashSet(); |
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
public Artifact retrieveRelocatedArtifact( Artifact artifact, ArtifactRepository localRepository, List remoteRepositories ) |
87 | |
throws ArtifactMetadataRetrievalException |
88 | |
{ |
89 | 48 | if ( artifact instanceof ActiveProjectArtifact ) |
90 | |
{ |
91 | 0 | return artifact; |
92 | |
} |
93 | |
|
94 | 48 | ProjectRelocation rel = retrieveRelocatedProject( artifact, localRepository, remoteRepositories ); |
95 | |
|
96 | 48 | if ( rel == null ) |
97 | |
{ |
98 | 0 | return artifact; |
99 | |
} |
100 | |
|
101 | 48 | MavenProject project = rel.project; |
102 | 48 | if ( project == null || getRelocationKey( artifact ).equals( getRelocationKey( project.getArtifact() ) ) ) |
103 | |
{ |
104 | 48 | return artifact; |
105 | |
} |
106 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
|
112 | |
|
113 | |
|
114 | 0 | Artifact result = null; |
115 | 0 | if ( artifact.getClassifier() != null ) |
116 | |
{ |
117 | 0 | result = artifactFactory.createArtifactWithClassifier( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getType(), artifact.getClassifier() ); |
118 | |
} |
119 | |
else |
120 | |
{ |
121 | 0 | result = artifactFactory.createArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getScope(), artifact.getType() ); |
122 | |
} |
123 | |
|
124 | 0 | result.setResolved( artifact.isResolved() ); |
125 | 0 | result.setFile( artifact.getFile() ); |
126 | |
|
127 | 0 | result.setScope( artifact.getScope() ); |
128 | 0 | result.setArtifactHandler( artifact.getArtifactHandler() ); |
129 | 0 | result.setDependencyFilter( artifact.getDependencyFilter() ); |
130 | 0 | result.setDependencyTrail( artifact.getDependencyTrail() ); |
131 | 0 | result.setOptional( artifact.isOptional() ); |
132 | 0 | result.setRelease( artifact.isRelease() ); |
133 | |
|
134 | 0 | return result; |
135 | |
} |
136 | |
|
137 | |
private String getRelocationKey( Artifact artifact ) |
138 | |
{ |
139 | 96 | return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion(); |
140 | |
} |
141 | |
|
142 | |
private ProjectRelocation retrieveRelocatedProject( Artifact artifact, ArtifactRepository localRepository, List remoteRepositories ) |
143 | |
throws ArtifactMetadataRetrievalException |
144 | |
{ |
145 | 96 | MavenProject project = null; |
146 | |
|
147 | |
Artifact pomArtifact; |
148 | 96 | boolean done = false; |
149 | |
do |
150 | |
{ |
151 | |
|
152 | 96 | pomArtifact = artifactFactory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(), |
153 | |
artifact.getVersion(), artifact.getScope() ); |
154 | |
|
155 | 96 | if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) ) |
156 | |
{ |
157 | 0 | done = true; |
158 | |
} |
159 | |
else |
160 | |
{ |
161 | |
try |
162 | |
{ |
163 | 96 | project = mavenProjectBuilder.buildFromRepository( pomArtifact, remoteRepositories, localRepository, |
164 | |
true ); |
165 | |
} |
166 | 0 | catch ( InvalidProjectModelException e ) |
167 | |
{ |
168 | 0 | String id = pomArtifact.getId(); |
169 | |
|
170 | 0 | if ( !warnedPoms.contains( id ) ) |
171 | |
{ |
172 | 0 | warnedPoms.add( pomArtifact.getId() ); |
173 | |
|
174 | 0 | getLogger().warn( "POM for \'" |
175 | |
+ pomArtifact |
176 | |
+ "\' is invalid.\n\nIts dependencies (if any) will NOT be available to the current build." ); |
177 | |
|
178 | 0 | if ( getLogger().isDebugEnabled() ) |
179 | |
{ |
180 | 0 | getLogger().debug( "Reason: " + e.getMessage() ); |
181 | |
|
182 | 0 | ModelValidationResult validationResult = e.getValidationResult(); |
183 | |
|
184 | 0 | if ( validationResult != null ) |
185 | |
{ |
186 | 0 | getLogger().debug( "\nValidation Errors:" ); |
187 | 0 | for ( Iterator i = validationResult.getMessages().iterator(); i.hasNext(); ) |
188 | |
{ |
189 | 0 | getLogger().debug( i.next().toString() ); |
190 | |
} |
191 | 0 | getLogger().debug( "\n" ); |
192 | |
} |
193 | |
} |
194 | |
} |
195 | |
|
196 | 0 | project = null; |
197 | |
} |
198 | 0 | catch ( ProjectBuildingException e ) |
199 | |
{ |
200 | 0 | throw new ArtifactMetadataRetrievalException( "Unable to read the metadata file for artifact '" + |
201 | |
artifact.getDependencyConflictId() + "': " + e.getMessage(), e, artifact ); |
202 | 96 | } |
203 | |
|
204 | 96 | if ( project != null ) |
205 | |
{ |
206 | 96 | Relocation relocation = null; |
207 | |
|
208 | 96 | DistributionManagement distMgmt = project.getDistributionManagement(); |
209 | 96 | if ( distMgmt != null ) |
210 | |
{ |
211 | 0 | relocation = distMgmt.getRelocation(); |
212 | |
|
213 | 0 | artifact.setDownloadUrl( distMgmt.getDownloadUrl() ); |
214 | 0 | pomArtifact.setDownloadUrl( distMgmt.getDownloadUrl() ); |
215 | |
} |
216 | |
|
217 | 96 | if ( relocation != null ) |
218 | |
{ |
219 | 0 | if ( relocation.getGroupId() != null ) |
220 | |
{ |
221 | 0 | artifact.setGroupId( relocation.getGroupId() ); |
222 | 0 | project.setGroupId( relocation.getGroupId() ); |
223 | |
} |
224 | 0 | if ( relocation.getArtifactId() != null ) |
225 | |
{ |
226 | 0 | artifact.setArtifactId( relocation.getArtifactId() ); |
227 | 0 | project.setArtifactId( relocation.getArtifactId() ); |
228 | |
} |
229 | 0 | if ( relocation.getVersion() != null ) |
230 | |
{ |
231 | |
|
232 | 0 | artifact.setVersionRange( VersionRange.createFromVersion( relocation.getVersion() ) ); |
233 | 0 | project.setVersion( relocation.getVersion() ); |
234 | |
} |
235 | |
|
236 | 0 | if ( artifact.getDependencyFilter() != null && |
237 | |
!artifact.getDependencyFilter().include( artifact ) ) |
238 | |
{ |
239 | 0 | return null; |
240 | |
} |
241 | |
|
242 | |
|
243 | |
|
244 | 0 | List available = artifact.getAvailableVersions(); |
245 | 0 | if ( available != null && !available.isEmpty() ) |
246 | |
{ |
247 | 0 | artifact.setAvailableVersions( retrieveAvailableVersions( artifact, localRepository, |
248 | |
remoteRepositories ) ); |
249 | |
|
250 | |
} |
251 | |
|
252 | 0 | String message = "\n This artifact has been relocated to " + artifact.getGroupId() + ":" + |
253 | |
artifact.getArtifactId() + ":" + artifact.getVersion() + ".\n"; |
254 | |
|
255 | 0 | if ( relocation.getMessage() != null ) |
256 | |
{ |
257 | 0 | message += " " + relocation.getMessage() + "\n"; |
258 | |
} |
259 | |
|
260 | 0 | if ( artifact.getDependencyTrail() != null && artifact.getDependencyTrail().size() == 1 ) |
261 | |
{ |
262 | 0 | getLogger().warn( "While downloading " + pomArtifact.getGroupId() + ":" + |
263 | |
pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message + "\n" ); |
264 | |
} |
265 | |
else |
266 | |
{ |
267 | 0 | getLogger().debug( "While downloading " + pomArtifact.getGroupId() + ":" + |
268 | |
pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message + "\n" ); |
269 | |
} |
270 | |
} |
271 | |
else |
272 | |
{ |
273 | 96 | done = true; |
274 | |
} |
275 | |
} |
276 | |
else |
277 | |
{ |
278 | 0 | done = true; |
279 | |
} |
280 | |
} |
281 | |
} |
282 | 96 | while ( !done ); |
283 | |
|
284 | 96 | ProjectRelocation rel = new ProjectRelocation(); |
285 | 96 | rel.project = project; |
286 | 96 | rel.pomArtifact = pomArtifact; |
287 | |
|
288 | 96 | return rel; |
289 | |
} |
290 | |
|
291 | |
|
292 | |
|
293 | |
|
294 | |
|
295 | |
|
296 | |
public ResolutionGroup retrieve( Artifact artifact, ArtifactRepository localRepository, List remoteRepositories ) |
297 | |
throws ArtifactMetadataRetrievalException |
298 | |
{ |
299 | 48 | ProjectRelocation rel = retrieveRelocatedProject( artifact, localRepository, remoteRepositories ); |
300 | |
|
301 | 48 | if ( rel == null ) |
302 | |
{ |
303 | 0 | return null; |
304 | |
} |
305 | |
|
306 | 48 | MavenProject project = rel.project; |
307 | 48 | Artifact pomArtifact = rel.pomArtifact; |
308 | |
|
309 | |
|
310 | 48 | if ( artifact.getDownloadUrl() == null && pomArtifact != null ) |
311 | |
{ |
312 | |
|
313 | 48 | artifact.setDownloadUrl( pomArtifact.getDownloadUrl() ); |
314 | |
} |
315 | |
|
316 | |
ResolutionGroup result; |
317 | |
|
318 | 48 | if ( project == null ) |
319 | |
{ |
320 | |
|
321 | |
|
322 | |
|
323 | 0 | result = new ResolutionGroup( pomArtifact, Collections.EMPTY_SET, Collections.EMPTY_LIST ); |
324 | |
} |
325 | |
else |
326 | |
{ |
327 | 48 | Set artifacts = Collections.EMPTY_SET; |
328 | 48 | if ( !artifact.getArtifactHandler().isIncludesDependencies() ) |
329 | |
{ |
330 | |
|
331 | |
|
332 | |
try |
333 | |
{ |
334 | 48 | artifacts = project.createArtifacts( artifactFactory, artifact.getScope(), |
335 | |
artifact.getDependencyFilter() ); |
336 | |
} |
337 | 0 | catch ( InvalidDependencyVersionException e ) |
338 | |
{ |
339 | 0 | throw new ArtifactMetadataRetrievalException( "Error in metadata for artifact '" + |
340 | |
artifact.getDependencyConflictId() + "': " + e.getMessage(), e ); |
341 | 48 | } |
342 | |
} |
343 | |
|
344 | 48 | List repositories = aggregateRepositoryLists( remoteRepositories, project.getRemoteArtifactRepositories() ); |
345 | |
|
346 | 48 | result = new ResolutionGroup( pomArtifact, artifacts, repositories ); |
347 | |
} |
348 | |
|
349 | 48 | return result; |
350 | |
} |
351 | |
|
352 | |
private List aggregateRepositoryLists( List remoteRepositories, List remoteArtifactRepositories ) |
353 | |
throws ArtifactMetadataRetrievalException |
354 | |
{ |
355 | 48 | if ( superProject == null ) |
356 | |
{ |
357 | |
try |
358 | |
{ |
359 | 10 | superProject = mavenProjectBuilder.buildStandaloneSuperProject( new DefaultProjectBuilderConfiguration() ); |
360 | |
} |
361 | 0 | catch ( ProjectBuildingException e ) |
362 | |
{ |
363 | 0 | throw new ArtifactMetadataRetrievalException( |
364 | |
"Unable to parse the Maven built-in model: " + e.getMessage(), e ); |
365 | 10 | } |
366 | |
} |
367 | |
|
368 | 48 | List repositories = new ArrayList(); |
369 | |
|
370 | 48 | repositories.addAll( remoteRepositories ); |
371 | |
|
372 | |
|
373 | 48 | for ( Iterator it = superProject.getRemoteArtifactRepositories().iterator(); it.hasNext(); ) |
374 | |
{ |
375 | 48 | ArtifactRepository superRepo = (ArtifactRepository) it.next(); |
376 | |
|
377 | 48 | for ( Iterator aggregatedIterator = repositories.iterator(); aggregatedIterator.hasNext(); ) |
378 | |
{ |
379 | 48 | ArtifactRepository repo = (ArtifactRepository) aggregatedIterator.next(); |
380 | |
|
381 | |
|
382 | |
|
383 | |
|
384 | |
|
385 | 48 | if ( repo.getId().equals( superRepo.getId() ) && repo.getUrl().equals( superRepo.getUrl() ) ) |
386 | |
{ |
387 | 33 | aggregatedIterator.remove(); |
388 | |
} |
389 | |
} |
390 | |
} |
391 | |
|
392 | |
|
393 | 48 | for ( Iterator it = remoteArtifactRepositories.iterator(); it.hasNext(); ) |
394 | |
{ |
395 | 48 | ArtifactRepository repository = (ArtifactRepository) it.next(); |
396 | |
|
397 | 48 | if ( !repositories.contains( repository ) ) |
398 | |
{ |
399 | 33 | repositories.add( repository ); |
400 | |
} |
401 | |
} |
402 | |
|
403 | 48 | return repositories; |
404 | |
} |
405 | |
|
406 | |
|
407 | |
|
408 | |
|
409 | |
|
410 | |
public static Set createArtifacts( ArtifactFactory artifactFactory, List dependencies, String inheritedScope, |
411 | |
ArtifactFilter dependencyFilter, MavenProject project ) |
412 | |
throws InvalidDependencyVersionException |
413 | |
{ |
414 | 79 | Set projectArtifacts = new LinkedHashSet( dependencies.size() ); |
415 | |
|
416 | 79 | for ( Iterator i = dependencies.iterator(); i.hasNext(); ) |
417 | |
{ |
418 | 73 | Dependency d = (Dependency) i.next(); |
419 | |
|
420 | 73 | String scope = d.getScope(); |
421 | |
|
422 | 73 | if ( StringUtils.isEmpty( scope ) ) |
423 | |
{ |
424 | 33 | scope = Artifact.SCOPE_COMPILE; |
425 | |
|
426 | 33 | d.setScope( scope ); |
427 | |
} |
428 | |
|
429 | |
VersionRange versionRange; |
430 | |
try |
431 | |
{ |
432 | 73 | versionRange = VersionRange.createFromVersionSpec( d.getVersion() ); |
433 | |
} |
434 | 0 | catch ( InvalidVersionSpecificationException e ) |
435 | |
{ |
436 | 0 | throw new InvalidDependencyVersionException( "Unable to parse version '" + d.getVersion() + |
437 | |
"' for dependency '" + d.getManagementKey() + "': " + e.getMessage(), e ); |
438 | 73 | } |
439 | 73 | Artifact artifact = artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), |
440 | |
versionRange, d.getType(), d.getClassifier(), |
441 | |
scope, inheritedScope, d.isOptional() ); |
442 | |
|
443 | 73 | if ( Artifact.SCOPE_SYSTEM.equals( scope ) ) |
444 | |
{ |
445 | 0 | artifact.setFile( new File( d.getSystemPath() ) ); |
446 | |
} |
447 | |
|
448 | 73 | ArtifactFilter artifactFilter = dependencyFilter; |
449 | |
|
450 | |
|
451 | |
|
452 | |
|
453 | |
|
454 | |
|
455 | 73 | if ( artifact != null && ( artifactFilter == null || artifactFilter.include( artifact ) ) ) |
456 | |
{ |
457 | 71 | if ( d.getExclusions() != null && !d.getExclusions().isEmpty() ) |
458 | |
{ |
459 | 1 | List exclusions = new ArrayList(); |
460 | 1 | for ( Iterator j = d.getExclusions().iterator(); j.hasNext(); ) |
461 | |
{ |
462 | 1 | Exclusion e = (Exclusion) j.next(); |
463 | 1 | exclusions.add( e.getGroupId() + ":" + e.getArtifactId() ); |
464 | |
} |
465 | |
|
466 | 1 | ArtifactFilter newFilter = new ExcludesArtifactFilter( exclusions ); |
467 | |
|
468 | 1 | if ( artifactFilter != null ) |
469 | |
{ |
470 | 1 | AndArtifactFilter filter = new AndArtifactFilter(); |
471 | 1 | filter.add( artifactFilter ); |
472 | 1 | filter.add( newFilter ); |
473 | 1 | artifactFilter = filter; |
474 | |
} |
475 | |
else |
476 | |
{ |
477 | 0 | artifactFilter = newFilter; |
478 | |
} |
479 | |
} |
480 | |
|
481 | 71 | artifact.setDependencyFilter( artifactFilter ); |
482 | |
|
483 | 71 | if ( project != null ) |
484 | |
{ |
485 | 71 | artifact = project.replaceWithActiveArtifact( artifact ); |
486 | |
} |
487 | |
|
488 | 71 | projectArtifacts.add( artifact ); |
489 | |
} |
490 | |
} |
491 | |
|
492 | 79 | return projectArtifacts; |
493 | |
} |
494 | |
|
495 | |
public List retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository, |
496 | |
List remoteRepositories ) |
497 | |
throws ArtifactMetadataRetrievalException |
498 | |
{ |
499 | 0 | RepositoryMetadata metadata = new ArtifactRepositoryMetadata( artifact ); |
500 | |
try |
501 | |
{ |
502 | 0 | repositoryMetadataManager.resolve( metadata, remoteRepositories, localRepository ); |
503 | |
} |
504 | 0 | catch ( RepositoryMetadataResolutionException e ) |
505 | |
{ |
506 | 0 | throw new ArtifactMetadataRetrievalException( e.getMessage(), e ); |
507 | 0 | } |
508 | |
|
509 | |
List versions; |
510 | 0 | Metadata repoMetadata = metadata.getMetadata(); |
511 | 0 | if ( repoMetadata != null && repoMetadata.getVersioning() != null ) |
512 | |
{ |
513 | 0 | List metadataVersions = repoMetadata.getVersioning().getVersions(); |
514 | 0 | versions = new ArrayList( metadataVersions.size() ); |
515 | 0 | for ( Iterator i = metadataVersions.iterator(); i.hasNext(); ) |
516 | |
{ |
517 | 0 | String version = (String) i.next(); |
518 | 0 | versions.add( new DefaultArtifactVersion( version ) ); |
519 | |
} |
520 | |
} |
521 | |
else |
522 | |
{ |
523 | 0 | versions = Collections.EMPTY_LIST; |
524 | |
} |
525 | |
|
526 | 0 | return versions; |
527 | |
} |
528 | |
|
529 | 13 | private static final class ProjectRelocation |
530 | |
{ |
531 | |
private MavenProject project; |
532 | |
private Artifact pomArtifact; |
533 | |
} |
534 | |
|
535 | |
} |