View Javadoc

1   /*
2    * Copyright 2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.maven.plugin.jboss.modules.aether;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import org.sonatype.aether.RepositorySystem;
22  import org.sonatype.aether.RepositorySystemSession;
23  import org.sonatype.aether.artifact.Artifact;
24  import org.sonatype.aether.collection.CollectRequest;
25  import org.sonatype.aether.collection.DependencyTraverser;
26  import org.sonatype.aether.graph.Dependency;
27  import org.sonatype.aether.graph.DependencyFilter;
28  import org.sonatype.aether.graph.DependencyNode;
29  import org.sonatype.aether.repository.RemoteRepository;
30  import org.sonatype.aether.resolution.DependencyRequest;
31  import org.sonatype.aether.resolution.DependencyResolutionException;
32  import org.sonatype.aether.resolution.DependencyResult;
33  import org.sonatype.aether.util.filter.AndDependencyFilter;
34  import org.sonatype.aether.util.graph.PreorderNodeListGenerator;
35  
36  import de.smartics.maven.plugin.jboss.modules.aether.filter.DependencyFlagger;
37  import de.smartics.maven.plugin.jboss.modules.aether.filter.DirectDependenciesOnlyFilter;
38  
39  /**
40   * The repository to access artifacts to resolve for property descriptor
41   * information.
42   */
43  public final class MavenRepository
44  { // NOPMD
45    // ********************************* Fields *********************************
46  
47    // --- constants ------------------------------------------------------------
48  
49    // --- members --------------------------------------------------------------
50  
51    /**
52     * Resolver for artifact repositories.
53     */
54    private final RepositorySystem repositorySystem;
55  
56    /**
57     * The current repository/network configuration of Maven.
58     */
59    private final RepositorySystemSession session;
60  
61    /**
62     * The project's remote repositories to use for the resolution of
63     * dependencies.
64     */
65    private final List<RemoteRepository> remoteRepositories;
66  
67    /**
68     * The list of dependency filters to apply to the dependency request. This
69     * allows to limit the collect request since every unresolved dependency is
70     * skipped.
71     */
72    private final List<DependencyFilter> dependencyFilters;
73  
74    /**
75     * The list of managed dependencies to allow to resolve the appropriat
76     * versions of artifacts.
77     */
78    private final List<Dependency> managedDependencies;
79  
80    /**
81     * The flag to control accessing the local repository only.
82     */
83    private final boolean offline;
84  
85    /**
86     * The generator of traversers used to prune dependency branches.
87     */
88    private final DependencyTraverserGenerator traverserGenerator;
89  
90    // ****************************** Initializer *******************************
91  
92    // ****************************** Constructors ******************************
93  
94    MavenRepository(final RepositoryBuilder builder)
95    {
96      this.remoteRepositories = builder.getRemoteRepositories();
97      this.session = builder.getSession();
98      this.repositorySystem = builder.getRepositorySystem();
99      this.dependencyFilters = builder.getDependencyFilters();
100     this.managedDependencies = builder.getManagedDependencies();
101     this.offline = builder.isOffline();
102     this.traverserGenerator = builder.getTraverserGenerator();
103   }
104 
105   // ****************************** Inner Classes *****************************
106 
107   // ********************************* Methods ********************************
108 
109   // --- init -----------------------------------------------------------------
110 
111   // --- get&set --------------------------------------------------------------
112 
113   // --- business -------------------------------------------------------------
114 
115   /**
116    * Resolves the dependency so that it is locally accessible.
117    *
118    * @param dependency the dependency to resolve.
119    * @return the reference to the resolved artifact that is now stored locally
120    *         ready for access.
121    * @throws DependencyResolutionException if the dependency tree could not be
122    *           built or any dependency artifact could not be resolved.
123    */
124   public MavenResponse resolve(final Dependency dependency)
125     throws DependencyResolutionException
126   {
127     final DependencyRequest dependencyRequest = createRequest(dependency, true);
128     return configureRequest(dependencyRequest);
129   }
130 
131   /**
132    * Resolves direct dependencies of the dependency so that they are locally
133    * accessible.
134    *
135    * @param dependency the dependency to resolve.
136    * @return the reference to the resolved artifact that is now stored locally
137    *         ready for access.
138    * @throws DependencyResolutionException if the dependency tree could not be
139    *           built or any dependency artifact could not be resolved.
140    */
141   public MavenResponse resolveDirect(final Dependency dependency)
142     throws DependencyResolutionException
143   {
144     final DependencyRequest dependencyRequest =
145         createRequest(dependency, false);
146     return configureRequest(dependencyRequest);
147   }
148 
149   private DependencyRequest createRequest(final Dependency dependency,
150       final boolean transitive)
151   {
152     final CollectRequest collectRequest = new CollectRequest();
153     collectRequest.setRoot(dependency);
154     collectRequest.setManagedDependencies(managedDependencies);
155     return configureRequest(collectRequest, transitive);
156   }
157 
158   private static MavenResponse createResult(
159       final PreorderNodeListGenerator generator)
160   {
161     final MavenResponse response = new MavenResponse();
162     final List<DependencyNode> nodes = generator.getNodes();
163 
164     // This is a kind of workaround: We should limit the collect request, but
165     // have not enough information with the DependencySelector interface
166     // (we need the parents!). Therefore we use the DependencyFilter interface
167     // (which has access to the parents) to resolve only those that meet our
168     // constraints. Afterwards we skip all unresolved dependencies (which are
169     // those that do not reference a file).
170     for (final DependencyNode node : nodes)
171     {
172       final Dependency dependency = node.getDependency();
173       final Artifact artifact = dependency.getArtifact();
174       if (!(artifact.getFile() == null || DependencyFlagger.INSTANCE
175           .isFlagged(dependency)))
176       {
177         response.add(dependency);
178       }
179     }
180     return response;
181   }
182 
183   /**
184    * Resolves the dependencies so that it is locally accessible.
185    *
186    * @param dependencies the rootDependencies to resolve.
187    * @return the reference to the resolved artifact that is now stored locally
188    *         ready for access.
189    * @throws DependencyResolutionException if the dependency tree could not be
190    *           built or any dependency artifact could not be resolved.
191    */
192   public MavenResponse resolve(final List<Dependency> dependencies)
193     throws DependencyResolutionException
194   {
195     final DependencyRequest dependencyRequest =
196         createRequest(dependencies, true);
197     return configureRequest(dependencyRequest);
198   }
199 
200   private MavenResponse configureRequest(
201       final DependencyRequest dependencyRequest)
202     throws DependencyResolutionException
203   {
204     try
205     {
206       final DependencyTraverser traverser =
207           traverserGenerator.createDependencyTraverser(session
208               .getDependencyTraverser());
209       final FilterSession filterSession = new FilterSession(session, traverser);
210       final DependencyResult result =
211           repositorySystem
212               .resolveDependencies(filterSession, dependencyRequest);
213       final DependencyNode rootNode = result.getRoot();
214       final PreorderNodeListGenerator generator =
215           new PreorderNodeListGenerator();
216       rootNode.accept(generator);
217 
218       final MavenResponse response = createResult(generator);
219       return response;
220     }
221     catch (final NullPointerException e) // NOPMD aether problem
222     {
223       // Only occurs if a parent dependency of the resource cannot be resolved
224       throw new DependencyResolutionException(new DependencyResult(
225           dependencyRequest), e);
226     }
227   }
228 
229   private DependencyRequest createRequest(final List<Dependency> dependencies,
230       final boolean transitive)
231   {
232     final CollectRequest collectRequest = new CollectRequest();
233     collectRequest.setDependencies(dependencies);
234     return configureRequest(collectRequest, transitive);
235   }
236 
237   private DependencyRequest configureRequest(
238       final CollectRequest collectRequest, final boolean transitive)
239   {
240     if (!offline && !remoteRepositories.isEmpty())
241     {
242       collectRequest.setRepositories(remoteRepositories);
243     }
244 
245     final DependencyRequest dependencyRequest = new DependencyRequest();
246     dependencyRequest.setCollectRequest(collectRequest);
247     applyFilters(dependencyRequest, transitive);
248 
249     return dependencyRequest;
250   }
251 
252   private void applyFilters(final DependencyRequest dependencyRequest,
253       final boolean transitive)
254   {
255     final List<DependencyFilter> filters = new ArrayList<DependencyFilter>();
256     if (dependencyFilters != null)
257     {
258       filters.addAll(dependencyFilters);
259     }
260     if (!transitive)
261     {
262       filters.add(DirectDependenciesOnlyFilter.INSTANCE);
263     }
264     if (!filters.isEmpty())
265     {
266       final AndDependencyFilter dependencyFilter =
267           new AndDependencyFilter(filters);
268       dependencyRequest.setFilter(dependencyFilter);
269     }
270   }
271 
272   // --- object basics --------------------------------------------------------
273 
274 }