1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.project;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Set;
27 import java.util.concurrent.atomic.AtomicReference;
28
29 import org.apache.maven.api.model.Dependency;
30 import org.apache.maven.api.model.Parent;
31 import org.apache.maven.api.model.Repository;
32 import org.apache.maven.model.Model;
33 import org.apache.maven.model.building.ArtifactModelSource;
34 import org.apache.maven.model.building.FileModelSource;
35 import org.apache.maven.model.building.ModelSource;
36 import org.apache.maven.model.resolution.InvalidRepositoryException;
37 import org.apache.maven.model.resolution.ModelResolver;
38 import org.apache.maven.model.resolution.UnresolvableModelException;
39 import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
40 import org.eclipse.aether.RepositorySystem;
41 import org.eclipse.aether.RepositorySystemSession;
42 import org.eclipse.aether.RequestTrace;
43 import org.eclipse.aether.artifact.Artifact;
44 import org.eclipse.aether.artifact.DefaultArtifact;
45 import org.eclipse.aether.impl.RemoteRepositoryManager;
46 import org.eclipse.aether.repository.RemoteRepository;
47 import org.eclipse.aether.resolution.ArtifactRequest;
48 import org.eclipse.aether.resolution.ArtifactResolutionException;
49 import org.eclipse.aether.resolution.VersionRangeRequest;
50 import org.eclipse.aether.resolution.VersionRangeResolutionException;
51 import org.eclipse.aether.resolution.VersionRangeResult;
52
53
54
55
56
57
58 public class ProjectModelResolver implements ModelResolver {
59
60 private final RepositorySystemSession session;
61
62 private final RequestTrace trace;
63
64 private final String context = "project";
65
66 private List<RemoteRepository> repositories;
67
68 private List<RemoteRepository> pomRepositories;
69
70 private final List<RemoteRepository> externalRepositories;
71
72 private final RepositorySystem resolver;
73
74 private final RemoteRepositoryManager remoteRepositoryManager;
75
76 private final Set<String> repositoryIds;
77
78 private final ReactorModelPool modelPool;
79
80 private final ProjectBuildingRequest.RepositoryMerging repositoryMerging;
81
82 public ProjectModelResolver(
83 RepositorySystemSession session,
84 RequestTrace trace,
85 RepositorySystem resolver,
86 RemoteRepositoryManager remoteRepositoryManager,
87 List<RemoteRepository> repositories,
88 ProjectBuildingRequest.RepositoryMerging repositoryMerging,
89 ReactorModelPool modelPool) {
90 this.session = session;
91 this.trace = trace;
92 this.resolver = resolver;
93 this.remoteRepositoryManager = remoteRepositoryManager;
94 this.pomRepositories = new ArrayList<>();
95 this.externalRepositories = Collections.unmodifiableList(new ArrayList<>(repositories));
96 this.repositories = new ArrayList<>();
97 this.repositories.addAll(externalRepositories);
98 this.repositoryMerging = repositoryMerging;
99 this.repositoryIds = new HashSet<>();
100 this.modelPool = modelPool;
101 }
102
103 private ProjectModelResolver(ProjectModelResolver original) {
104 this.session = original.session;
105 this.trace = original.trace;
106 this.resolver = original.resolver;
107 this.remoteRepositoryManager = original.remoteRepositoryManager;
108 this.pomRepositories = new ArrayList<>(original.pomRepositories);
109 this.externalRepositories = original.externalRepositories;
110 this.repositories = new ArrayList<>(original.repositories);
111 this.repositoryMerging = original.repositoryMerging;
112 this.repositoryIds = new HashSet<>(original.repositoryIds);
113 this.modelPool = original.modelPool;
114 }
115
116 public void addRepository(Repository repository) throws InvalidRepositoryException {
117 addRepository(repository, false);
118 }
119
120 @Override
121 public void addRepository(final Repository repository, boolean replace) throws InvalidRepositoryException {
122 if (!repositoryIds.add(repository.getId())) {
123 if (!replace) {
124 return;
125 }
126
127
128 removeMatchingRepository(repositories, repository.getId());
129 removeMatchingRepository(pomRepositories, repository.getId());
130 }
131
132 List<RemoteRepository> newRepositories = Collections.singletonList(
133 ArtifactDescriptorUtils.toRemoteRepository(new org.apache.maven.model.Repository(repository)));
134
135 if (ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT.equals(repositoryMerging)) {
136 repositories = remoteRepositoryManager.aggregateRepositories(session, repositories, newRepositories, true);
137 } else {
138 pomRepositories =
139 remoteRepositoryManager.aggregateRepositories(session, pomRepositories, newRepositories, true);
140 repositories = remoteRepositoryManager.aggregateRepositories(
141 session, pomRepositories, externalRepositories, false);
142 }
143 }
144
145 private static void removeMatchingRepository(Iterable<RemoteRepository> repositories, final String id) {
146 Iterator<RemoteRepository> iterator = repositories.iterator();
147 while (iterator.hasNext()) {
148 RemoteRepository next = iterator.next();
149 if (next.getId().equals(id)) {
150 iterator.remove();
151 }
152 }
153 }
154
155 public ModelResolver newCopy() {
156 return new ProjectModelResolver(this);
157 }
158
159 public ModelSource resolveModel(String groupId, String artifactId, String version)
160 throws UnresolvableModelException {
161 Artifact pomArtifact = new DefaultArtifact(groupId, artifactId, "", "pom", version);
162
163 try {
164 ArtifactRequest request = new ArtifactRequest(pomArtifact, repositories, context);
165 request.setTrace(trace);
166 pomArtifact = resolver.resolveArtifact(session, request).getArtifact();
167 } catch (ArtifactResolutionException e) {
168 throw new UnresolvableModelException(e.getMessage(), groupId, artifactId, version, e);
169 }
170
171 return new ArtifactModelSource(pomArtifact.getFile(), groupId, artifactId, version);
172 }
173
174 @Override
175 public ModelSource resolveModel(final Parent parent, AtomicReference<Parent> modified)
176 throws UnresolvableModelException {
177 try {
178 final Artifact artifact =
179 new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), "", "pom", parent.getVersion());
180
181 final VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, repositories, context);
182 versionRangeRequest.setTrace(trace);
183
184 final VersionRangeResult versionRangeResult = resolver.resolveVersionRange(session, versionRangeRequest);
185
186 if (versionRangeResult.getHighestVersion() == null) {
187 throw new UnresolvableModelException(
188 String.format(
189 "No versions matched the requested parent version range '%s'", parent.getVersion()),
190 parent.getGroupId(),
191 parent.getArtifactId(),
192 parent.getVersion());
193 }
194
195 if (versionRangeResult.getVersionConstraint() != null
196 && versionRangeResult.getVersionConstraint().getRange() != null
197 && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null) {
198
199 throw new UnresolvableModelException(
200 String.format(
201 "The requested parent version range '%s' does not specify an upper bound",
202 parent.getVersion()),
203 parent.getGroupId(),
204 parent.getArtifactId(),
205 parent.getVersion());
206 }
207
208 String newVersion = versionRangeResult.getHighestVersion().toString();
209 if (!parent.getVersion().equals(newVersion)) {
210 modified.set(parent.withVersion(newVersion));
211 }
212
213 return resolveModel(parent.getGroupId(), parent.getArtifactId(), newVersion);
214 } catch (final VersionRangeResolutionException e) {
215 throw new UnresolvableModelException(
216 e.getMessage(), parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), e);
217 }
218 }
219
220 @Override
221 public ModelSource resolveModel(final Dependency dependency, AtomicReference<Dependency> modified)
222 throws UnresolvableModelException {
223 try {
224 final Artifact artifact = new DefaultArtifact(
225 dependency.getGroupId(), dependency.getArtifactId(), "", "pom", dependency.getVersion());
226
227 final VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, repositories, context);
228 versionRangeRequest.setTrace(trace);
229
230 final VersionRangeResult versionRangeResult = resolver.resolveVersionRange(session, versionRangeRequest);
231
232 if (versionRangeResult.getHighestVersion() == null) {
233 throw new UnresolvableModelException(
234 String.format(
235 "No versions matched the requested dependency version range '%s'",
236 dependency.getVersion()),
237 dependency.getGroupId(),
238 dependency.getArtifactId(),
239 dependency.getVersion());
240 }
241
242 if (versionRangeResult.getVersionConstraint() != null
243 && versionRangeResult.getVersionConstraint().getRange() != null
244 && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null) {
245
246 throw new UnresolvableModelException(
247 String.format(
248 "The requested dependency version range '%s' does not specify an upper bound",
249 dependency.getVersion()),
250 dependency.getGroupId(),
251 dependency.getArtifactId(),
252 dependency.getVersion());
253 }
254
255 String newVersion = versionRangeResult.getHighestVersion().toString();
256 if (!dependency.getVersion().equals(newVersion)) {
257 modified.set(dependency.withVersion(newVersion));
258 }
259
260 if (modelPool != null) {
261 Model model = modelPool.get(dependency.getGroupId(), dependency.getArtifactId(), newVersion);
262
263 if (model != null) {
264 return new FileModelSource(model.getPomFile());
265 }
266 }
267
268 return resolveModel(dependency.getGroupId(), dependency.getArtifactId(), newVersion);
269 } catch (VersionRangeResolutionException e) {
270 throw new UnresolvableModelException(
271 e.getMessage(), dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), e);
272 }
273 }
274
275 @Override
276 public ModelSource resolveModel(org.apache.maven.model.Parent parent) throws UnresolvableModelException {
277 AtomicReference<org.apache.maven.api.model.Parent> resolvedParent = new AtomicReference<>();
278 ModelSource result = resolveModel(parent.getDelegate(), resolvedParent);
279 if (resolvedParent.get() != null) {
280 parent.setVersion(resolvedParent.get().getVersion());
281 }
282 return result;
283 }
284
285 @Override
286 public ModelSource resolveModel(org.apache.maven.model.Dependency dependency) throws UnresolvableModelException {
287 AtomicReference<org.apache.maven.api.model.Dependency> resolvedDependency = new AtomicReference<>();
288 ModelSource result = resolveModel(dependency.getDelegate(), resolvedDependency);
289 if (resolvedDependency.get() != null) {
290 dependency.setVersion(resolvedDependency.get().getVersion());
291 }
292 return result;
293 }
294
295 @Override
296 public void addRepository(org.apache.maven.model.Repository repository) throws InvalidRepositoryException {
297 addRepository(repository.getDelegate());
298 }
299
300 @Override
301 public void addRepository(org.apache.maven.model.Repository repository, boolean replace)
302 throws InvalidRepositoryException {
303 addRepository(repository.getDelegate(), replace);
304 }
305 }