View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.project.artifact;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.HashMap;
27  import java.util.LinkedHashMap;
28  import java.util.LinkedHashSet;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Properties;
32  import java.util.Set;
33  import javax.inject.Inject;
34  import javax.inject.Named;
35  import javax.inject.Singleton;
36  import org.apache.maven.RepositoryUtils;
37  import org.apache.maven.artifact.Artifact;
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.eclipse.aether.RepositorySystemSession;
79  import org.eclipse.aether.repository.RepositoryPolicy;
80  import org.eclipse.aether.repository.WorkspaceReader;
81  import org.eclipse.aether.transfer.ArtifactNotFoundException;
82  import org.slf4j.Logger;
83  import org.slf4j.LoggerFactory;
84  
85  /**
86   * @author Jason van Zyl
87   */
88  @Named("maven")
89  @Singleton
90  public class MavenMetadataSource implements ArtifactMetadataSource {
91      private final Logger logger = LoggerFactory.getLogger(getClass());
92      private final RepositoryMetadataManager repositoryMetadataManager;
93      private final ArtifactFactory repositorySystem;
94      private final ProjectBuilder projectBuilder;
95      private final MavenMetadataCache cache;
96      private final LegacySupport legacySupport;
97  
98      @Inject
99      public MavenMetadataSource(
100             RepositoryMetadataManager repositoryMetadataManager,
101             ArtifactFactory repositorySystem,
102             ProjectBuilder projectBuilder,
103             MavenMetadataCache cache,
104             LegacySupport legacySupport) {
105         this.repositoryMetadataManager = repositoryMetadataManager;
106         this.repositorySystem = repositorySystem;
107         this.projectBuilder = projectBuilder;
108         this.cache = cache;
109         this.legacySupport = legacySupport;
110     }
111 
112     private void injectSession(MetadataResolutionRequest request) {
113         RepositorySystemSession session = legacySupport.getRepositorySession();
114 
115         if (session != null) {
116             request.setOffline(session.isOffline());
117             request.setForceUpdate(RepositoryPolicy.UPDATE_POLICY_ALWAYS.equals(session.getUpdatePolicy()));
118         }
119     }
120 
121     public ResolutionGroup retrieve(
122             Artifact artifact, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories)
123             throws ArtifactMetadataRetrievalException {
124         return retrieve(artifact, localRepository, remoteRepositories, false);
125     }
126 
127     public ResolutionGroup retrieve(
128             Artifact artifact,
129             ArtifactRepository localRepository,
130             List<ArtifactRepository> remoteRepositories,
131             boolean resolveManagedVersions)
132             throws ArtifactMetadataRetrievalException {
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) throws ArtifactMetadataRetrievalException {
143         Artifact artifact = request.getArtifact();
144 
145         //
146         // If we have a system scoped artifact then we do not want any searching in local or remote repositories
147         // and we want artifact resolution to only return the system scoped artifact itself.
148         //
149         if (artifact.getScope() != null && artifact.getScope().equals(Artifact.SCOPE_SYSTEM)) {
150             return new ResolutionGroup(null, null, null);
151         }
152 
153         ResolutionGroup cached = cache.get(
154                 artifact,
155                 request.isResolveManagedVersions(),
156                 request.getLocalRepository(),
157                 request.getRemoteRepositories());
158 
159         if (cached != null
160                 // if the POM has no file, we cached a missing artifact, only return the cached data if no update forced
161                 && (!request.isForceUpdate() || hasFile(cached.getPomArtifact()))) {
162             return cached;
163         }
164 
165         List<Dependency> dependencies;
166 
167         List<Dependency> managedDependencies = null;
168 
169         List<ArtifactRepository> pomRepositories = null;
170 
171         Artifact pomArtifact;
172 
173         Artifact relocatedArtifact = null;
174 
175         // TODO hack: don't rebuild model if it was already loaded during reactor resolution
176         final WorkspaceReader workspace = legacySupport.getRepositorySession().getWorkspaceReader();
177         Model model = null;
178         if (workspace instanceof MavenWorkspaceReader) {
179             model = ((MavenWorkspaceReader) workspace).findModel(RepositoryUtils.toArtifact(artifact));
180         }
181 
182         if (model != null) {
183             pomArtifact = artifact;
184             dependencies = model.getDependencies();
185             DependencyManagement dependencyManagement = model.getDependencyManagement();
186             managedDependencies = dependencyManagement == null ? null : dependencyManagement.getDependencies();
187             MavenSession session = legacySupport.getSession();
188             if (session != null) {
189                 pomRepositories = session.getProjects().stream()
190                         .filter(p -> artifact.equals(p.getArtifact()))
191                         .map(MavenProject::getRemoteArtifactRepositories)
192                         .findFirst()
193                         .orElseGet(ArrayList::new);
194             } else {
195                 pomRepositories = new ArrayList<>();
196             }
197         } else if (artifact instanceof ArtifactWithDependencies) {
198             pomArtifact = artifact;
199 
200             dependencies = ((ArtifactWithDependencies) artifact).getDependencies();
201 
202             managedDependencies = ((ArtifactWithDependencies) artifact).getManagedDependencies();
203         } else {
204             ProjectRelocation rel = retrieveRelocatedProject(artifact, request);
205 
206             if (rel == null) {
207                 return null;
208             }
209 
210             pomArtifact = rel.pomArtifact;
211 
212             relocatedArtifact = rel.relocatedArtifact;
213 
214             if (rel.project == null) {
215                 // When this happens we have a Maven 1.x POM, or some invalid POM.
216                 // It should have never found its way into Maven 2.x repository but it did.
217                 dependencies = Collections.emptyList();
218             } else {
219                 dependencies = rel.project.getModel().getDependencies();
220 
221                 DependencyManagement depMgmt = rel.project.getModel().getDependencyManagement();
222                 managedDependencies = (depMgmt != null) ? depMgmt.getDependencies() : null;
223 
224                 pomRepositories = rel.project.getRemoteArtifactRepositories();
225             }
226         }
227 
228         Set<Artifact> artifacts = Collections.emptySet();
229 
230         if (!artifact.getArtifactHandler().isIncludesDependencies()) {
231             artifacts = new LinkedHashSet<>();
232 
233             for (Dependency dependency : dependencies) {
234                 Artifact dependencyArtifact = createDependencyArtifact(dependency, artifact, pomArtifact);
235 
236                 if (dependencyArtifact != null) {
237                     artifacts.add(dependencyArtifact);
238                 }
239             }
240         }
241 
242         Map<String, Artifact> managedVersions = null;
243 
244         if (managedDependencies != null && request.isResolveManagedVersions()) {
245             managedVersions = new HashMap<>();
246 
247             for (Dependency managedDependency : managedDependencies) {
248                 Artifact managedArtifact = createDependencyArtifact(managedDependency, null, pomArtifact);
249 
250                 managedVersions.put(managedDependency.getManagementKey(), managedArtifact);
251             }
252         }
253 
254         List<ArtifactRepository> aggregatedRepositories =
255                 aggregateRepositories(request.getRemoteRepositories(), pomRepositories);
256 
257         ResolutionGroup result =
258                 new ResolutionGroup(pomArtifact, relocatedArtifact, artifacts, managedVersions, aggregatedRepositories);
259 
260         cache.put(
261                 artifact,
262                 request.isResolveManagedVersions(),
263                 request.getLocalRepository(),
264                 request.getRemoteRepositories(),
265                 result);
266 
267         return result;
268     }
269 
270     private boolean hasFile(Artifact artifact) {
271         return artifact != null
272                 && artifact.getFile() != null
273                 && artifact.getFile().exists();
274     }
275 
276     private List<ArtifactRepository> aggregateRepositories(
277             List<ArtifactRepository> requestRepositories, List<ArtifactRepository> pomRepositories) {
278         List<ArtifactRepository> repositories = requestRepositories;
279 
280         if (pomRepositories != null && !pomRepositories.isEmpty()) {
281             Map<String, ArtifactRepository> repos = new LinkedHashMap<>();
282 
283             for (ArtifactRepository repo : requestRepositories) {
284                 if (!repos.containsKey(repo.getId())) {
285                     repos.put(repo.getId(), repo);
286                 }
287             }
288 
289             for (ArtifactRepository repo : pomRepositories) {
290                 if (!repos.containsKey(repo.getId())) {
291                     repos.put(repo.getId(), repo);
292                 }
293             }
294 
295             repositories = new ArrayList<>(repos.values());
296         }
297 
298         return repositories;
299     }
300 
301     private Artifact createDependencyArtifact(Dependency dependency, Artifact owner, Artifact pom)
302             throws ArtifactMetadataRetrievalException {
303         try {
304             String inheritedScope = (owner != null) ? owner.getScope() : null;
305 
306             ArtifactFilter inheritedFilter = (owner != null) ? owner.getDependencyFilter() : null;
307 
308             return createDependencyArtifact(repositorySystem, dependency, inheritedScope, inheritedFilter);
309         } catch (InvalidVersionSpecificationException e) {
310             throw new ArtifactMetadataRetrievalException(
311                     "Invalid version for dependency " + dependency.getManagementKey() + ": " + e.getMessage(), e, pom);
312         }
313     }
314 
315     private static Artifact createDependencyArtifact(
316             ArtifactFactory factory, Dependency dependency, String inheritedScope, ArtifactFilter inheritedFilter)
317             throws InvalidVersionSpecificationException {
318         String effectiveScope = getEffectiveScope(dependency.getScope(), inheritedScope);
319 
320         if (effectiveScope == null) {
321             return null;
322         }
323 
324         VersionRange versionRange = VersionRange.createFromVersionSpec(dependency.getVersion());
325 
326         Artifact dependencyArtifact = factory.createDependencyArtifact(
327                 dependency.getGroupId(),
328                 dependency.getArtifactId(),
329                 versionRange,
330                 dependency.getType(),
331                 dependency.getClassifier(),
332                 effectiveScope,
333                 dependency.isOptional());
334 
335         if (inheritedFilter != null && !inheritedFilter.include(dependencyArtifact)) {
336             return null;
337         }
338 
339         if (Artifact.SCOPE_SYSTEM.equals(effectiveScope)) {
340             dependencyArtifact.setFile(new File(dependency.getSystemPath()));
341         }
342 
343         dependencyArtifact.setDependencyFilter(createDependencyFilter(dependency, inheritedFilter));
344 
345         return dependencyArtifact;
346     }
347 
348     private static String getEffectiveScope(String originalScope, String inheritedScope) {
349         String effectiveScope = Artifact.SCOPE_RUNTIME;
350 
351         if (originalScope == null) {
352             originalScope = Artifact.SCOPE_COMPILE;
353         }
354 
355         if (inheritedScope == null) {
356             // direct dependency retains its scope
357             effectiveScope = originalScope;
358         } else if (Artifact.SCOPE_TEST.equals(originalScope) || Artifact.SCOPE_PROVIDED.equals(originalScope)) {
359             // test and provided are not transitive, so exclude them
360             effectiveScope = null;
361         } else if (Artifact.SCOPE_SYSTEM.equals(originalScope)) {
362             // system scope come through unchanged...
363             effectiveScope = Artifact.SCOPE_SYSTEM;
364         } else if (Artifact.SCOPE_COMPILE.equals(originalScope) && Artifact.SCOPE_COMPILE.equals(inheritedScope)) {
365             // added to retain compile scope. Remove if you want compile inherited as runtime
366             effectiveScope = Artifact.SCOPE_COMPILE;
367         } else if (Artifact.SCOPE_TEST.equals(inheritedScope)) {
368             effectiveScope = Artifact.SCOPE_TEST;
369         } else if (Artifact.SCOPE_PROVIDED.equals(inheritedScope)) {
370             effectiveScope = Artifact.SCOPE_PROVIDED;
371         }
372 
373         return effectiveScope;
374     }
375 
376     private static ArtifactFilter createDependencyFilter(Dependency dependency, ArtifactFilter inheritedFilter) {
377         ArtifactFilter effectiveFilter = inheritedFilter;
378 
379         if (!dependency.getExclusions().isEmpty()) {
380             effectiveFilter = new ExclusionArtifactFilter(dependency.getExclusions());
381 
382             if (inheritedFilter != null) {
383                 effectiveFilter = new AndArtifactFilter(Arrays.asList(inheritedFilter, effectiveFilter));
384             }
385         }
386 
387         return effectiveFilter;
388     }
389 
390     public List<ArtifactVersion> retrieveAvailableVersions(
391             Artifact artifact, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepositories)
392             throws ArtifactMetadataRetrievalException {
393         MetadataResolutionRequest request = new DefaultMetadataResolutionRequest();
394         injectSession(request);
395         request.setArtifact(artifact);
396         request.setLocalRepository(localRepository);
397         request.setRemoteRepositories(remoteRepositories);
398         return retrieveAvailableVersions(request);
399     }
400 
401     public List<ArtifactVersion> retrieveAvailableVersions(MetadataResolutionRequest request)
402             throws ArtifactMetadataRetrievalException {
403         RepositoryMetadata metadata = new ArtifactRepositoryMetadata(request.getArtifact());
404 
405         try {
406             repositoryMetadataManager.resolve(metadata, request);
407         } catch (RepositoryMetadataResolutionException e) {
408             throw new ArtifactMetadataRetrievalException(e.getMessage(), e, request.getArtifact());
409         }
410 
411         List<String> availableVersions = request.getLocalRepository().findVersions(request.getArtifact());
412 
413         return retrieveAvailableVersionsFromMetadata(metadata.getMetadata(), availableVersions);
414     }
415 
416     public List<ArtifactVersion> retrieveAvailableVersionsFromDeploymentRepository(
417             Artifact artifact, ArtifactRepository localRepository, ArtifactRepository deploymentRepository)
418             throws ArtifactMetadataRetrievalException {
419         RepositoryMetadata metadata = new ArtifactRepositoryMetadata(artifact);
420 
421         try {
422             repositoryMetadataManager.resolveAlways(metadata, localRepository, deploymentRepository);
423         } catch (RepositoryMetadataResolutionException e) {
424             throw new ArtifactMetadataRetrievalException(e.getMessage(), e, artifact);
425         }
426 
427         List<String> availableVersions = localRepository.findVersions(artifact);
428 
429         return retrieveAvailableVersionsFromMetadata(metadata.getMetadata(), availableVersions);
430     }
431 
432     private List<ArtifactVersion> retrieveAvailableVersionsFromMetadata(
433             Metadata repoMetadata, List<String> availableVersions) {
434         Collection<String> versions = new LinkedHashSet<>();
435 
436         if ((repoMetadata != null) && (repoMetadata.getVersioning() != null)) {
437             versions.addAll(repoMetadata.getVersioning().getVersions());
438         }
439 
440         versions.addAll(availableVersions);
441 
442         List<ArtifactVersion> artifactVersions = new ArrayList<>(versions.size());
443 
444         for (String version : versions) {
445             artifactVersions.add(new DefaultArtifactVersion(version));
446         }
447 
448         return artifactVersions;
449     }
450 
451     // USED BY MAVEN ASSEMBLY PLUGIN
452     @Deprecated
453     public static Set<Artifact> createArtifacts(
454             ArtifactFactory artifactFactory,
455             List<Dependency> dependencies,
456             String inheritedScope,
457             ArtifactFilter dependencyFilter,
458             MavenProject project)
459             throws InvalidDependencyVersionException {
460         Set<Artifact> artifacts = new LinkedHashSet<>();
461 
462         for (Dependency d : dependencies) {
463             Artifact dependencyArtifact;
464             try {
465                 dependencyArtifact = createDependencyArtifact(artifactFactory, d, inheritedScope, dependencyFilter);
466             } catch (InvalidVersionSpecificationException e) {
467                 throw new InvalidDependencyVersionException(project.getId(), d, project.getFile(), e);
468             }
469 
470             if (dependencyArtifact != null) {
471                 artifacts.add(dependencyArtifact);
472             }
473         }
474 
475         return artifacts;
476     }
477 
478     @SuppressWarnings("checkstyle:methodlength")
479     private ProjectRelocation retrieveRelocatedProject(Artifact artifact, MetadataResolutionRequest repositoryRequest)
480             throws ArtifactMetadataRetrievalException {
481         MavenProject project;
482 
483         Artifact pomArtifact;
484         Artifact relocatedArtifact = null;
485         boolean done = false;
486         do {
487             project = null;
488 
489             pomArtifact = repositorySystem.createProjectArtifact(
490                     artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getScope());
491 
492             if ("pom".equals(artifact.getType())) {
493                 pomArtifact.setFile(artifact.getFile());
494             }
495 
496             if (Artifact.SCOPE_SYSTEM.equals(artifact.getScope())) {
497                 done = true;
498             } else {
499                 try {
500                     ProjectBuildingRequest configuration = new DefaultProjectBuildingRequest();
501                     configuration.setLocalRepository(repositoryRequest.getLocalRepository());
502                     configuration.setRemoteRepositories(repositoryRequest.getRemoteRepositories());
503                     configuration.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
504                     configuration.setProcessPlugins(false);
505                     configuration.setRepositoryMerging(ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT);
506                     MavenSession session = legacySupport.getSession();
507                     if (session != null) {
508                         configuration.setSystemProperties(session.getSystemProperties());
509                         configuration.setUserProperties(session.getUserProperties());
510                     } else {
511                         configuration.setSystemProperties(getSystemProperties());
512                         configuration.setUserProperties(new Properties());
513                     }
514                     configuration.setRepositorySession(legacySupport.getRepositorySession());
515 
516                     project = projectBuilder.build(pomArtifact, configuration).getProject();
517                 } catch (ProjectBuildingException e) {
518                     ModelProblem missingParentPom = hasMissingParentPom(e);
519                     if (missingParentPom != null) {
520                         throw new ArtifactMetadataRetrievalException(
521                                 "Failed to process POM for " + artifact.getId() + ": " + missingParentPom.getMessage(),
522                                 missingParentPom.getException(),
523                                 artifact);
524                     }
525 
526                     String message;
527 
528                     if (isMissingPom(e)) {
529                         message = "Missing POM for " + artifact.getId();
530                     } else if (isNonTransferablePom(e)) {
531                         throw new ArtifactMetadataRetrievalException(
532                                 "Failed to retrieve POM for " + artifact.getId() + ": "
533                                         + e.getCause().getMessage(),
534                                 e.getCause(),
535                                 artifact);
536                     } else {
537                         message = "Invalid POM for " + artifact.getId()
538                                 + ", transitive dependencies (if any) will not be available"
539                                 + ", enable verbose output (-X) for more details";
540                     }
541 
542                     if (logger.isDebugEnabled()) {
543                         message += ": " + e.getMessage();
544                     }
545 
546                     logger.warn(message);
547                 }
548 
549                 if (project != null) {
550                     Relocation relocation = null;
551 
552                     DistributionManagement distMgmt = project.getModel().getDistributionManagement();
553                     if (distMgmt != null) {
554                         relocation = distMgmt.getRelocation();
555 
556                         artifact.setDownloadUrl(distMgmt.getDownloadUrl());
557                         pomArtifact.setDownloadUrl(distMgmt.getDownloadUrl());
558                     }
559 
560                     if (relocation != null) {
561                         if (relocation.getGroupId() != null) {
562                             artifact.setGroupId(relocation.getGroupId());
563                             relocatedArtifact = artifact;
564                             project.setGroupId(relocation.getGroupId());
565                         }
566                         if (relocation.getArtifactId() != null) {
567                             artifact.setArtifactId(relocation.getArtifactId());
568                             relocatedArtifact = artifact;
569                             project.setArtifactId(relocation.getArtifactId());
570                         }
571                         if (relocation.getVersion() != null) {
572                             // note: see MNG-3454. This causes a problem, but fixing it may break more.
573                             artifact.setVersionRange(VersionRange.createFromVersion(relocation.getVersion()));
574                             relocatedArtifact = artifact;
575                             project.setVersion(relocation.getVersion());
576                         }
577 
578                         if (artifact.getDependencyFilter() != null
579                                 && !artifact.getDependencyFilter().include(artifact)) {
580                             return null;
581                         }
582 
583                         // MNG-2861: the artifact data has changed. If the available versions where previously
584                         // retrieved, we need to update it.
585                         // TODO shouldn't the versions be merged across relocations?
586                         List<ArtifactVersion> available = artifact.getAvailableVersions();
587                         if (available != null && !available.isEmpty()) {
588                             MetadataResolutionRequest metadataRequest =
589                                     new DefaultMetadataResolutionRequest(repositoryRequest);
590                             metadataRequest.setArtifact(artifact);
591                             available = retrieveAvailableVersions(metadataRequest);
592                             artifact.setAvailableVersions(available);
593                         }
594 
595                         String message = "  this artifact has been relocated to " + artifact.getGroupId() + ":"
596                                 + artifact.getArtifactId() + ":" + artifact.getVersion() + ".";
597 
598                         if (relocation.getMessage() != null) {
599                             message += "  " + relocation.getMessage();
600                         }
601 
602                         if (artifact.getDependencyTrail() != null
603                                 && artifact.getDependencyTrail().size() == 1) {
604                             logger.warn("While downloading " + pomArtifact.getGroupId() + ":"
605                                     + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message);
606                         } else {
607                             logger.debug("While downloading " + pomArtifact.getGroupId() + ":"
608                                     + pomArtifact.getArtifactId() + ":" + pomArtifact.getVersion() + message);
609                         }
610                     } else {
611                         done = true;
612                     }
613                 } else {
614                     done = true;
615                 }
616             }
617         } while (!done);
618 
619         ProjectRelocation rel = new ProjectRelocation();
620         rel.project = project;
621         rel.pomArtifact = pomArtifact;
622         rel.relocatedArtifact = relocatedArtifact;
623 
624         return rel;
625     }
626 
627     private ModelProblem hasMissingParentPom(ProjectBuildingException e) {
628         if (e.getCause() instanceof ModelBuildingException) {
629             ModelBuildingException mbe = (ModelBuildingException) e.getCause();
630             for (ModelProblem problem : mbe.getProblems()) {
631                 if (problem.getException() instanceof UnresolvableModelException) {
632                     return problem;
633                 }
634             }
635         }
636         return null;
637     }
638 
639     private boolean isMissingPom(Exception e) {
640         if (e.getCause() instanceof MultipleArtifactsNotFoundException) {
641             return true;
642         }
643         return e.getCause() instanceof org.eclipse.aether.resolution.ArtifactResolutionException
644                 && e.getCause().getCause() instanceof ArtifactNotFoundException;
645     }
646 
647     private boolean isNonTransferablePom(Exception e) {
648         if (e.getCause() instanceof ArtifactResolutionException) {
649             return true;
650         }
651         return e.getCause() instanceof org.eclipse.aether.resolution.ArtifactResolutionException
652                 && !(e.getCause().getCause() instanceof ArtifactNotFoundException);
653     }
654 
655     private Properties getSystemProperties() {
656         Properties props = new Properties();
657 
658         EnvironmentUtils.addEnvVars(props);
659 
660         SystemProperties.addSystemProperties(props);
661 
662         return props;
663     }
664 
665     private static final class ProjectRelocation {
666         private MavenProject project;
667 
668         private Artifact pomArtifact;
669 
670         private Artifact relocatedArtifact;
671     }
672 }