View Javadoc
1   package org.apache.maven.shared.transfer.dependencies.resolve.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.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  import org.apache.maven.RepositoryUtils;
28  import org.apache.maven.artifact.handler.ArtifactHandler;
29  import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
30  import org.apache.maven.model.DependencyManagement;
31  import org.apache.maven.model.Model;
32  import org.apache.maven.project.ProjectBuildingRequest;
33  import org.apache.maven.shared.artifact.filter.resolve.TransformableFilter;
34  import org.apache.maven.shared.artifact.filter.resolve.transform.SonatypeAetherFilterTransformer;
35  import org.apache.maven.shared.transfer.dependencies.DependableCoordinate;
36  import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
37  import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
38  import org.codehaus.plexus.component.annotations.Component;
39  import org.codehaus.plexus.component.annotations.Requirement;
40  
41  import org.sonatype.aether.RepositorySystem;
42  import org.sonatype.aether.RepositorySystemSession;
43  import org.sonatype.aether.artifact.Artifact;
44  import org.sonatype.aether.artifact.ArtifactType;
45  import org.sonatype.aether.artifact.ArtifactTypeRegistry;
46  import org.sonatype.aether.collection.CollectRequest;
47  import org.sonatype.aether.collection.DependencyCollectionException;
48  import org.sonatype.aether.graph.Dependency;
49  import org.sonatype.aether.graph.DependencyFilter;
50  import org.sonatype.aether.repository.RemoteRepository;
51  import org.sonatype.aether.resolution.ArtifactResolutionException;
52  import org.sonatype.aether.resolution.ArtifactResult;
53  import org.sonatype.aether.util.artifact.DefaultArtifact;
54  import org.sonatype.aether.util.artifact.DefaultArtifactType;
55  
56  /**
57   * 
58   */
59  @Component( role = DependencyResolver.class, hint = "maven3" )
60  class Maven30DependencyResolver
61      implements DependencyResolver
62  {
63      @Requirement
64      private RepositorySystem repositorySystem;
65  
66      @Requirement
67      private ArtifactHandlerManager artifactHandlerManager;
68  
69      @Override
70      // CHECKSTYLE_OFF: LineLength
71      public Iterable<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult> resolveDependencies( ProjectBuildingRequest buildingRequest,
72                                                                                                    DependableCoordinate coordinate,
73                                                                                                    TransformableFilter dependencyFilter )
74      // CHECKSTYLE_ON: LineLength
75          throws DependencyResolverException
76      {
77          ArtifactTypeRegistry typeRegistry =
78              (ArtifactTypeRegistry) Invoker.invoke( RepositoryUtils.class, "newArtifactTypeRegistry",
79                                                     ArtifactHandlerManager.class, artifactHandlerManager );
80  
81          Dependency aetherRoot = toDependency( coordinate, typeRegistry );
82  
83          @SuppressWarnings( "unchecked" )
84          List<RemoteRepository> aetherRepositories =
85              (List<RemoteRepository>) Invoker.invoke( RepositoryUtils.class, "toRepos", List.class,
86                                                       buildingRequest.getRemoteRepositories() );
87  
88          CollectRequest request = new CollectRequest( aetherRoot, aetherRepositories );
89  
90          return resolveDependencies( buildingRequest, aetherRepositories, dependencyFilter, request );
91      }
92      
93      @Override
94      // CHECKSTYLE_OFF: LineLength
95      public Iterable<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult> resolveDependencies( ProjectBuildingRequest buildingRequest,
96                                                                                                    Model model,
97                                                                                                    TransformableFilter dependencyFilter )
98      // CHECKSTYLE_ON: LineLength
99          throws DependencyResolverException
100     {
101         // Are there examples where packaging and type are NOT in sync
102         ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler( model.getPackaging() );
103         
104         String extension = artifactHandler != null ? artifactHandler.getExtension() : null;
105         
106         Artifact aetherArtifact =
107             new DefaultArtifact( model.getGroupId(), model.getArtifactId(), extension, model.getVersion() );
108         
109         Dependency aetherRoot = new Dependency( aetherArtifact, null );
110         
111         @SuppressWarnings( "unchecked" )
112         List<RemoteRepository> aetherRepositories =
113             (List<RemoteRepository>) Invoker.invoke( RepositoryUtils.class, "toRepos", List.class,
114                                                      buildingRequest.getRemoteRepositories() );
115 
116         CollectRequest request = new CollectRequest( aetherRoot, aetherRepositories );
117         
118         ArtifactTypeRegistry typeRegistry =
119                         (ArtifactTypeRegistry) Invoker.invoke( RepositoryUtils.class, "newArtifactTypeRegistry",
120                                                                ArtifactHandlerManager.class, artifactHandlerManager );
121 
122         List<Dependency> aetherDependencies = new ArrayList<Dependency>( model.getDependencies().size() );
123         for ( org.apache.maven.model.Dependency mavenDependency : model.getDependencies() )
124         {
125             aetherDependencies.add( toDependency( mavenDependency, typeRegistry ) );
126         }
127         request.setDependencies( aetherDependencies );
128 
129         DependencyManagement mavenDependencyManagement = model.getDependencyManagement();
130         if ( mavenDependencyManagement != null )
131         {
132             List<Dependency> aetherManagerDependencies =
133                 new ArrayList<Dependency>( mavenDependencyManagement.getDependencies().size() );
134             
135             for ( org.apache.maven.model.Dependency mavenDependency : mavenDependencyManagement.getDependencies() )
136             {
137                 aetherManagerDependencies.add( toDependency( mavenDependency, typeRegistry ) );
138             }
139             
140             request.setManagedDependencies( aetherManagerDependencies );
141         }
142 
143         return resolveDependencies( buildingRequest, aetherRepositories, dependencyFilter, request );
144     }
145 
146     @Override
147     // CHECKSTYLE_OFF: LineLength
148     public Iterable<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult> resolveDependencies( ProjectBuildingRequest buildingRequest,
149                                                                                                   Collection<org.apache.maven.model.Dependency> mavenDependencies,
150                                                                                                   Collection<org.apache.maven.model.Dependency> managedMavenDependencies,
151                                                                                                   TransformableFilter filter )
152     // CHECKSTYLE_ON: LineLength
153         throws DependencyResolverException
154     {
155         ArtifactTypeRegistry typeRegistry =
156             (ArtifactTypeRegistry) Invoker.invoke( RepositoryUtils.class, "newArtifactTypeRegistry",
157                                                    ArtifactHandlerManager.class, artifactHandlerManager );
158 
159         final Class<?>[] argClasses =
160             new Class<?>[] { org.apache.maven.model.Dependency.class, ArtifactTypeRegistry.class };
161 
162          List<Dependency> aetherDependencies = new ArrayList<Dependency>( mavenDependencies.size() );
163 
164          if ( mavenDependencies != null )
165          {
166              aetherDependencies = new ArrayList<Dependency>( mavenDependencies.size() );
167 
168              for ( org.apache.maven.model.Dependency mavenDependency : mavenDependencies )
169              {
170                  Object[] args = new Object[] { mavenDependency, typeRegistry };
171 
172                  Dependency aetherDependency =
173                      (Dependency) Invoker.invoke( RepositoryUtils.class, "toDependency", argClasses, args );
174 
175                  aetherDependencies.add( aetherDependency );
176              }
177          }
178 
179         List<Dependency> aetherManagedDependencies = null;
180 
181         if ( managedMavenDependencies != null )
182         {
183             aetherManagedDependencies = new ArrayList<Dependency>( managedMavenDependencies.size() );
184 
185             for ( org.apache.maven.model.Dependency mavenDependency : managedMavenDependencies )
186             {
187                 Object[] args = new Object[] { mavenDependency, typeRegistry };
188 
189                 Dependency aetherDependency =
190                     (Dependency) Invoker.invoke( RepositoryUtils.class, "toDependency", argClasses, args );
191 
192                 aetherManagedDependencies.add( aetherDependency );
193             }
194         }
195 
196         @SuppressWarnings( "unchecked" )
197         List<RemoteRepository> aetherRepositories =
198             (List<RemoteRepository>) Invoker.invoke( RepositoryUtils.class, "toRepos", List.class,
199                                                      buildingRequest.getRemoteRepositories() );
200 
201         CollectRequest request =
202             new CollectRequest( aetherDependencies, aetherManagedDependencies, aetherRepositories );
203 
204         return resolveDependencies( buildingRequest, aetherRepositories, filter, request );
205     }
206 
207     // CHECKSTYLE_OFF: LineLength
208     private Iterable<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult> resolveDependencies( ProjectBuildingRequest buildingRequest,
209                                                                                                    List<RemoteRepository> aetherRepositories,
210                                                                                                    TransformableFilter dependencyFilter,
211                                                                                                    CollectRequest request )
212                                                                                                        throws DependencyResolverException
213     // CHECKSTYLE_ON :LineLength
214     {
215         try
216         {
217             DependencyFilter depFilter = null;
218             if ( dependencyFilter != null )
219             {
220                 depFilter = dependencyFilter.transform( new SonatypeAetherFilterTransformer() );
221             }
222 
223             RepositorySystemSession session =
224                 (RepositorySystemSession) Invoker.invoke( buildingRequest, "getRepositorySession" );
225 
226             final List<ArtifactResult> dependencyResults =
227                 repositorySystem.resolveDependencies( session, request, depFilter );
228 
229             // Keep it lazy! Often artifactsResults aren't used, so transforming up front is too expensive
230             return new Iterable<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult>()
231             {
232                 @Override
233                 public Iterator<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult> iterator()
234                 {
235                     // CHECKSTYLE_OFF: LineLength
236                     Collection<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult> artResults =
237                         new ArrayList<org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult>( dependencyResults.size() );
238                     // CHECKSTYLE_ON: LineLength
239                     
240                     for ( ArtifactResult artifactResult : dependencyResults )
241                     {
242                         artResults.add( new Maven30ArtifactResult( artifactResult ) );
243                     }
244 
245                     return artResults.iterator();
246                 }
247             };
248         }
249         catch ( ArtifactResolutionException e )
250         {
251             throw new Maven30DependencyResolverException( e );
252         }
253         catch ( DependencyCollectionException e )
254         {
255             throw new Maven30DependencyResolverException( e );
256         }
257     }
258 
259     /**
260      * Based on RepositoryUtils#toDependency(org.apache.maven.model.Dependency, ArtifactTypeRegistry)
261      * 
262      * @param coordinate
263      * @param stereotypes
264      * @return as Aether Dependency
265      */
266     private static Dependency toDependency( DependableCoordinate coordinate, ArtifactTypeRegistry stereotypes )
267     {
268         ArtifactType stereotype = stereotypes.get( coordinate.getType() );
269         if ( stereotype == null )
270         {
271             stereotype = new DefaultArtifactType( coordinate.getType() );
272         }
273 
274         Artifact artifact =
275             new DefaultArtifact( coordinate.getGroupId(), coordinate.getArtifactId(), coordinate.getClassifier(), null,
276                                  coordinate.getVersion(), null, stereotype );
277 
278         return new Dependency( artifact, null );
279     }
280     
281     private static Dependency toDependency( org.apache.maven.model.Dependency mavenDependency,
282                                             ArtifactTypeRegistry typeRegistry )
283         throws DependencyResolverException
284     {
285         Class<?>[] argClasses = new Class<?>[] { org.apache.maven.model.Dependency.class, ArtifactTypeRegistry.class };
286 
287         Object[] args = new Object[] { mavenDependency, typeRegistry };
288 
289         return (Dependency) Invoker.invoke( RepositoryUtils.class, "toDependency", argClasses, args );
290     }  
291 }