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.model.Dependency;
56  import org.apache.maven.model.DependencyManagement;
57  import org.apache.maven.model.DistributionManagement;
58  import org.apache.maven.model.Exclusion;
59  import org.apache.maven.model.Relocation;
60  import org.apache.maven.model.building.ModelBuildingException;
61  import org.apache.maven.model.building.ModelBuildingRequest;
62  import org.apache.maven.model.building.ModelProblem;
63  import org.apache.maven.model.resolution.UnresolvableModelException;
64  import org.apache.maven.plugin.LegacySupport;
65  import org.apache.maven.project.DefaultProjectBuildingRequest;
66  import org.apache.maven.project.MavenProject;
67  import org.apache.maven.project.ProjectBuilder;
68  import org.apache.maven.project.ProjectBuildingException;
69  import org.apache.maven.project.ProjectBuildingRequest;
70  import org.apache.maven.properties.internal.EnvironmentUtils;
71  import org.apache.maven.properties.internal.SystemProperties;
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.eclipse.aether.RepositorySystemSession;
80  import org.eclipse.aether.repository.RepositoryPolicy;
81  import org.eclipse.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         // if the POM has no file, we cached a missing artifact, only return the cached data if no update forced
163             && ( !request.isForceUpdate() || hasFile( cached.getPomArtifact() ) ) )
164         {
165             return cached;
166         }
167 
168         List<Dependency> dependencies;
169 
170         List<Dependency> managedDependencies = null;
171 
172         List<ArtifactRepository> pomRepositories = null;
173 
174         Artifact pomArtifact;
175 
176         Artifact relocatedArtifact = null;
177 
178         //TODO: Not even sure this is really required as the project will be cached in the builder, we'll see this
179         // is currently the biggest hotspot
180         if ( artifact instanceof ArtifactWithDependencies )
181         {
182             pomArtifact = artifact;
183 
184             dependencies = ( (ArtifactWithDependencies) artifact ).getDependencies();
185 
186             managedDependencies = ( (ArtifactWithDependencies) artifact ).getManagedDependencies();
187         }
188         else
189         {
190             ProjectRelocation rel = retrieveRelocatedProject( artifact, request );
191 
192             if ( rel == null )
193             {
194                 return null;
195             }
196 
197             pomArtifact = rel.pomArtifact;
198 
199             relocatedArtifact = rel.relocatedArtifact;
200 
201             if ( rel.project == null )
202             {
203                 // When this happens we have a Maven 1.x POM, or some invalid POM.
204                 // It should have never found its way into Maven 2.x repository but it did.
205                 dependencies = Collections.emptyList();
206             }
207             else
208             {
209                 dependencies = rel.project.getDependencies();
210 
211                 DependencyManagement depMngt = rel.project.getDependencyManagement();
212                 managedDependencies = ( depMngt != null ) ? depMngt.getDependencies() : null;
213 
214                 pomRepositories = rel.project.getRemoteArtifactRepositories();
215             }
216         }
217 
218         Set<Artifact> artifacts = Collections.<Artifact>emptySet();
219 
220         if ( !artifact.getArtifactHandler().isIncludesDependencies() )
221         {
222             artifacts = new LinkedHashSet<Artifact>();
223 
224             for ( Dependency dependency : dependencies )
225             {
226                 Artifact dependencyArtifact = createDependencyArtifact( dependency, artifact, pomArtifact );
227 
228                 if ( dependencyArtifact != null )
229                 {
230                     artifacts.add( dependencyArtifact );
231                 }
232             }
233         }
234 
235         Map<String, Artifact> managedVersions = null;
236 
237         if ( managedDependencies != null && request.isResolveManagedVersions() )
238         {
239             managedVersions = new HashMap<String, Artifact>();
240 
241             for ( Dependency managedDependency : managedDependencies )
242             {
243                 Artifact managedArtifact = createDependencyArtifact( managedDependency, null, pomArtifact );
244 
245                 managedVersions.put( managedDependency.getManagementKey(), managedArtifact );
246             }
247         }
248 
249         List<ArtifactRepository> aggregatedRepositories =
250             aggregateRepositories( request.getRemoteRepositories(), pomRepositories );
251 
252         ResolutionGroup result =
253             new ResolutionGroup( pomArtifact, relocatedArtifact, artifacts, managedVersions, aggregatedRepositories );
254 
255         cache.put( artifact, request.isResolveManagedVersions(), request.getLocalRepository(),
256                    request.getRemoteRepositories(), result );
257 
258         return result;
259     }
260 
261     private boolean hasFile( Artifact artifact )
262     {
263         return artifact != null && artifact.getFile() != null && artifact.getFile().exists();
264     }
265 
266     private List<ArtifactRepository> aggregateRepositories( List<ArtifactRepository> requestRepositories,
267                                                             List<ArtifactRepository> pomRepositories )
268     {
269         List<ArtifactRepository> repositories = requestRepositories;
270 
271         if ( pomRepositories != null && !pomRepositories.isEmpty() )
272         {
273             Map<String, ArtifactRepository> repos = new LinkedHashMap<String, ArtifactRepository>();
274 
275             for ( ArtifactRepository repo : requestRepositories )
276             {
277                 if ( !repos.containsKey( repo.getId() ) )
278                 {
279                     repos.put( repo.getId(), repo );
280                 }
281             }
282 
283             for ( ArtifactRepository repo : pomRepositories )
284             {
285                 if ( !repos.containsKey( repo.getId() ) )
286                 {
287                     repos.put( repo.getId(), repo );
288                 }
289             }
290 
291             repositories = new ArrayList<ArtifactRepository>( repos.values() );
292         }
293 
294         return repositories;
295     }
296 
297     private Artifact createDependencyArtifact( Dependency dependency, Artifact owner, Artifact pom )
298         throws ArtifactMetadataRetrievalException
299     {
300         try
301         {
302             String inheritedScope = ( owner != null ) ? owner.getScope() : null;
303 
304             ArtifactFilter inheritedFilter = ( owner != null ) ? owner.getDependencyFilter() : null;
305 
306             return createDependencyArtifact( repositorySystem, dependency, inheritedScope, inheritedFilter );
307         }
308         catch ( InvalidVersionSpecificationException e )
309         {
310             throw new ArtifactMetadataRetrievalException( "Invalid version for dependency "
311                 + dependency.getManagementKey() + ": " + e.getMessage(), e, pom );
312         }
313     }
314 
315     private static Artifact createDependencyArtifact( ArtifactFactory factory, Dependency dependency,
316                                                       String inheritedScope, ArtifactFilter inheritedFilter )
317         throws InvalidVersionSpecificationException
318     {
319         String effectiveScope = getEffectiveScope( dependency.getScope(), inheritedScope );
320 
321         if ( effectiveScope == null )
322         {
323             return null;
324         }
325 
326         VersionRange versionRange = VersionRange.createFromVersionSpec( dependency.getVersion() );
327 
328         Artifact dependencyArtifact =
329             factory.createDependencyArtifact( dependency.getGroupId(), dependency.getArtifactId(), versionRange,
330                                               dependency.getType(), dependency.getClassifier(), effectiveScope,
331                                               dependency.isOptional() );
332 
333         ArtifactFilter dependencyFilter = inheritedFilter;
334 
335         if ( dependencyFilter != null && !dependencyFilter.include( dependencyArtifact ) )
336         {
337             return null;
338         }
339 
340         if ( Artifact.SCOPE_SYSTEM.equals( effectiveScope ) )
341         {
342             dependencyArtifact.setFile( new File( dependency.getSystemPath() ) );
343         }
344 
345         dependencyArtifact.setDependencyFilter( createDependencyFilter( dependency, dependencyFilter ) );
346 
347         return dependencyArtifact;
348     }
349 
350     private static String getEffectiveScope( String originalScope, String inheritedScope )
351     {
352         String effectiveScope = Artifact.SCOPE_RUNTIME;
353 
354         if ( originalScope == null )
355         {
356             originalScope = Artifact.SCOPE_COMPILE;
357         }
358 
359         if ( inheritedScope == null )
360         {
361             // direct dependency retains its scope
362             effectiveScope = originalScope;
363         }
364         else if ( Artifact.SCOPE_TEST.equals( originalScope ) || Artifact.SCOPE_PROVIDED.equals( originalScope ) )
365         {
366             // test and provided are not transitive, so exclude them
367             effectiveScope = null;
368         }
369         else if ( Artifact.SCOPE_SYSTEM.equals( originalScope ) )
370         {
371             // system scope come through unchanged...
372             effectiveScope = Artifact.SCOPE_SYSTEM;
373         }
374         else if ( Artifact.SCOPE_COMPILE.equals( originalScope ) && Artifact.SCOPE_COMPILE.equals( inheritedScope ) )
375         {
376             // added to retain compile scope. Remove if you want compile inherited as runtime
377             effectiveScope = Artifact.SCOPE_COMPILE;
378         }
379         else if ( Artifact.SCOPE_TEST.equals( inheritedScope ) )
380         {
381             effectiveScope = Artifact.SCOPE_TEST;
382         }
383         else if ( Artifact.SCOPE_PROVIDED.equals( inheritedScope ) )
384         {
385             effectiveScope = Artifact.SCOPE_PROVIDED;
386         }
387 
388         return effectiveScope;
389     }
390 
391     private static ArtifactFilter createDependencyFilter( Dependency dependency, ArtifactFilter inheritedFilter )
392     {
393         ArtifactFilter effectiveFilter = inheritedFilter;
394 
395         if ( !dependency.getExclusions().isEmpty() )
396         {
397             List<String> exclusions = new ArrayList<String>();
398 
399             for ( Exclusion e : dependency.getExclusions() )
400             {
401                 exclusions.add( e.getGroupId() + ':' + e.getArtifactId() );
402             }
403 
404             effectiveFilter = new ExcludesArtifactFilter( exclusions );
405 
406             if ( inheritedFilter != null )
407             {
408                 effectiveFilter = new AndArtifactFilter( Arrays.asList( inheritedFilter, effectiveFilter ) );
409             }
410         }
411 
412         return effectiveFilter;
413     }
414 
415     public List<ArtifactVersion> retrieveAvailableVersions( Artifact artifact, ArtifactRepository localRepository,
416                                                             List<ArtifactRepository> remoteRepositories )
417         throws ArtifactMetadataRetrievalException
418     {
419         MetadataResolutionRequest request = new DefaultMetadataResolutionRequest();
420         injectSession( request );
421         request.setArtifact( artifact );
422         request.setLocalRepository( localRepository );
423         request.setRemoteRepositories( remoteRepositories );
424         return retrieveAvailableVersions( request );
425     }
426 
427     public List<ArtifactVersion> retrieveAvailableVersions( MetadataResolutionRequest request )
428         throws ArtifactMetadataRetrievalException
429     {
430         RepositoryMetadata metadata = new ArtifactRepositoryMetadata( request.getArtifact() );
431 
432         try
433         {
434             repositoryMetadataManager.resolve( metadata, request );
435         }
436         catch ( RepositoryMetadataResolutionException e )
437         {
438             throw new ArtifactMetadataRetrievalException( e.getMessage(), e, request.getArtifact() );
439         }
440 
441         List<String> availableVersions = request.getLocalRepository().findVersions( request.getArtifact() );
442 
443         return retrieveAvailableVersionsFromMetadata( metadata.getMetadata(), availableVersions );
444     }
445 
446     public List<ArtifactVersion> retrieveAvailableVersionsFromDeploymentRepository( Artifact artifact,
447                                                                                     ArtifactRepository localRepository,
448                                                                               ArtifactRepository deploymentRepository )
449         throws ArtifactMetadataRetrievalException
450     {
451         RepositoryMetadata metadata = new ArtifactRepositoryMetadata( artifact );
452 
453         try
454         {
455             repositoryMetadataManager.resolveAlways( metadata, localRepository, deploymentRepository );
456         }
457         catch ( RepositoryMetadataResolutionException e )
458         {
459             throw new ArtifactMetadataRetrievalException( e.getMessage(), e, artifact );
460         }
461 
462         List<String> availableVersions = localRepository.findVersions( artifact );
463 
464         return retrieveAvailableVersionsFromMetadata( metadata.getMetadata(), availableVersions );
465     }
466 
467     private List<ArtifactVersion> retrieveAvailableVersionsFromMetadata( Metadata repoMetadata,
468                                                                          List<String> availableVersions )
469     {
470         Collection<String> versions = new LinkedHashSet<String>();
471 
472         if ( ( repoMetadata != null ) && ( repoMetadata.getVersioning() != null ) )
473         {
474             versions.addAll( repoMetadata.getVersioning().getVersions() );
475         }
476 
477         versions.addAll( availableVersions );
478 
479         List<ArtifactVersion> artifactVersions = new ArrayList<ArtifactVersion>( versions.size() );
480 
481         for ( String version : versions )
482         {
483             artifactVersions.add( new DefaultArtifactVersion( version ) );
484         }
485 
486         return artifactVersions;
487     }
488 
489     // USED BY MAVEN ASSEMBLY PLUGIN
490     @Deprecated
491     public static Set<Artifact> createArtifacts( ArtifactFactory artifactFactory, List<Dependency> dependencies,
492                                                  String inheritedScope, ArtifactFilter dependencyFilter,
493                                                  MavenProject project )
494         throws InvalidDependencyVersionException
495     {
496         Set<Artifact> artifacts = new LinkedHashSet<Artifact>();
497 
498         for ( Dependency d : dependencies )
499         {
500             Artifact dependencyArtifact;
501             try
502             {
503                 dependencyArtifact = createDependencyArtifact( artifactFactory, d, inheritedScope, dependencyFilter );
504             }
505             catch ( InvalidVersionSpecificationException e )
506             {
507                 throw new InvalidDependencyVersionException( project.getId(), d, project.getFile(), e );
508             }
509 
510             if ( dependencyArtifact != null )
511             {
512                 artifacts.add( dependencyArtifact );
513             }
514         }
515 
516         return artifacts;
517     }
518 
519     private ProjectBuilder getProjectBuilder()
520     {
521         if ( projectBuilder != null )
522         {
523             return projectBuilder;
524         }
525 
526         try
527         {
528             projectBuilder = container.lookup( ProjectBuilder.class );
529         }
530         catch ( ComponentLookupException e )
531         {
532             // Won't happen
533         }
534 
535         return projectBuilder;
536     }
537 
538     private ProjectRelocation retrieveRelocatedProject( Artifact artifact, MetadataResolutionRequest repositoryRequest )
539         throws ArtifactMetadataRetrievalException
540     {
541         MavenProject project;
542 
543         Artifact pomArtifact;
544         Artifact relocatedArtifact = null;
545         boolean done = false;
546         do
547         {
548             project = null;
549 
550             pomArtifact =
551                 repositorySystem.createProjectArtifact( artifact.getGroupId(),
552                                                         artifact.getArtifactId(),
553                                                         artifact.getVersion(), artifact.getScope() );
554 
555             if ( "pom".equals( artifact.getType() ) )
556             {
557                 pomArtifact.setFile( artifact.getFile() );
558             }
559 
560             if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) )
561             {
562                 done = true;
563             }
564             else
565             {
566                 try
567                 {
568                     ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
569                     configuration.setLocalRepository( repositoryRequest.getLocalRepository() );
570                     configuration.setRemoteRepositories( repositoryRequest.getRemoteRepositories() );
571                     configuration.setValidationLevel( ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL );
572                     configuration.setProcessPlugins( false );
573                     configuration.setRepositoryMerging( ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT );
574                     configuration.setSystemProperties( getSystemProperties() );
575                     configuration.setRepositorySession( legacySupport.getRepositorySession() );
576 
577                     project = getProjectBuilder().build( pomArtifact, configuration ).getProject();
578                 }
579                 catch ( ProjectBuildingException e )
580                 {
581                     ModelProblem missingParentPom = hasMissingParentPom( e );
582                     if ( missingParentPom != null )
583                     {
584                         throw new ArtifactMetadataRetrievalException( "Failed to process POM for "
585                             + artifact.getId() + ": " + missingParentPom.getMessage(),
586                                                                       missingParentPom.getException(),
587                                                                       artifact );
588                     }
589 
590                     String message;
591 
592                     if ( isMissingPom( e ) )
593                     {
594                         message = "Missing POM for " + artifact.getId();
595                     }
596                     else if ( isNonTransferrablePom( e ) )
597                     {
598                         throw new ArtifactMetadataRetrievalException( "Failed to retrieve POM for "
599                             + artifact.getId() + ": " + e.getCause().getMessage(), e.getCause(),
600                                                                       artifact );
601                     }
602                     else
603                     {
604                         message =
605                             "Invalid POM for " + artifact.getId()
606                                 + ", transitive dependencies (if any) will not be available"
607                                 + ", enable debug logging for more details";
608                     }
609 
610                     if ( logger.isDebugEnabled() )
611                     {
612                         message += ": " + e.getMessage();
613                     }
614 
615                     logger.warn( message );
616                 }
617 
618                 if ( project != null )
619                 {
620                     Relocation relocation = null;
621 
622                     DistributionManagement distMgmt = project.getDistributionManagement();
623                     if ( distMgmt != null )
624                     {
625                         relocation = distMgmt.getRelocation();
626 
627                         artifact.setDownloadUrl( distMgmt.getDownloadUrl() );
628                         pomArtifact.setDownloadUrl( distMgmt.getDownloadUrl() );
629                     }
630 
631                     if ( relocation != null )
632                     {
633                         if ( relocation.getGroupId() != null )
634                         {
635                             artifact.setGroupId( relocation.getGroupId() );
636                             relocatedArtifact = artifact;
637                             project.setGroupId( relocation.getGroupId() );
638                         }
639                         if ( relocation.getArtifactId() != null )
640                         {
641                             artifact.setArtifactId( relocation.getArtifactId() );
642                             relocatedArtifact = artifact;
643                             project.setArtifactId( relocation.getArtifactId() );
644                         }
645                         if ( relocation.getVersion() != null )
646                         {
647                             // note: see MNG-3454. This causes a problem, but fixing it may break more.
648                             artifact.setVersionRange( VersionRange.createFromVersion( relocation.getVersion() ) );
649                             relocatedArtifact = artifact;
650                             project.setVersion( relocation.getVersion() );
651                         }
652 
653                         if ( artifact.getDependencyFilter() != null
654                             && !artifact.getDependencyFilter().include( artifact ) )
655                         {
656                             return null;
657                         }
658 
659                         // MNG-2861: the artifact data has changed. If the available versions where previously
660                         // retrieved, we need to update it.
661                         // TODO: shouldn't the versions be merged across relocations?
662                         List<ArtifactVersion> available = artifact.getAvailableVersions();
663                         if ( available != null && !available.isEmpty() )
664                         {
665                             MetadataResolutionRequest metadataRequest =
666                                 new DefaultMetadataResolutionRequest( repositoryRequest );
667                             metadataRequest.setArtifact( artifact );
668                             available = retrieveAvailableVersions( metadataRequest );
669                             artifact.setAvailableVersions( available );
670                         }
671 
672                         String message =
673                             "\n  This artifact has been relocated to " + artifact.getGroupId() + ":"
674                                 + artifact.getArtifactId() + ":" + artifact.getVersion() + ".\n";
675 
676                         if ( relocation.getMessage() != null )
677                         {
678                             message += "  " + relocation.getMessage() + "\n";
679                         }
680 
681                         if ( artifact.getDependencyTrail() != null && artifact.getDependencyTrail().size() == 1 )
682                         {
683                             logger.warn( "While downloading " + pomArtifact.getGroupId() + ":"
684                                 + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message + "\n" );
685                         }
686                         else
687                         {
688                             logger.debug( "While downloading " + pomArtifact.getGroupId() + ":"
689                                 + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message + "\n" );
690                         }
691                     }
692                     else
693                     {
694                         done = true;
695                     }
696                 }
697                 else
698                 {
699                     done = true;
700                 }
701             }
702         }
703         while ( !done );
704 
705         ProjectRelocation rel = new ProjectRelocation();
706         rel.project = project;
707         rel.pomArtifact = pomArtifact;
708         rel.relocatedArtifact = relocatedArtifact;
709 
710         return rel;
711     }
712 
713     private ModelProblem hasMissingParentPom( ProjectBuildingException e )
714     {
715         if ( e.getCause() instanceof ModelBuildingException )
716         {
717             ModelBuildingException mbe = (ModelBuildingException) e.getCause();
718             for ( ModelProblem problem : mbe.getProblems() )
719             {
720                 if ( problem.getException() instanceof UnresolvableModelException )
721                 {
722                     return problem;
723                 }
724             }
725 
726         }
727         return null;
728     }
729 
730     private boolean isMissingPom( Exception e )
731     {
732         if ( e.getCause() instanceof MultipleArtifactsNotFoundException )
733         {
734             return true;
735         }
736         return e.getCause() instanceof org.eclipse.aether.resolution.ArtifactResolutionException
737             && e.getCause().getCause() instanceof ArtifactNotFoundException;
738     }
739 
740     private boolean isNonTransferrablePom( Exception e )
741     {
742         if ( e.getCause() instanceof ArtifactResolutionException )
743         {
744             return true;
745         }
746         return e.getCause() instanceof org.eclipse.aether.resolution.ArtifactResolutionException
747             && !( e.getCause().getCause() instanceof ArtifactNotFoundException );
748     }
749 
750     private Properties getSystemProperties()
751     {
752         Properties props = new Properties();
753 
754         EnvironmentUtils.addEnvVars( props );
755 
756         SystemProperties.addSystemProperties( props );
757 
758         return props;
759     }
760 
761     private static final class ProjectRelocation
762     {
763         private MavenProject project;
764 
765         private Artifact pomArtifact;
766 
767         private Artifact relocatedArtifact;
768     }
769 
770 }