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