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