View Javadoc
1   /*
2    * (C) Copyright 2013-2015 Nuxeo SA (http://nuxeo.com/) and contributors.
3    *
4    * All rights reserved. This program and the accompanying materials
5    * are made available under the terms of the GNU Lesser General Public License
6    * (LGPL) version 2.1 which accompanies this distribution, and is available at
7    * http://www.gnu.org/licenses/lgpl-2.1.html
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   * Lesser General Public License for more details.
13   *
14   * Contributors:
15   *     Julien Carsique
16   *
17   */
18  
19  package org.nuxeo.build.maven.graph;
20  
21  import java.util.List;
22  
23  import org.apache.maven.RepositoryUtils;
24  import org.apache.maven.artifact.handler.ArtifactHandler;
25  import org.apache.tools.ant.BuildException;
26  import org.apache.tools.ant.Project;
27  import org.eclipse.aether.artifact.Artifact;
28  import org.eclipse.aether.collection.DependencyManagement;
29  import org.eclipse.aether.graph.Dependency;
30  import org.eclipse.aether.graph.DependencyNode;
31  import org.eclipse.aether.repository.RemoteRepository;
32  import org.eclipse.aether.resolution.ArtifactRequest;
33  import org.eclipse.aether.resolution.ArtifactResolutionException;
34  import org.eclipse.aether.resolution.ArtifactResult;
35  import org.eclipse.aether.resolution.DependencyRequest;
36  import org.eclipse.aether.resolution.DependencyResolutionException;
37  import org.eclipse.aether.resolution.DependencyResult;
38  import org.eclipse.aether.resolution.VersionRangeRequest;
39  import org.eclipse.aether.resolution.VersionRangeResolutionException;
40  import org.eclipse.aether.resolution.VersionRangeResult;
41  import org.eclipse.aether.util.artifact.ArtifactIdUtils;
42  import org.nuxeo.build.ant.AntClient;
43  import org.nuxeo.build.maven.AntBuildMojo;
44  import org.nuxeo.build.maven.filter.Filter;
45  
46  /**
47   * Utility class for dealing with {@link org.apache.maven.artifact.Artifact},
48   * {@link org.eclipse.aether.artifact.Artifact} and {@link org.eclipse.aether.graph.Dependency}
49   *
50   * @since 2.0
51   */
52  public class DependencyUtils {
53  
54      private DependencyUtils() {
55      }
56  
57      public static org.apache.maven.artifact.Artifact aetherToMaven(Artifact aetherArtifact, String scope,
58              ArtifactHandler artifactHandler) {
59          org.apache.maven.artifact.Artifact mavenArtifact = new org.apache.maven.artifact.DefaultArtifact(
60                  aetherArtifact.getGroupId(), aetherArtifact.getArtifactId(), aetherArtifact.getVersion(), scope,
61                  aetherArtifact.getExtension(), aetherArtifact.getClassifier(), artifactHandler);
62          mavenArtifact.setFile(aetherArtifact.getFile());
63          mavenArtifact.setResolved(aetherArtifact.getFile() != null);
64          return mavenArtifact;
65      }
66  
67      public static org.apache.maven.artifact.Artifact toMavenArtifact(Dependency dependency) {
68          return aetherToMaven(
69                  dependency.getArtifact(),
70                  dependency.getScope(),
71                  AntBuildMojo.getInstance()
72                              .getArtifactHandlerManager()
73                              .getArtifactHandler(dependency.getArtifact().getExtension()));
74      }
75  
76      public static org.apache.maven.artifact.Artifact aetherToMaven(Artifact aetherArtifact, String scope) {
77          return aetherToMaven(aetherArtifact, scope, AntBuildMojo.getInstance()
78                                                                  .getArtifactHandlerManager()
79                                                                  .getArtifactHandler(aetherArtifact.getExtension()));
80      }
81  
82      /**
83       * @deprecated Since 2.0.4. Use {@link RepositoryUtils#toArtifact(Artifact)} instead.
84       */
85      @Deprecated
86      public static Artifact mavenToAether(org.apache.maven.artifact.Artifact artifact) {
87          return RepositoryUtils.toArtifact(artifact);
88      }
89  
90      /**
91       * @throws org.eclipse.aether.resolution.ArtifactResolutionException
92       */
93      public static Artifact resolve(Artifact artifact) throws org.eclipse.aether.resolution.ArtifactResolutionException {
94          AntBuildMojo mojo = AntBuildMojo.getInstance();
95          return resolve(artifact, mojo.getRemoteRepositories());
96      }
97  
98      /**
99       * @throws org.eclipse.aether.resolution.ArtifactResolutionException
100      */
101     public static Artifact resolve(Artifact artifact, List<RemoteRepository> remoteRepositories)
102             throws org.eclipse.aether.resolution.ArtifactResolutionException {
103         AntBuildMojo mojo = AntBuildMojo.getInstance();
104         ArtifactResult result = mojo.getSystem().resolveArtifact(mojo.getSession(),
105                 new ArtifactRequest(artifact, remoteRepositories, null));
106         artifact = result.getArtifact();
107         AntClient.getInstance().log(artifact + " resolved to  " + artifact.getFile(), Project.MSG_DEBUG);
108         return artifact;
109     }
110 
111     /**
112      * @throws ArtifactResolutionException
113      * @deprecated Prefer use of {@link #resolve(org.eclipse.aether.artifact.Artifact)}
114      * @see #mavenToAether(org.apache.maven.artifact.Artifact)
115      */
116     @Deprecated
117     public static void resolve(org.apache.maven.artifact.Artifact artifact) throws ArtifactResolutionException {
118         resolve(RepositoryUtils.toArtifact(artifact));
119     }
120 
121     /**
122      * The generated dependency has no exclusions.
123      *
124      * @deprecated Since 2.0.4. Use
125      *             {@link RepositoryUtils#toDependency(org.apache.maven.artifact.Artifact, java.util.Collection)} or
126      *             {@link RepositoryUtils#toDependency(org.apache.maven.model.Dependency, org.eclipse.aether.artifact.ArtifactTypeRegistry)}
127      *             instead
128      */
129     @Deprecated
130     public static Dependency mavenToDependency(org.apache.maven.artifact.Artifact artifact) {
131         // String scope = artifact.getScope() != null ? artifact.getScope()
132         // : JavaScopes.COMPILE;
133         return new Dependency(RepositoryUtils.toArtifact(artifact), artifact.getScope(), artifact.isOptional());
134     }
135 
136     /**
137      * FIXME JC doesn't work because of depth < 2 in org.eclipse.aether.collection.DependencyManager
138      *
139      * @return The dependency on which the dependencyManagement has been applied.
140      */
141     public static Dependency getManagedDependency(Dependency dependency) {
142         AntBuildMojo mojo = AntBuildMojo.getInstance();
143         DependencyManagement depMgt = mojo.getSession().getDependencyManager().manageDependency(dependency);
144         if (depMgt != null) {
145             if (depMgt.getVersion() != null) {
146                 Artifact artifact = dependency.getArtifact();
147                 dependency = dependency.setArtifact(artifact.setVersion(depMgt.getVersion()));
148             }
149             if (depMgt.getProperties() != null) {
150                 Artifact artifact = dependency.getArtifact();
151                 dependency = dependency.setArtifact(artifact.setProperties(depMgt.getProperties()));
152             }
153             if (depMgt.getScope() != null) {
154                 dependency = dependency.setScope(depMgt.getScope());
155             }
156             if (depMgt.getOptional() != null) {
157                 dependency = dependency.setOptional(depMgt.getOptional());
158             }
159             if (depMgt.getExclusions() != null) {
160                 dependency = dependency.setExclusions(depMgt.getExclusions());
161             }
162         }
163         return dependency;
164     }
165 
166     /**
167      * Look for a version in the project dependencyManagement for the given artifact and set it.
168      *
169      * @return The new artifact if the version changed, else the original one
170      */
171     public static Artifact setManagedVersion(Artifact artifact) {
172         AntBuildMojo mojo = AntBuildMojo.getInstance();
173         List<org.apache.maven.model.Dependency> managedDeps = AntBuildMojo.getInstance()
174                                                                           .getProject()
175                                                                           .getDependencyManagement()
176                                                                           .getDependencies();
177         for (org.apache.maven.model.Dependency dependency : managedDeps) {
178             Artifact managedArtifact = RepositoryUtils.toDependency(dependency,
179                     mojo.getSession().getArtifactTypeRegistry()).getArtifact();
180             if (ArtifactIdUtils.equalsVersionlessId(managedArtifact, artifact)) {
181                 artifact = artifact.setVersion(managedArtifact.getVersion());
182                 AntClient.getInstance().log("Managed version set on " + artifact);
183                 break;
184             }
185         }
186         return artifact;
187     }
188 
189     /**
190      * Look for the newest available version in the configured repositories.
191      *
192      * @return The new artifact if the version changed, else the original one
193      */
194     public static Artifact setNewestVersion(Artifact artifact) {
195         AntBuildMojo mojo = AntBuildMojo.getInstance();
196         artifact = artifact.setVersion("[0,)");
197         VersionRangeRequest rangeRequest = new VersionRangeRequest(artifact, AntBuildMojo.getInstance()
198                                                                                          .getRemoteRepositories(), null);
199         try {
200             VersionRangeResult rangeResult = mojo.getSystem().resolveVersionRange(mojo.getSession(), rangeRequest);
201             AntClient.getInstance().log(
202                     String.format("Versions found for %s: %s", artifact, rangeResult.getVersions()), Project.MSG_DEBUG);
203             artifact = artifact.setVersion(rangeResult.getHighestVersion().toString());
204             AntClient.getInstance().log("Highest version found set on " + artifact);
205         } catch (VersionRangeResolutionException e) {
206             AntClient.getInstance().log(e.getMessage(), e, Project.MSG_ERR);
207         }
208         return artifact;
209     }
210 
211     /**
212      * TODO NXBT-696 manage depth limit
213      */
214     public static DependencyResult resolveDependencies(DependencyNode node, Filter filter, int depth) {
215         AntBuildMojo mojo = AntBuildMojo.getInstance();
216         AntClient.getInstance().log(String.format("Resolving %s with filter %s and depth %d", node, filter, depth),
217                 Project.MSG_DEBUG);
218         DependencyRequest dependencyRequest = new DependencyRequest(node, filter);
219         try {
220             DependencyResult result = mojo.getSystem().resolveDependencies(mojo.getSession(), dependencyRequest);
221             AntClient.getInstance().log("Dependency result: " + result, new Error(), Project.MSG_DEBUG);
222             AntClient.getInstance().log("Dependency exceptions: " + result.getCollectExceptions(), Project.MSG_DEBUG);
223             return result;
224         } catch (DependencyResolutionException e) {
225             throw new BuildException("Cannot resolve dependency tree for " + node, e);
226         }
227     }
228 
229 }