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