1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.repository.internal;
20
21 import javax.inject.Inject;
22 import javax.inject.Named;
23 import javax.inject.Singleton;
24
25 import java.io.InputStream;
26 import java.nio.file.Files;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Objects;
33
34 import org.apache.maven.artifact.repository.metadata.Versioning;
35 import org.apache.maven.metadata.v4.MetadataStaxReader;
36 import org.eclipse.aether.RepositoryEvent;
37 import org.eclipse.aether.RepositoryEvent.EventType;
38 import org.eclipse.aether.RepositorySystemSession;
39 import org.eclipse.aether.RequestTrace;
40 import org.eclipse.aether.SyncContext;
41 import org.eclipse.aether.impl.MetadataResolver;
42 import org.eclipse.aether.impl.RepositoryEventDispatcher;
43 import org.eclipse.aether.impl.VersionRangeResolver;
44 import org.eclipse.aether.metadata.DefaultMetadata;
45 import org.eclipse.aether.metadata.Metadata;
46 import org.eclipse.aether.repository.ArtifactRepository;
47 import org.eclipse.aether.repository.RemoteRepository;
48 import org.eclipse.aether.repository.WorkspaceReader;
49 import org.eclipse.aether.resolution.MetadataRequest;
50 import org.eclipse.aether.resolution.MetadataResult;
51 import org.eclipse.aether.resolution.VersionRangeRequest;
52 import org.eclipse.aether.resolution.VersionRangeResolutionException;
53 import org.eclipse.aether.resolution.VersionRangeResult;
54 import org.eclipse.aether.spi.synccontext.SyncContextFactory;
55 import org.eclipse.aether.version.InvalidVersionSpecificationException;
56 import org.eclipse.aether.version.Version;
57 import org.eclipse.aether.version.VersionConstraint;
58 import org.eclipse.aether.version.VersionRange;
59 import org.eclipse.aether.version.VersionScheme;
60
61
62
63
64 @Named
65 @Singleton
66 @Deprecated(since = "4.0.0")
67 public class DefaultVersionRangeResolver implements VersionRangeResolver {
68
69 private static final String MAVEN_METADATA_XML = "maven-metadata.xml";
70
71 private final MetadataResolver metadataResolver;
72 private final SyncContextFactory syncContextFactory;
73 private final RepositoryEventDispatcher repositoryEventDispatcher;
74 private final VersionScheme versionScheme;
75
76 @Inject
77 public DefaultVersionRangeResolver(
78 MetadataResolver metadataResolver,
79 SyncContextFactory syncContextFactory,
80 RepositoryEventDispatcher repositoryEventDispatcher,
81 VersionScheme versionScheme) {
82 this.metadataResolver = Objects.requireNonNull(metadataResolver, "metadataResolver cannot be null");
83 this.syncContextFactory = Objects.requireNonNull(syncContextFactory, "syncContextFactory cannot be null");
84 this.repositoryEventDispatcher =
85 Objects.requireNonNull(repositoryEventDispatcher, "repositoryEventDispatcher cannot be null");
86 this.versionScheme = Objects.requireNonNull(versionScheme, "versionScheme cannot be null");
87 }
88
89 @Override
90 public VersionRangeResult resolveVersionRange(RepositorySystemSession session, VersionRangeRequest request)
91 throws VersionRangeResolutionException {
92 VersionRangeResult result = new VersionRangeResult(request);
93
94 VersionConstraint versionConstraint;
95 try {
96 versionConstraint =
97 versionScheme.parseVersionConstraint(request.getArtifact().getVersion());
98 } catch (InvalidVersionSpecificationException e) {
99 result.addException(e);
100 throw new VersionRangeResolutionException(result);
101 }
102
103 result.setVersionConstraint(versionConstraint);
104
105 if (versionConstraint.getRange() == null) {
106 result.addVersion(versionConstraint.getVersion());
107 } else {
108 VersionRange.Bound lowerBound = versionConstraint.getRange().getLowerBound();
109 if (lowerBound != null
110 && lowerBound.equals(versionConstraint.getRange().getUpperBound())) {
111 result.addVersion(lowerBound.getVersion());
112 } else {
113 Map<String, ArtifactRepository> versionIndex = getVersions(session, result, request);
114
115 List<Version> versions = new ArrayList<>();
116 for (Map.Entry<String, ArtifactRepository> v : versionIndex.entrySet()) {
117 try {
118 Version ver = versionScheme.parseVersion(v.getKey());
119 if (versionConstraint.containsVersion(ver)) {
120 versions.add(ver);
121 result.setRepository(ver, v.getValue());
122 }
123 } catch (InvalidVersionSpecificationException e) {
124 result.addException(e);
125 }
126 }
127
128 Collections.sort(versions);
129 result.setVersions(versions);
130 }
131 }
132
133 return result;
134 }
135
136 private Map<String, ArtifactRepository> getVersions(
137 RepositorySystemSession session, VersionRangeResult result, VersionRangeRequest request) {
138 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request);
139
140 Map<String, ArtifactRepository> versionIndex = new HashMap<>();
141
142 Metadata metadata = new DefaultMetadata(
143 request.getArtifact().getGroupId(),
144 request.getArtifact().getArtifactId(),
145 MAVEN_METADATA_XML,
146 Metadata.Nature.RELEASE_OR_SNAPSHOT);
147
148 List<MetadataRequest> metadataRequests =
149 new ArrayList<>(request.getRepositories().size());
150
151 metadataRequests.add(new MetadataRequest(metadata, null, request.getRequestContext()));
152
153 for (RemoteRepository repository : request.getRepositories()) {
154 MetadataRequest metadataRequest = new MetadataRequest(metadata, repository, request.getRequestContext());
155 metadataRequest.setDeleteLocalCopyIfMissing(true);
156 metadataRequest.setTrace(trace);
157 metadataRequests.add(metadataRequest);
158 }
159
160 List<MetadataResult> metadataResults = metadataResolver.resolveMetadata(session, metadataRequests);
161
162 WorkspaceReader workspace = session.getWorkspaceReader();
163 if (workspace != null) {
164 List<String> versions = workspace.findVersions(request.getArtifact());
165 for (String version : versions) {
166 versionIndex.put(version, workspace.getRepository());
167 }
168 }
169
170 for (MetadataResult metadataResult : metadataResults) {
171 result.addException(metadataResult.getException());
172
173 ArtifactRepository repository = metadataResult.getRequest().getRepository();
174 if (repository == null) {
175 repository = session.getLocalRepository();
176 }
177
178 Versioning versioning = readVersions(session, trace, metadataResult.getMetadata(), repository, result);
179
180 versioning = filterVersionsByRepositoryType(
181 versioning, metadataResult.getRequest().getRepository());
182
183 for (String version : versioning.getVersions()) {
184 if (!versionIndex.containsKey(version)) {
185 versionIndex.put(version, repository);
186 }
187 }
188 }
189
190 return versionIndex;
191 }
192
193 private Versioning readVersions(
194 RepositorySystemSession session,
195 RequestTrace trace,
196 Metadata metadata,
197 ArtifactRepository repository,
198 VersionRangeResult result) {
199 Versioning versioning = null;
200 try {
201 if (metadata != null) {
202 try (SyncContext syncContext = syncContextFactory.newInstance(session, true)) {
203 syncContext.acquire(null, Collections.singleton(metadata));
204
205 if (metadata.getPath() != null && Files.exists(metadata.getPath())) {
206 try (InputStream in = Files.newInputStream(metadata.getPath())) {
207 versioning = new Versioning(
208 new MetadataStaxReader().read(in, false).getVersioning());
209 }
210 }
211 }
212 }
213 } catch (Exception e) {
214 invalidMetadata(session, trace, metadata, repository, e);
215 result.addException(e);
216 }
217
218 return (versioning != null) ? versioning : new Versioning();
219 }
220
221 private Versioning filterVersionsByRepositoryType(Versioning versioning, RemoteRepository remoteRepository) {
222 if (remoteRepository == null) {
223 return versioning;
224 }
225
226 Versioning filteredVersions = versioning.clone();
227
228 for (String version : versioning.getVersions()) {
229 if (!remoteRepository
230 .getPolicy(DefaultModelVersionParser.checkSnapshot(version))
231 .isEnabled()) {
232 filteredVersions.removeVersion(version);
233 }
234 }
235
236 return filteredVersions;
237 }
238
239 private void invalidMetadata(
240 RepositorySystemSession session,
241 RequestTrace trace,
242 Metadata metadata,
243 ArtifactRepository repository,
244 Exception exception) {
245 RepositoryEvent.Builder event = new RepositoryEvent.Builder(session, EventType.METADATA_INVALID);
246 event.setTrace(trace);
247 event.setMetadata(metadata);
248 event.setException(exception);
249 event.setRepository(repository);
250
251 repositoryEventDispatcher.dispatch(event.build());
252 }
253 }