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