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