View Javadoc

1   package org.apache.maven.repository.internal;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.FileInputStream;
23  import java.io.FileNotFoundException;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.maven.artifact.repository.metadata.Versioning;
31  import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
32  import org.codehaus.plexus.component.annotations.Component;
33  import org.codehaus.plexus.component.annotations.Requirement;
34  import org.codehaus.plexus.util.IOUtil;
35  import org.sonatype.aether.RepositoryListener;
36  import org.sonatype.aether.RepositorySystemSession;
37  import org.sonatype.aether.util.listener.DefaultRepositoryEvent;
38  import org.sonatype.aether.util.metadata.DefaultMetadata;
39  import org.sonatype.aether.util.version.GenericVersionScheme;
40  import org.sonatype.aether.version.InvalidVersionSpecificationException;
41  import org.sonatype.aether.version.Version;
42  import org.sonatype.aether.version.VersionConstraint;
43  import org.sonatype.aether.version.VersionScheme;
44  import org.sonatype.aether.impl.MetadataResolver;
45  import org.sonatype.aether.impl.VersionRangeResolver;
46  import org.sonatype.aether.metadata.Metadata;
47  import org.sonatype.aether.repository.ArtifactRepository;
48  import org.sonatype.aether.repository.RemoteRepository;
49  import org.sonatype.aether.repository.WorkspaceReader;
50  import org.sonatype.aether.resolution.MetadataRequest;
51  import org.sonatype.aether.resolution.MetadataResult;
52  import org.sonatype.aether.resolution.VersionRangeRequest;
53  import org.sonatype.aether.resolution.VersionRangeResolutionException;
54  import org.sonatype.aether.resolution.VersionRangeResult;
55  import org.sonatype.aether.spi.locator.Service;
56  import org.sonatype.aether.spi.locator.ServiceLocator;
57  import org.sonatype.aether.spi.log.Logger;
58  import org.sonatype.aether.spi.log.NullLogger;
59  
60  /**
61   * @author Benjamin Bentmann
62   */
63  @Component( role = VersionRangeResolver.class )
64  public class DefaultVersionRangeResolver
65      implements VersionRangeResolver, Service
66  {
67  
68      private static final String MAVEN_METADATA_XML = "maven-metadata.xml";
69  
70      @Requirement
71      private Logger logger = NullLogger.INSTANCE;
72  
73      @Requirement
74      private MetadataResolver metadataResolver;
75  
76      public void initService( ServiceLocator locator )
77      {
78          setLogger( locator.getService( Logger.class ) );
79          setMetadataResolver( locator.getService( MetadataResolver.class ) );
80      }
81  
82      public DefaultVersionRangeResolver setLogger( Logger logger )
83      {
84          this.logger = ( logger != null ) ? logger : NullLogger.INSTANCE;
85          return this;
86      }
87  
88      public DefaultVersionRangeResolver setMetadataResolver( MetadataResolver metadataResolver )
89      {
90          if ( metadataResolver == null )
91          {
92              throw new IllegalArgumentException( "metadata resolver has not been specified" );
93          }
94          this.metadataResolver = metadataResolver;
95          return this;
96      }
97  
98      public VersionRangeResult resolveVersionRange( RepositorySystemSession session, VersionRangeRequest request )
99          throws VersionRangeResolutionException
100     {
101         VersionRangeResult result = new VersionRangeResult( request );
102 
103         VersionScheme versionScheme = new GenericVersionScheme();
104 
105         VersionConstraint versionConstraint;
106         try
107         {
108             versionConstraint = versionScheme.parseVersionConstraint( request.getArtifact().getVersion() );
109         }
110         catch ( InvalidVersionSpecificationException e )
111         {
112             result.addException( e );
113             throw new VersionRangeResolutionException( result );
114         }
115 
116         result.setVersionConstraint( versionConstraint );
117 
118         if ( versionConstraint.getRanges().isEmpty() )
119         {
120             result.addVersion( versionConstraint.getVersion() );
121         }
122         else
123         {
124             Map<String, ArtifactRepository> versionIndex = getVersions( session, result, request );
125 
126             List<Version> versions = new ArrayList<Version>();
127             for ( Map.Entry<String, ArtifactRepository> v : versionIndex.entrySet() )
128             {
129                 try
130                 {
131                     Version ver = versionScheme.parseVersion( v.getKey() );
132                     if ( versionConstraint.containsVersion( ver ) )
133                     {
134                         versions.add( ver );
135                         result.setRepository( ver, v.getValue() );
136                     }
137                 }
138                 catch ( InvalidVersionSpecificationException e )
139                 {
140                     result.addException( e );
141                 }
142             }
143 
144             Collections.sort( versions );
145             result.setVersions( versions );
146         }
147 
148         return result;
149     }
150 
151     private Map<String, ArtifactRepository> getVersions( RepositorySystemSession session, VersionRangeResult result,
152                                                          VersionRangeRequest request )
153     {
154         Map<String, ArtifactRepository> versionIndex = new HashMap<String, ArtifactRepository>();
155 
156         Metadata metadata =
157             new DefaultMetadata( request.getArtifact().getGroupId(), request.getArtifact().getArtifactId(),
158                                  MAVEN_METADATA_XML, Metadata.Nature.RELEASE_OR_SNAPSHOT );
159 
160         List<MetadataRequest> metadataRequests = new ArrayList<MetadataRequest>( request.getRepositories().size() );
161 
162         metadataRequests.add( new MetadataRequest( metadata, null, request.getRequestContext() ) );
163 
164         for ( RemoteRepository repository : request.getRepositories() )
165         {
166             MetadataRequest metadataRequest = new MetadataRequest( metadata, repository, request.getRequestContext() );
167             metadataRequest.setDeleteLocalCopyIfMissing( true );
168             metadataRequests.add( metadataRequest );
169         }
170 
171         List<MetadataResult> metadataResults = metadataResolver.resolveMetadata( session, metadataRequests );
172 
173         WorkspaceReader workspace = session.getWorkspaceReader();
174         if ( workspace != null )
175         {
176             List<String> versions = workspace.findVersions( request.getArtifact() );
177             for ( String version : versions )
178             {
179                 versionIndex.put( version, workspace.getRepository() );
180             }
181         }
182 
183         for ( MetadataResult metadataResult : metadataResults )
184         {
185             result.addException( metadataResult.getException() );
186 
187             ArtifactRepository repository = metadataResult.getRequest().getRepository();
188             if ( repository == null )
189             {
190                 repository = session.getLocalRepository();
191             }
192 
193             Versioning versioning = readVersions( session, metadataResult.getMetadata(), repository, result );
194             for ( String version : versioning.getVersions() )
195             {
196                 if ( !versionIndex.containsKey( version ) )
197                 {
198                     versionIndex.put( version, repository );
199                 }
200             }
201         }
202 
203         return versionIndex;
204     }
205 
206     private Versioning readVersions( RepositorySystemSession session, Metadata metadata, ArtifactRepository repository,
207                                      VersionRangeResult result )
208     {
209         Versioning versioning = null;
210 
211         FileInputStream fis = null;
212         try
213         {
214             if ( metadata != null && metadata.getFile() != null )
215             {
216                 fis = new FileInputStream( metadata.getFile() );
217                 org.apache.maven.artifact.repository.metadata.Metadata m = new MetadataXpp3Reader().read( fis, false );
218                 versioning = m.getVersioning();
219             }
220         }
221         catch ( FileNotFoundException e )
222         {
223             // tolerable
224         }
225         catch ( Exception e )
226         {
227             invalidMetadata( session, metadata, repository, e );
228             result.addException( e );
229         }
230         finally
231         {
232             IOUtil.close( fis );
233         }
234 
235         return ( versioning != null ) ? versioning : new Versioning();
236     }
237 
238     private void invalidMetadata( RepositorySystemSession session, Metadata metadata, ArtifactRepository repository,
239                                   Exception exception )
240     {
241         RepositoryListener listener = session.getRepositoryListener();
242         if ( listener != null )
243         {
244             DefaultRepositoryEvent event = new DefaultRepositoryEvent( session, metadata );
245             event.setException( exception );
246             event.setRepository( repository );
247             listener.metadataInvalid( event );
248         }
249     }
250 
251 }