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