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.repository.internal;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Set;
28  
29  import org.apache.maven.model.Dependency;
30  import org.apache.maven.model.Parent;
31  import org.apache.maven.model.Repository;
32  import org.apache.maven.model.building.FileModelSource;
33  import org.apache.maven.model.building.ModelSource;
34  import org.apache.maven.model.resolution.InvalidRepositoryException;
35  import org.apache.maven.model.resolution.ModelResolver;
36  import org.apache.maven.model.resolution.UnresolvableModelException;
37  import org.eclipse.aether.RepositorySystemSession;
38  import org.eclipse.aether.RequestTrace;
39  import org.eclipse.aether.artifact.Artifact;
40  import org.eclipse.aether.artifact.DefaultArtifact;
41  import org.eclipse.aether.impl.ArtifactResolver;
42  import org.eclipse.aether.impl.RemoteRepositoryManager;
43  import org.eclipse.aether.impl.VersionRangeResolver;
44  import org.eclipse.aether.repository.RemoteRepository;
45  import org.eclipse.aether.resolution.ArtifactRequest;
46  import org.eclipse.aether.resolution.ArtifactResolutionException;
47  import org.eclipse.aether.resolution.VersionRangeRequest;
48  import org.eclipse.aether.resolution.VersionRangeResolutionException;
49  import org.eclipse.aether.resolution.VersionRangeResult;
50  
51  /**
52   * A model resolver to assist building of dependency POMs. This resolver gives priority to those repositories that have
53   * been initially specified and repositories discovered in dependency POMs are recessively merged into the search chain.
54   *
55   * @see DefaultArtifactDescriptorReader
56   * @deprecated since 4.0.0, use {@code maven-api-impl} jar instead
57   */
58  @Deprecated(since = "4.0.0")
59  class DefaultModelResolver implements ModelResolver {
60  
61      private final RepositorySystemSession session;
62  
63      private final RequestTrace trace;
64  
65      private final String context;
66  
67      private List<RemoteRepository> repositories;
68  
69      private final List<RemoteRepository> externalRepositories;
70  
71      private final ArtifactResolver resolver;
72  
73      private final VersionRangeResolver versionRangeResolver;
74  
75      private final RemoteRepositoryManager remoteRepositoryManager;
76  
77      private final Set<String> repositoryIds;
78  
79      DefaultModelResolver(
80              RepositorySystemSession session,
81              RequestTrace trace,
82              String context,
83              ArtifactResolver resolver,
84              VersionRangeResolver versionRangeResolver,
85              RemoteRepositoryManager remoteRepositoryManager,
86              List<RemoteRepository> repositories) {
87          this.session = session;
88          this.trace = trace;
89          this.context = context;
90          this.resolver = resolver;
91          this.versionRangeResolver = versionRangeResolver;
92          this.remoteRepositoryManager = remoteRepositoryManager;
93          this.repositories = repositories;
94          this.externalRepositories = Collections.unmodifiableList(new ArrayList<>(repositories));
95  
96          this.repositoryIds = new HashSet<>();
97      }
98  
99      private DefaultModelResolver(DefaultModelResolver original) {
100         this.session = original.session;
101         this.trace = original.trace;
102         this.context = original.context;
103         this.resolver = original.resolver;
104         this.versionRangeResolver = original.versionRangeResolver;
105         this.remoteRepositoryManager = original.remoteRepositoryManager;
106         this.repositories = new ArrayList<>(original.repositories);
107         this.externalRepositories = original.externalRepositories;
108         this.repositoryIds = new HashSet<>(original.repositoryIds);
109     }
110 
111     @Override
112     public void addRepository(org.apache.maven.model.Repository repository) throws InvalidRepositoryException {
113         addRepository(repository, false);
114     }
115 
116     @Override
117     public void addRepository(final Repository repository, boolean replace) throws InvalidRepositoryException {
118         if (session.isIgnoreArtifactDescriptorRepositories()) {
119             return;
120         }
121 
122         if (!repositoryIds.add(repository.getId())) {
123             if (!replace) {
124                 return;
125             }
126 
127             removeMatchingRepository(repositories, repository.getId());
128         }
129 
130         List<RemoteRepository> newRepositories =
131                 Collections.singletonList(ArtifactDescriptorUtils.toRemoteRepository(repository));
132 
133         this.repositories = remoteRepositoryManager.aggregateRepositories(session, repositories, newRepositories, true);
134     }
135 
136     private static void removeMatchingRepository(Iterable<RemoteRepository> repositories, final String id) {
137         Iterator<RemoteRepository> iterator = repositories.iterator();
138         while (iterator.hasNext()) {
139             RemoteRepository remoteRepository = iterator.next();
140             if (remoteRepository.getId().equals(id)) {
141                 iterator.remove();
142             }
143         }
144     }
145 
146     @Override
147     public ModelResolver newCopy() {
148         return new DefaultModelResolver(this);
149     }
150 
151     @Override
152     public ModelSource resolveModel(String groupId, String artifactId, String version)
153             throws UnresolvableModelException {
154         Artifact pomArtifact = new DefaultArtifact(groupId, artifactId, "", "pom", version);
155 
156         try {
157             ArtifactRequest request = new ArtifactRequest(pomArtifact, repositories, context);
158             request.setTrace(trace);
159             pomArtifact = resolver.resolveArtifact(session, request).getArtifact();
160         } catch (ArtifactResolutionException e) {
161             throw new UnresolvableModelException(e.getMessage(), groupId, artifactId, version, e);
162         }
163 
164         File pomFile = pomArtifact.getFile();
165 
166         return new FileModelSource(pomFile);
167     }
168 
169     @Override
170     public ModelSource resolveModel(final Parent parent) throws UnresolvableModelException {
171         try {
172             final Artifact artifact =
173                     new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), "", "pom", parent.getVersion());
174 
175             final VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, repositories, context);
176             versionRangeRequest.setTrace(trace);
177 
178             final VersionRangeResult versionRangeResult =
179                     versionRangeResolver.resolveVersionRange(session, versionRangeRequest);
180 
181             if (versionRangeResult.getHighestVersion() == null) {
182                 throw new UnresolvableModelException(
183                         String.format(
184                                 "No versions matched the requested parent version range '%s'", parent.getVersion()),
185                         parent.getGroupId(),
186                         parent.getArtifactId(),
187                         parent.getVersion());
188             }
189 
190             if (versionRangeResult.getVersionConstraint() != null
191                     && versionRangeResult.getVersionConstraint().getRange() != null
192                     && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null) {
193                 // Message below is checked for in the MNG-2199 core IT.
194                 throw new UnresolvableModelException(
195                         String.format(
196                                 "The requested parent version range '%s' does not specify an upper bound",
197                                 parent.getVersion()),
198                         parent.getGroupId(),
199                         parent.getArtifactId(),
200                         parent.getVersion());
201             }
202 
203             parent.setVersion(versionRangeResult.getHighestVersion().toString());
204 
205             return resolveModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion());
206         } catch (final VersionRangeResolutionException e) {
207             throw new UnresolvableModelException(
208                     e.getMessage(), parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), e);
209         }
210     }
211 
212     @Override
213     public ModelSource resolveModel(final Dependency dependency) throws UnresolvableModelException {
214         try {
215             final Artifact artifact = new DefaultArtifact(
216                     dependency.getGroupId(), dependency.getArtifactId(), "", "pom", dependency.getVersion());
217 
218             final VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, repositories, context);
219             versionRangeRequest.setTrace(trace);
220 
221             final VersionRangeResult versionRangeResult =
222                     versionRangeResolver.resolveVersionRange(session, versionRangeRequest);
223 
224             if (versionRangeResult.getHighestVersion() == null) {
225                 throw new UnresolvableModelException(
226                         String.format(
227                                 "No versions matched the requested dependency version range '%s'",
228                                 dependency.getVersion()),
229                         dependency.getGroupId(),
230                         dependency.getArtifactId(),
231                         dependency.getVersion());
232             }
233 
234             if (versionRangeResult.getVersionConstraint() != null
235                     && versionRangeResult.getVersionConstraint().getRange() != null
236                     && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null) {
237                 // Message below is checked for in the MNG-4463 core IT.
238                 throw new UnresolvableModelException(
239                         String.format(
240                                 "The requested dependency version range '%s' does not specify an upper bound",
241                                 dependency.getVersion()),
242                         dependency.getGroupId(),
243                         dependency.getArtifactId(),
244                         dependency.getVersion());
245             }
246 
247             dependency.setVersion(versionRangeResult.getHighestVersion().toString());
248 
249             return resolveModel(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion());
250         } catch (VersionRangeResolutionException e) {
251             throw new UnresolvableModelException(
252                     e.getMessage(), dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), e);
253         }
254     }
255 }