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