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