View Javadoc

1   package org.apache.maven.project.artifact;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.LinkedHashMap;
29  import java.util.LinkedHashSet;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Properties;
33  import java.util.Set;
34  
35  import org.apache.maven.artifact.Artifact;
36  import org.apache.maven.artifact.factory.ArtifactFactory;
37  import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
38  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
39  import org.apache.maven.artifact.metadata.ResolutionGroup;
40  import org.apache.maven.artifact.repository.ArtifactRepository;
41  import org.apache.maven.artifact.repository.metadata.ArtifactRepositoryMetadata;
42  import org.apache.maven.artifact.repository.metadata.Metadata;
43  import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
44  import org.apache.maven.artifact.repository.metadata.RepositoryMetadataManager;
45  import org.apache.maven.artifact.repository.metadata.RepositoryMetadataResolutionException;
46  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
47  import org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException;
48  import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
49  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
50  import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
51  import org.apache.maven.artifact.versioning.ArtifactVersion;
52  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
53  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
54  import org.apache.maven.artifact.versioning.VersionRange;
55  import org.apache.maven.execution.MavenSession;
56  import org.apache.maven.model.Dependency;
57  import org.apache.maven.model.DependencyManagement;
58  import org.apache.maven.model.DistributionManagement;
59  import org.apache.maven.model.Exclusion;
60  import org.apache.maven.model.Relocation;
61  import org.apache.maven.model.building.ModelBuildingException;
62  import org.apache.maven.model.building.ModelBuildingRequest;
63  import org.apache.maven.model.building.ModelProblem;
64  import org.apache.maven.model.resolution.UnresolvableModelException;
65  import org.apache.maven.plugin.LegacySupport;
66  import org.apache.maven.project.DefaultProjectBuildingRequest;
67  import org.apache.maven.project.MavenProject;
68  import org.apache.maven.project.ProjectBuilder;
69  import org.apache.maven.project.ProjectBuildingException;
70  import org.apache.maven.project.ProjectBuildingRequest;
71  import org.apache.maven.properties.internal.EnvironmentUtils;
72  import org.apache.maven.repository.legacy.metadata.DefaultMetadataResolutionRequest;
73  import org.apache.maven.repository.legacy.metadata.MetadataResolutionRequest;
74  import org.codehaus.plexus.PlexusContainer;
75  import org.codehaus.plexus.component.annotations.Component;
76  import org.codehaus.plexus.component.annotations.Requirement;
77  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
78  import org.codehaus.plexus.logging.Logger;
79  import org.sonatype.aether.RepositorySystemSession;
80  import org.sonatype.aether.repository.RepositoryPolicy;
81  import org.sonatype.aether.transfer.ArtifactNotFoundException;
82  
83  /**
84   * @author Jason van Zyl
85   */
86  @Component( role = ArtifactMetadataSource.class, hint = "maven" )
87  public class MavenMetadataSource
88      implements ArtifactMetadataSource
89  {
90      @Requirement
91      private RepositoryMetadataManager repositoryMetadataManager;
92  
93      @Requirement
94      private ArtifactFactory repositorySystem;
95  
96      //TODO: This prevents a cycle in the composition which shows us another problem we need to deal with.
97      //@Requirement
98      private ProjectBuilder projectBuilder;
99  
100     @Requirement
101     private PlexusContainer container;
102 
103     @Requirement
104     private Logger logger;
105 
106     @Requirement
107     private MavenMetadataCache cache;
108 
109     @Requirement
110     private LegacySupport legacySupport;
111 
112     private void injectSession( MetadataResolutionRequest request )
113     {
114         RepositorySystemSession session = legacySupport.getRepositorySession();
115 
116         if ( session != null )
117         {
118             request.setOffline( session.isOffline() );
119             request.setForceUpdate( RepositoryPolicy.UPDATE_POLICY_ALWAYS.equals( session.getUpdatePolicy() ) );
120         }
121     }
122 
123     public ResolutionGroup retrieve( Artifact artifact, ArtifactRepository localRepository,
124                                      List<ArtifactRepository> remoteRepositories )
125         throws ArtifactMetadataRetrievalException
126     {
127         return retrieve( artifact, localRepository, remoteRepositories, false );
128     }
129 
130     public ResolutionGroup retrieve( Artifact artifact, ArtifactRepository localRepository,
131                                      List<ArtifactRepository> remoteRepositories, boolean resolveManagedVersions )
132         throws ArtifactMetadataRetrievalException
133     {
134         MetadataResolutionRequest request = new DefaultMetadataResolutionRequest();
135         injectSession( request );
136         request.setArtifact( artifact );
137         request.setLocalRepository( localRepository );
138         request.setRemoteRepositories( remoteRepositories );
139         request.setResolveManagedVersions( resolveManagedVersions );
140         return retrieve( request );
141     }
142 
143     public ResolutionGroup retrieve( MetadataResolutionRequest request )
144         throws ArtifactMetadataRetrievalException
145     {
146         Artifact artifact = request.getArtifact();
147 
148         //
149         // If we have a system scoped artifact then we do not want any searching in local or remote repositories
150         // and we want artifact resolution to only return the system scoped artifact itself.
151         //
152         if ( artifact.getScope() != null && artifact.getScope().equals( Artifact.SCOPE_SYSTEM ) )
153         {
154             return new ResolutionGroup( null, null, null );
155         }
156 
157         ResolutionGroup cached =
158             cache.get( artifact, request.isResolveManagedVersions(), request.getLocalRepository(),
159                        request.getRemoteRepositories() );
160 
161         if ( cached != null )
162         {
163             // if the POM has no file, we cached a missing artifact, only return the cached data if no update forced
164             if ( !request.isForceUpdate() || hasFile( cached.getPomArtifact() ) )
165             {
166                 return cached;
167             }
168         }
169 
170         List<Dependency> dependencies;
171 
172         List<Dependency> managedDependencies = null;
173 
174         List<ArtifactRepository> pomRepositories = null;
175 
176         Artifact pomArtifact;
177 
178         Artifact relocatedArtifact = null;
179 
180         //TODO: Not even sure this is really required as the project will be cached in the builder, we'll see this
181         // is currently the biggest hotspot
182         if ( artifact instanceof ArtifactWithDependencies )
183         {
184             pomArtifact = artifact;
185 
186             dependencies = ( (ArtifactWithDependencies) artifact ).getDependencies();
187 
188             managedDependencies = ( (ArtifactWithDependencies) artifact ).getManagedDependencies();
189         }
190         else
191         {
192             ProjectRelocation rel = retrieveRelocatedProject( artifact, request );
193 
194             if ( rel == null )
195             {
196                 return null;
197             }
198 
199             pomArtifact = rel.pomArtifact;
200 
201             relocatedArtifact = rel.relocatedArtifact;
202 
203             if ( rel.project == null )
204             {
205                 // When this happens we have a Maven 1.x POM, or some invalid POM. There is still a pile of
206                 // shit in the Maven 2.x repository that should have never found its way into the repository
207                 // but it did.
208                 dependencies = Collections.emptyList();
209             }
210             else
211             {
212                 dependencies = rel.project.getDependencies();
213 
214                 DependencyManagement depMngt = rel.project.getDependencyManagement();
215                 managedDependencies = ( depMngt != null ) ? depMngt.getDependencies() : null;
216 
217                 pomRepositories = rel.project.getRemoteArtifactRepositories();
218             }
219         }
220 
221         Set<Artifact> artifacts = Collections.<Artifact>emptySet();
222 
223         if ( !artifact.getArtifactHandler().isIncludesDependencies() )
224         {
225             artifacts = new LinkedHashSet<Artifact>();
226 
227             for ( Dependency dependency : dependencies )
228             {
229                 Artifact dependencyArtifact = createDependencyArtifact( dependency, artifact, pomArtifact );
230 
231                 if ( dependencyArtifact != null )
232                 {
233                     artifacts.add( dependencyArtifact );
234                 }
235             }
236         }
237 
238         Map<String, Artifact> managedVersions = null;
239 
240         if ( managedDependencies != null && request.isResolveManagedVersions() )
241         {
242             managedVersions = new HashMap<String, Artifact>();
243 
244             for ( Dependency managedDependency : managedDependencies )
245             {
246                 Artifact managedArtifact = createDependencyArtifact( managedDependency, null, pomArtifact );
247 
248                 managedVersions.put( managedDependency.getManagementKey(), managedArtifact );
249             }
250         }
251 
252         List<ArtifactRepository> aggregatedRepositories =
253             aggregateRepositories( request.getRemoteRepositories(), pomRepositories );
254 
255         ResolutionGroup result =
256             new ResolutionGroup( pomArtifact, relocatedArtifact, artifacts, managedVersions, aggregatedRepositories );
257 
258         cache.put( artifact, request.isResolveManagedVersions(), request.getLocalRepository(),
259                    request.getRemoteRepositories(), result );
260 
261         return result;
262     }
263 
264     private boolean hasFile( Artifact artifact )
265     {
266         return artifact != null && artifact.getFile() != null && artifact.getFile().exists();
267     }
268 
269     private List<ArtifactRepository> aggregateRepositories( List<ArtifactRepository> requestRepositories,
270                                                             List<ArtifactRepository> pomRepositories )
271     {
272         List<ArtifactRepository> repositories = requestRepositories;
273 
274         if ( pomRepositories != null && !pomRepositories.isEmpty() )
275         {
276             Map<String, ArtifactRepository> repos = new LinkedHashMap<String, ArtifactRepository>();
277 
278             for ( ArtifactRepository repo : requestRepositories )
279             {
280                 if ( !repos.containsKey( repo.getId() ) )
281                 {
282                     repos.put( repo.getId(), repo );
283                 }
284             }
285 
286             for ( ArtifactRepository repo : pomRepositories )
287             {
288                 if ( !repos.containsKey( repo.getId() ) )
289                 {
290                     repos.put( repo.getId(), repo );
291                 }
292             }
293 
294             repositories = new ArrayList<ArtifactRepository>( repos.values() );
295         }
296 
297         return repositories;
298     }
299 
300     private Artifact createDependencyArtifact( Dependency dependency, Artifact owner, Artifact pom )
301         throws ArtifactMetadataRetrievalException
302     {
303         try
304         {
305             String inheritedScope = ( owner != null ) ? owner.getScope() : null;
306 
307             ArtifactFilter inheritedFilter = ( owner != null ) ? owner.getDependencyFilter() : null;
308 
309             return createDependencyArtifact( repositorySystem, dependency, inheritedScope, inheritedFilter );
310         }
311         catch ( InvalidVersionSpecificationException e )
312         {
313             throw new ArtifactMetadataRetrievalException( "Invalid version for dependency "
314                 + dependency.getManagementKey() + ": " + e.getMessage(), e, pom );
315         }
316     }
317 
318     private static Artifact createDependencyArtifact( ArtifactFactory factory, Dependency dependency,
319                                                       String inheritedScope, ArtifactFilter inheritedFilter )
320         throws InvalidVersionSpecificationException
321     {
322         String effectiveScope = getEffectiveScope( dependency.getScope(), inheritedScope );
323 
324         if ( effectiveScope == null )
325         {
326             return null;
327         }
328 
329         VersionRange versionRange = VersionRange.createFromVersionSpec( dependency.getVersion() );
330 
331         Artifact dependencyArtifact =
332             factory.createDependencyArtifact( dependency.getGroupId(), dependency.getArtifactId(), versionRange,
333                                               dependency.getType(), dependency.getClassifier(), effectiveScope,
334                                               dependency.isOptional() );
335 
336         ArtifactFilter dependencyFilter = inheritedFilter;
337 
338         if ( dependencyFilter != null && !dependencyFilter.include( dependencyArtifact ) )
339         {
340             return null;
341         }
342 
343         if ( Artifact.SCOPE_SYSTEM.equals( effectiveScope ) )
344         {
345             dependencyArtifact.setFile( new File( dependency.getSystemPath() ) );
346         }
347 
348         dependencyArtifact.setDependencyFilter( createDependencyFilter( dependency, dependencyFilter ) );
349 
350         return dependencyArtifact;
351     }
352 
353     private static String getEffectiveScope( String originalScope, String inheritedScope )
354     {
355         String effectiveScope = Artifact.SCOPE_RUNTIME;
356 
357         if ( originalScope == null )
358         {
359             originalScope = Artifact.SCOPE_COMPILE;
360         }
361 
362         if ( inheritedScope == null )
363         {
364             // direct dependency retains its scope
365             effectiveScope = originalScope;
366         }
367         else if ( Artifact.SCOPE_TEST.equals( originalScope ) || Artifact.SCOPE_PROVIDED.equals( originalScope ) )
368         {
369             // test and provided are not transitive, so exclude them
370             effectiveScope = null;
371         }
372         else if ( Artifact.SCOPE_SYSTEM.equals( originalScope ) )
373         {
374             // system scope come through unchanged...
375             effectiveScope = Artifact.SCOPE_SYSTEM;
376         }
377         else if ( Artifact.SCOPE_COMPILE.equals( originalScope ) && Artifact.SCOPE_COMPILE.equals( inheritedScope ) )
378         {
379             // added to retain compile scope. Remove if you want compile inherited as runtime
380             effectiveScope = Artifact.SCOPE_COMPILE;
381         }
382         else if ( Artifact.SCOPE_TEST.equals( inheritedScope ) )
383         {
384             effectiveScope = Artifact.SCOPE_TEST;
385         }
386         else if ( Artifact.SCOPE_PROVIDED.equals( inheritedScope ) )
387         {
388             effectiveScope = Artifact.SCOPE_PROVIDED;
389         }
390 
391         return effectiveScope;
392     }
393 
394     private static ArtifactFilter createDependencyFilter( Dependency dependency, ArtifactFilter inheritedFilter )
395     {
396         ArtifactFilter effectiveFilter = inheritedFilter;
397 
398         if ( !dependency.getExclusions().isEmpty() )
399         {
400             List<String> exclusions = new ArrayList<String>();
401 
402             for ( Exclusion e : dependency.getExclusions() )
403             {
404                 exclusions.add( e.getGroupId() + ':' + e.getArtifactId() );
405             }
406 
407             effectiveFilter = new ExcludesArtifactFilter( exclusions );
408 
409             if ( inheritedFilter != null )
410             {
411                 effectiveFilter = new AndArtifactFilter( Arrays.asList( inheritedFilter, effectiveFilter ) );
412             }
413         }
414 
415         return effectiveFilter;
416     }
417 
418     public List<ArtifactVersion> retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
419                                                             List<ArtifactRepository> remoteRepositories )
420         throws ArtifactMetadataRetrievalException
421     {
422         MetadataResolutionRequest request = new DefaultMetadataResolutionRequest();
423         injectSession( request );
424         request.setArtifact( artifact );
425         request.setLocalRepository( localRepository );
426         request.setRemoteRepositories( remoteRepositories );
427         return retrieveAvailableVersions( request );
428     }
429 
430     public List<ArtifactVersion> retrieveAvailableVersions( MetadataResolutionRequest request )
431         throws ArtifactMetadataRetrievalException
432     {
433         RepositoryMetadata metadata = new ArtifactRepositoryMetadata( request.getArtifact() );
434 
435         try
436         {
437             repositoryMetadataManager.resolve( metadata, request );
438         }
439         catch ( RepositoryMetadataResolutionException e )
440         {
441             throw new ArtifactMetadataRetrievalException( e.getMessage(), e, request.getArtifact() );
442         }
443 
444         List<String> availableVersions = request.getLocalRepository().findVersions( request.getArtifact() );
445 
446         return retrieveAvailableVersionsFromMetadata( metadata.getMetadata(), availableVersions );
447     }
448 
449     public List<ArtifactVersion> retrieveAvailableVersionsFromDeploymentRepository( Artifact artifact,
450                                                                                     ArtifactRepository localRepository,
451                                                                                     ArtifactRepository deploymentRepository )
452         throws ArtifactMetadataRetrievalException
453     {
454         RepositoryMetadata metadata = new ArtifactRepositoryMetadata( artifact );
455 
456         try
457         {
458             repositoryMetadataManager.resolveAlways( metadata, localRepository, deploymentRepository );
459         }
460         catch ( RepositoryMetadataResolutionException e )
461         {
462             throw new ArtifactMetadataRetrievalException( e.getMessage(), e, artifact );
463         }
464 
465         List<String> availableVersions = localRepository.findVersions( artifact );
466 
467         return retrieveAvailableVersionsFromMetadata( metadata.getMetadata(), availableVersions );
468     }
469 
470     private List<ArtifactVersion> retrieveAvailableVersionsFromMetadata( Metadata repoMetadata,
471                                                                          List<String> availableVersions )
472     {
473         Collection<String> versions = new LinkedHashSet<String>();
474 
475         if ( ( repoMetadata != null ) && ( repoMetadata.getVersioning() != null ) )
476         {
477             versions.addAll( repoMetadata.getVersioning().getVersions() );
478         }
479 
480         versions.addAll( availableVersions );
481 
482         List<ArtifactVersion> artifactVersions = new ArrayList<ArtifactVersion>( versions.size() );
483 
484         for ( String version : versions )
485         {
486             artifactVersions.add( new DefaultArtifactVersion( version ) );
487         }
488 
489         return artifactVersions;
490     }
491 
492     // USED BY MAVEN ASSEMBLY PLUGIN
493     @Deprecated
494     public static Set<Artifact> createArtifacts( ArtifactFactory artifactFactory, List<Dependency> dependencies,
495                                                  String inheritedScope, ArtifactFilter dependencyFilter,
496                                                  MavenProject project )
497         throws InvalidDependencyVersionException
498     {
499         Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
500 
501         for ( Dependency d : dependencies )
502         {
503             Artifact dependencyArtifact;
504             try
505             {
506                 dependencyArtifact = createDependencyArtifact( artifactFactory, d, inheritedScope, dependencyFilter );
507             }
508             catch ( InvalidVersionSpecificationException e )
509             {
510                 throw new InvalidDependencyVersionException( project.getId(), d, project.getFile(), e );
511             }
512 
513             if ( dependencyArtifact != null )
514             {
515                 artifacts.add( dependencyArtifact );
516             }
517         }
518 
519         return artifacts;
520     }
521 
522     private ProjectBuilder getProjectBuilder()
523     {
524         if ( projectBuilder != null )
525         {
526             return projectBuilder;
527         }
528 
529         try
530         {
531             projectBuilder = container.lookup( ProjectBuilder.class );
532         }
533         catch ( ComponentLookupException e )
534         {
535             // Won't happen
536         }
537 
538         return projectBuilder;
539     }
540 
541     private ProjectRelocation retrieveRelocatedProject( Artifact artifact, MetadataResolutionRequest repositoryRequest )
542         throws ArtifactMetadataRetrievalException
543     {
544         MavenProject project;
545 
546         Artifact pomArtifact;
547         Artifact relocatedArtifact = null;
548         boolean done = false;
549         do
550         {
551             project = null;
552 
553             pomArtifact =
554                 repositorySystem.createProjectArtifact( artifact.getGroupId(),
555                                                         artifact.getArtifactId(),
556                                                         artifact.getVersion(), artifact.getScope() );
557 
558             if ( "pom".equals( artifact.getType() ) )
559             {
560                 pomArtifact.setFile( artifact.getFile() );
561             }
562 
563             if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
564             {
565                 done = true;
566             }
567             else
568             {
569                 try
570                 {
571                     ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
572                     configuration.setLocalRepository( repositoryRequest.getLocalRepository() );
573                     configuration.setRemoteRepositories( repositoryRequest.getRemoteRepositories() );
574                     configuration.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
575                     configuration.setProcessPlugins( false );
576                     configuration.setRepositoryMerging( ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT );
577                     configuration.setSystemProperties( getSystemProperties() );
578                     configuration.setRepositorySession( legacySupport.getRepositorySession() );
579 
580                     project = getProjectBuilder().build( pomArtifact, configuration ).getProject();
581                 }
582                 catch ( ProjectBuildingException e )
583                 {
584                     ModelProblem missingParentPom = hasMissingParentPom( e );
585                     if ( missingParentPom != null )
586                     {
587                         throw new ArtifactMetadataRetrievalException( "Failed to process POM for "
588                             + artifact.getId() + ": " + missingParentPom.getMessage(),
589                                                                       missingParentPom.getException(),
590                                                                       artifact );
591                     }
592 
593                     String message;
594 
595                     if ( isMissingPom( e ) )
596                     {
597                         message = "Missing POM for " + artifact.getId();
598                     }
599                     else if ( isNonTransferrablePom( e ) )
600                     {
601                         throw new ArtifactMetadataRetrievalException( "Failed to retrieve POM for "
602                             + artifact.getId() + ": " + e.getCause().getMessage(), e.getCause(),
603                                                                       artifact );
604                     }
605                     else
606                     {
607                         message =
608                             "Invalid POM for " + artifact.getId()
609                                 + ", transitive dependencies (if any) will not be available"
610                                 + ", enable debug logging for more details";
611                     }
612 
613                     if ( logger.isDebugEnabled() )
614                     {
615                         message += ": " + e.getMessage();
616                     }
617 
618                     logger.warn( message );
619                 }
620 
621                 if ( project != null )
622                 {
623                     Relocation relocation = null;
624 
625                     DistributionManagement distMgmt = project.getDistributionManagement();
626                     if ( distMgmt != null )
627                     {
628                         relocation = distMgmt.getRelocation();
629 
630                         artifact.setDownloadUrl( distMgmt.getDownloadUrl() );
631                         pomArtifact.setDownloadUrl( distMgmt.getDownloadUrl() );
632                     }
633 
634                     if ( relocation != null )
635                     {
636                         if ( relocation.getGroupId() != null )
637                         {
638                             artifact.setGroupId( relocation.getGroupId() );
639                             relocatedArtifact = artifact;
640                             project.setGroupId( relocation.getGroupId() );
641                         }
642                         if ( relocation.getArtifactId() != null )
643                         {
644                             artifact.setArtifactId( relocation.getArtifactId() );
645                             relocatedArtifact = artifact;
646                             project.setArtifactId( relocation.getArtifactId() );
647                         }
648                         if ( relocation.getVersion() != null )
649                         {
650                             // note: see MNG-3454. This causes a problem, but fixing it may break more.
651                             artifact.setVersionRange( VersionRange.createFromVersion( relocation.getVersion() ) );
652                             relocatedArtifact = artifact;
653                             project.setVersion( relocation.getVersion() );
654                         }
655 
656                         if ( artifact.getDependencyFilter() != null
657                             && !artifact.getDependencyFilter().include( artifact ) )
658                         {
659                             return null;
660                         }
661 
662                         // MNG-2861: the artifact data has changed. If the available versions where previously
663                         // retrieved, we need to update it.
664                         // TODO: shouldn't the versions be merged across relocations?
665                         List<ArtifactVersion> available = artifact.getAvailableVersions();
666                         if ( available != null && !available.isEmpty() )
667                         {
668                             MetadataResolutionRequest metadataRequest =
669                                 new DefaultMetadataResolutionRequest( repositoryRequest );
670                             metadataRequest.setArtifact( artifact );
671                             available = retrieveAvailableVersions( metadataRequest );
672                             artifact.setAvailableVersions( available );
673                         }
674 
675                         String message =
676                             "\n  This artifact has been relocated to " + artifact.getGroupId() + ":"
677                                 + artifact.getArtifactId() + ":" + artifact.getVersion() + ".\n";
678 
679                         if ( relocation.getMessage() != null )
680                         {
681                             message += "  " + relocation.getMessage() + "\n";
682                         }
683 
684                         if ( artifact.getDependencyTrail() != null && artifact.getDependencyTrail().size() == 1 )
685                         {
686                             logger.warn( "While downloading " + pomArtifact.getGroupId() + ":"
687                                 + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message + "\n" );
688                         }
689                         else
690                         {
691                             logger.debug( "While downloading " + pomArtifact.getGroupId() + ":"
692                                 + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message + "\n" );
693                         }
694                     }
695                     else
696                     {
697                         done = true;
698                     }
699                 }
700                 else
701                 {
702                     done = true;
703                 }
704             }
705         }
706         while ( !done );
707 
708         ProjectRelocation rel = new ProjectRelocation();
709         rel.project = project;
710         rel.pomArtifact = pomArtifact;
711         rel.relocatedArtifact = relocatedArtifact;
712 
713         return rel;
714     }
715 
716     private ModelProblem hasMissingParentPom( ProjectBuildingException e )
717     {
718         if ( e.getCause() instanceof ModelBuildingException )
719         {
720             ModelBuildingException mbe = (ModelBuildingException) e.getCause();
721             for ( ModelProblem problem : mbe.getProblems() )
722             {
723                 if ( problem.getException() instanceof UnresolvableModelException )
724                 {
725                     return problem;
726                 }
727             }
728 
729         }
730         return null;
731     }
732 
733     private boolean isMissingPom( Exception e )
734     {
735         if ( e.getCause() instanceof MultipleArtifactsNotFoundException )
736         {
737             return true;
738         }
739         if ( e.getCause() instanceof org.sonatype.aether.resolution.ArtifactResolutionException
740             && e.getCause().getCause() instanceof ArtifactNotFoundException )
741         {
742             return true;
743         }
744         return false;
745     }
746 
747     private boolean isNonTransferrablePom( Exception e )
748     {
749         if ( e.getCause() instanceof ArtifactResolutionException )
750         {
751             return true;
752         }
753         if ( e.getCause() instanceof org.sonatype.aether.resolution.ArtifactResolutionException
754             && !( e.getCause().getCause() instanceof ArtifactNotFoundException ) )
755         {
756             return true;
757         }
758         return false;
759     }
760 
761     private Properties getSystemProperties()
762     {
763         Properties props = new Properties();
764 
765         EnvironmentUtils.addEnvVars( props );
766 
767         props.putAll( System.getProperties() );
768 
769         return props;
770     }
771 
772     private static final class ProjectRelocation
773     {
774         private MavenProject project;
775 
776         private Artifact pomArtifact;
777 
778         private Artifact relocatedArtifact;
779     }
780 
781 }