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