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