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