View Javadoc
1   package org.apache.maven.shared.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.List;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Iterator;
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.EclipseAetherFilterTransformer;
35  import org.apache.maven.shared.dependencies.DependableCoordinate;
36  import org.apache.maven.shared.dependencies.resolve.DependencyResolver;
37  import org.apache.maven.shared.dependencies.resolve.DependencyResolverException;
38  import org.codehaus.plexus.component.annotations.Component;
39  import org.codehaus.plexus.component.annotations.Requirement;
40  import org.eclipse.aether.RepositorySystem;
41  import org.eclipse.aether.RepositorySystemSession;
42  import org.eclipse.aether.artifact.Artifact;
43  import org.eclipse.aether.artifact.ArtifactType;
44  import org.eclipse.aether.artifact.ArtifactTypeRegistry;
45  import org.eclipse.aether.artifact.DefaultArtifact;
46  import org.eclipse.aether.artifact.DefaultArtifactType;
47  import org.eclipse.aether.collection.CollectRequest;
48  import org.eclipse.aether.graph.Dependency;
49  import org.eclipse.aether.graph.DependencyFilter;
50  import org.eclipse.aether.repository.RemoteRepository;
51  import org.eclipse.aether.resolution.ArtifactResult;
52  import org.eclipse.aether.resolution.DependencyRequest;
53  import org.eclipse.aether.resolution.DependencyResolutionException;
54  import org.eclipse.aether.resolution.DependencyResult;
55  
56  /**
57   * 
58   */
59  @Component( role = DependencyResolver.class, hint = "maven31" )
60  public class Maven31DependencyResolver
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.artifact.resolve.ArtifactResult> resolveDependencies( ProjectBuildingRequest buildingRequest,
72                                                                                                    DependableCoordinate coordinate,
73                                                                                                    TransformableFilter dependencyFilter )
74                                                                                                        throws DependencyResolverException
75      // CHECKSTYLE_ON: LineLength
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.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.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                                                                                                       throws DependencyResolverException
153     // CHECKSTYLE_ON: LineLength
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> aetherDeps = null;
163 
164         if ( mavenDependencies != null )
165         {
166             aetherDeps = 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                 aetherDeps.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> aetherRepos =
198             (List<RemoteRepository>) Invoker.invoke( RepositoryUtils.class, "toRepos", List.class,
199                                                      buildingRequest.getRemoteRepositories() );
200 
201         CollectRequest request = new CollectRequest( aetherDeps, aetherManagedDependencies, aetherRepos );
202 
203         return resolveDependencies( buildingRequest, aetherRepos, filter, request );
204     }
205 
206     // CHECKSTYLE_OFF: LineLength
207     private Iterable<org.apache.maven.shared.artifact.resolve.ArtifactResult> resolveDependencies( ProjectBuildingRequest buildingRequest,
208                                                                                                    List<RemoteRepository> aetherRepositories,
209                                                                                                    TransformableFilter dependencyFilter,
210                                                                                                    CollectRequest request )
211                                                                                                        throws DependencyResolverException
212     // CHECKSTYLE_ON: LineLength
213     {
214         try
215         {
216             DependencyFilter depFilter = null;
217             if ( dependencyFilter != null )
218             {
219                 depFilter = dependencyFilter.transform( new EclipseAetherFilterTransformer() );
220             }
221 
222             DependencyRequest depRequest = new DependencyRequest( request, depFilter );
223 
224             RepositorySystemSession session =
225                 (RepositorySystemSession) Invoker.invoke( buildingRequest, "getRepositorySession" );
226 
227             final DependencyResult dependencyResults = repositorySystem.resolveDependencies( session, depRequest );
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.artifact.resolve.ArtifactResult>()
231             {
232                 @Override
233                 public Iterator<org.apache.maven.shared.artifact.resolve.ArtifactResult> iterator()
234                 {
235                     // CHECKSTYLE_OFF: LineLength
236                     Collection<org.apache.maven.shared.artifact.resolve.ArtifactResult> artResults =
237                         new ArrayList<org.apache.maven.shared.artifact.resolve.ArtifactResult>( dependencyResults.getArtifactResults().size() );
238                     // CHECKSTYLE_ON: LineLength
239 
240                     for ( ArtifactResult artifactResult : dependencyResults.getArtifactResults() )
241                     {
242                         artResults.add( new Maven31ArtifactResult( artifactResult ) );
243                     }
244 
245                     return artResults.iterator();
246                 }
247             };
248         }
249         catch ( DependencyResolutionException e )
250         {
251             throw new Maven31DependencyResolverException( e );
252         }
253     }
254 
255     /**
256      * Based on RepositoryUtils#toDependency(org.apache.maven.model.Dependency, ArtifactTypeRegistry)
257      * 
258      * @param coordinate {@link DependableCoordinate}
259      * @param stereotypes {@link ArtifactTypeRegistry
260      * @return as Aether Dependency
261      */
262     private static Dependency toDependency( DependableCoordinate coordinate, ArtifactTypeRegistry stereotypes )
263     {
264         ArtifactType stereotype = stereotypes.get( coordinate.getType() );
265         if ( stereotype == null )
266         {
267             stereotype = new DefaultArtifactType( coordinate.getType() );
268         }
269 
270         Artifact artifact =
271           new DefaultArtifact( coordinate.getGroupId(), coordinate.getArtifactId(), coordinate.getClassifier(), null,
272                                  coordinate.getVersion(), null, stereotype );
273 
274         return new Dependency( artifact, null );
275     }
276 
277     private static Dependency toDependency( org.apache.maven.model.Dependency root, ArtifactTypeRegistry typeRegistry )
278                     throws DependencyResolverException
279     {
280         Class<?>[] argClasses = new Class<?>[] { org.apache.maven.model.Dependency.class, ArtifactTypeRegistry.class };
281 
282         Object[] args = new Object[] { root, typeRegistry };
283 
284         return (Dependency) Invoker.invoke( RepositoryUtils.class, "toDependency", argClasses, args );
285     }    
286 }