1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.internal.impl.resolver;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.util.List;
26 import java.util.Objects;
27 import java.util.concurrent.atomic.AtomicReference;
28 import java.util.function.Consumer;
29 import java.util.stream.Collectors;
30
31 import org.apache.maven.api.ArtifactCoordinates;
32 import org.apache.maven.api.DownloadedArtifact;
33 import org.apache.maven.api.RemoteRepository;
34 import org.apache.maven.api.Session;
35 import org.apache.maven.api.Version;
36 import org.apache.maven.api.annotations.Nonnull;
37 import org.apache.maven.api.annotations.Nullable;
38 import org.apache.maven.api.di.Named;
39 import org.apache.maven.api.di.Singleton;
40 import org.apache.maven.api.model.Dependency;
41 import org.apache.maven.api.model.InputLocation;
42 import org.apache.maven.api.model.Parent;
43 import org.apache.maven.api.services.ArtifactResolverException;
44 import org.apache.maven.api.services.ModelSource;
45 import org.apache.maven.api.services.Source;
46 import org.apache.maven.api.services.VersionRangeResolverException;
47 import org.apache.maven.api.services.model.ModelResolver;
48 import org.apache.maven.api.services.model.ModelResolverException;
49
50
51
52
53
54
55 @Named
56 @Singleton
57 public class DefaultModelResolver implements ModelResolver {
58
59 @Nonnull
60 @Override
61 public ModelSource resolveModel(
62 @Nonnull Session session,
63 @Nullable List<RemoteRepository> repositories,
64 @Nonnull Parent parent,
65 @Nonnull AtomicReference<Parent> modified)
66 throws ModelResolverException {
67 return resolveModel(
68 session,
69 repositories,
70 parent.getGroupId(),
71 parent.getArtifactId(),
72 parent.getVersion(),
73 "parent",
74 null,
75 parent.getLocation("version"),
76 version -> modified.set(parent.withVersion(version)));
77 }
78
79 @Nonnull
80 public ModelSource resolveModel(
81 @Nonnull Session session,
82 @Nullable List<RemoteRepository> repositories,
83 @Nonnull Dependency dependency,
84 @Nonnull AtomicReference<Dependency> modified)
85 throws ModelResolverException {
86 return resolveModel(
87 session,
88 repositories,
89 dependency.getGroupId(),
90 dependency.getArtifactId(),
91 dependency.getVersion(),
92 "dependency",
93 dependency.getClassifier(),
94 dependency.getLocation("version"),
95 version -> modified.set(dependency.withVersion(version)));
96 }
97
98 @Override
99 public ModelSource resolveModel(
100 @Nonnull Session session,
101 @Nullable List<RemoteRepository> repositories,
102 @Nonnull String groupId,
103 @Nonnull String artifactId,
104 @Nonnull String version,
105 @Nullable String classifier,
106 @Nonnull Consumer<String> resolvedVersion)
107 throws ModelResolverException {
108 return resolveModel(
109 session, repositories, groupId, artifactId, version, null, classifier, null, resolvedVersion);
110 }
111
112 @SuppressWarnings("checkstyle:ParameterNumber")
113 public ModelSource resolveModel(
114 Session session,
115 List<RemoteRepository> repositories,
116 String groupId,
117 String artifactId,
118 String version,
119 String type,
120 String classifier,
121 InputLocation location,
122 Consumer<String> resolvedVersion)
123 throws ModelResolverException {
124 try {
125 ArtifactCoordinates coords =
126 session.createArtifactCoordinates(groupId, artifactId, version, classifier, "pom", null);
127 if (coords.getVersionConstraint().getVersionRange() != null
128 && coords.getVersionConstraint().getVersionRange().getUpperBoundary() == null) {
129
130 throw new ModelResolverException(
131 "The requested " + (type != null ? type + " " : "") + "version range '" + version + "'"
132 + (location != null ? " (at " + location + ")" : "")
133 + " does not specify an upper bound",
134 groupId,
135 artifactId,
136 version);
137 }
138 List<Version> versions = session.resolveVersionRange(coords, repositories);
139 if (versions.isEmpty()) {
140 throw new ModelResolverException(
141 "No versions matched the requested " + (type != null ? type + " " : "") + "version range '"
142 + version + "'",
143 groupId,
144 artifactId,
145 version);
146 }
147 String newVersion = versions.get(versions.size() - 1).asString();
148 if (!version.equals(newVersion)) {
149 resolvedVersion.accept(newVersion);
150 }
151
152 Path path = getPath(session, repositories, groupId, artifactId, newVersion, classifier);
153 return new ResolverModelSource(path, groupId + ":" + artifactId + ":" + newVersion);
154 } catch (VersionRangeResolverException | ArtifactResolverException e) {
155 throw new ModelResolverException(
156 e.getMessage() + " (remote repositories: "
157 + (repositories != null ? repositories : session.getRemoteRepositories())
158 .stream().map(Object::toString).collect(Collectors.joining(", "))
159 + ")",
160 groupId,
161 artifactId,
162 version,
163 e);
164 }
165 }
166
167 protected Path getPath(
168 Session session,
169 List<RemoteRepository> repositories,
170 String groupId,
171 String artifactId,
172 String version,
173 String classifier) {
174 DownloadedArtifact resolved = session.resolveArtifact(
175 session.createArtifactCoordinates(groupId, artifactId, version, classifier, "pom", null), repositories);
176 return resolved.getPath();
177 }
178
179 protected static class ResolverModelSource implements ModelSource {
180 private final Path path;
181 private final String location;
182
183 ResolverModelSource(Path path, String location) {
184 this.path = path;
185 this.location = location;
186 }
187
188 @Override
189 public ModelSource resolve(ModelLocator modelLocator, String relative) {
190 return null;
191 }
192
193 @Override
194 public Path getPath() {
195 return null;
196 }
197
198 @Override
199 public InputStream openStream() throws IOException {
200 return Files.newInputStream(path);
201 }
202
203 @Override
204 public String getLocation() {
205 return location;
206 }
207
208 @Override
209 public Source resolve(String relative) {
210 return null;
211 }
212
213 @Override
214 public boolean equals(Object o) {
215 if (this == o) {
216 return true;
217 }
218 if (o == null || getClass() != o.getClass()) {
219 return false;
220 }
221 ResolverModelSource that = (ResolverModelSource) o;
222 return Objects.equals(path, that.path) && Objects.equals(location, that.location);
223 }
224
225 @Override
226 public int hashCode() {
227 return Objects.hash(path, location);
228 }
229 }
230 }