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