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