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