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