View Javadoc
1   /*
2    * (C) Copyright 2006-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   *     jcarsique
16   */
17  package org.nuxeo.build.ant.artifact;
18  
19  import org.apache.commons.io.IOUtils;
20  import org.apache.maven.RepositoryUtils;
21  import org.apache.tools.ant.BuildException;
22  import org.apache.tools.ant.Project;
23  import org.apache.tools.ant.Task;
24  import org.eclipse.aether.artifact.Artifact;
25  import org.eclipse.aether.graph.Dependency;
26  import org.eclipse.aether.resolution.ArtifactDescriptorException;
27  import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
28  import org.eclipse.aether.resolution.ArtifactDescriptorResult;
29  import org.eclipse.aether.resolution.ArtifactResolutionException;
30  import org.eclipse.aether.util.StringUtils;
31  import org.eclipse.aether.util.artifact.JavaScopes;
32  
33  import org.nuxeo.build.maven.AntBuildMojo;
34  import org.nuxeo.build.maven.ArtifactDescriptor;
35  import org.nuxeo.build.maven.graph.DependencyUtils;
36  
37  import java.io.FileOutputStream;
38  import java.io.IOException;
39  import java.io.OutputStream;
40  import java.util.ArrayList;
41  import java.util.List;
42  import java.util.StringTokenizer;
43  
44  /**
45   * Print the dependency management of a POM TODO NXBT-258
46   *
47   * @since 2.0.2
48   */
49  public class PrintDependencyManagementTask extends Task {
50  
51      private String output;
52  
53      public enum FORMAT {
54          // GAV: group:artifact:version:type:classifier
55          GAV,
56          // Key-value format: FILENAME=GAV
57          KV_F_GAV;
58      }
59  
60      private FORMAT format = FORMAT.KV_F_GAV;
61  
62      private boolean append = false;
63  
64      private String key;
65  
66      private List<String> scopes = null;
67  
68      private String checkOutput;
69  
70      private boolean check;
71  
72      @Override
73      public void execute() throws BuildException {
74          AntBuildMojo mojo = AntBuildMojo.getInstance();
75          OutputStream out = System.out;
76          OutputStream err = System.err;
77          try {
78              if (output != null) {
79                  out = new FileOutputStream(output, append);
80              }
81              if (checkOutput != null) {
82                  err = new FileOutputStream(checkOutput, append);
83              }
84              Artifact artifact;
85              if (key == null) {
86                  artifact = RepositoryUtils.toArtifact(mojo.getProject().getArtifact());
87              } else {
88                  ArtifactDescriptor ad = new ArtifactDescriptor(key);
89                  artifact = ad.getAetherArtifact();
90              }
91              if (StringUtils.isEmpty(artifact.getVersion())) {
92                  artifact = DependencyUtils.setManagedVersion(artifact);
93              }
94              if (StringUtils.isEmpty(artifact.getVersion())) {
95                  artifact = DependencyUtils.setNewestVersion(artifact);
96              }
97              ArtifactDescriptorRequest request = new ArtifactDescriptorRequest();
98              request.setArtifact(artifact);
99              request.setRepositories(mojo.getRemoteRepositories());
100             ArtifactDescriptorResult result = mojo.getSystem().readArtifactDescriptor(mojo.getSession(), request);
101             Throwable checks = new Throwable();
102             for (Dependency dependency : result.getManagedDependencies()) {
103                 if (check) {
104                     try {
105                         DependencyUtils.resolve(dependency.getArtifact());
106                     } catch (ArtifactResolutionException e) {
107                         checks.addSuppressed(e);
108                         String msg = "";
109                         if (checkOutput == null) {
110                             msg = "Cannot resolve ";
111                         }
112                         err.write((msg + toString(dependency)).getBytes(AntBuildMojo.getInstance().getEncoding()));
113                         continue;
114                     }
115                 }
116                 String scope = dependency.getScope();
117                 if ("".equals(scope)) {
118                     scope = JavaScopes.COMPILE;
119                 }
120                 if (scopes == null || scopes.contains(scope)) {
121                     out.write(toString(dependency).getBytes(AntBuildMojo.getInstance().getEncoding()));
122                 }
123             }
124             for (Throwable t : checks.getSuppressed()) {
125                 log(t.getMessage(), Project.MSG_WARN);
126             }
127         } catch (IOException | ArtifactDescriptorException e) {
128             throw new BuildException(e);
129         } finally {
130             IOUtils.closeQuietly(out);
131             IOUtils.closeQuietly(err);
132         }
133 
134     }
135 
136     public String toString(Dependency dependency) {
137         Artifact artifact = dependency.getArtifact();
138         StringBuilder sb = new StringBuilder();
139         switch (format) {
140         case KV_F_GAV:
141             String filename;
142             if (artifact.getFile() == null) {
143                 filename = artifact.getArtifactId() + "-" + artifact.getBaseVersion();
144                 if (!StringUtils.isEmpty(artifact.getClassifier())) {
145                     filename += "-" + artifact.getClassifier();
146                 }
147                 filename += "." + artifact.getExtension();
148             } else {
149                 filename = artifact.getFile().getName();
150             }
151             sb.append(filename);
152 
153             sb.append('=');
154             // fall through
155         case GAV:
156             sb.append(artifact.getGroupId());
157             sb.append(':').append(artifact.getArtifactId());
158             sb.append(':').append(artifact.getVersion());
159             sb.append(':').append(artifact.getExtension());
160             sb.append(':').append(artifact.getClassifier());
161             sb.append(':').append(dependency.getScope());
162             break;
163         default:
164         }
165         sb.append(System.lineSeparator());
166         return sb.toString();
167     }
168 
169     /**
170      * Output file. If null, the console is used.
171      *
172      * @param output
173      */
174     public void setOutput(String output) {
175         this.output = output;
176     }
177 
178     /**
179      * Defines output format
180      *
181      * @param format
182      */
183     public void setFormat(FORMAT format) {
184         this.format = format;
185     }
186 
187     /**
188      * Output append mode
189      *
190      * @param append
191      */
192     public void setAppend(boolean append) {
193         this.append = append;
194     }
195 
196     /**
197      * If set, filter on the {@code scopes}.
198      *
199      * @param scopes
200      * @since 2.0.3
201      */
202     public void setScopes(String scopes) {
203         StringTokenizer st = new StringTokenizer(scopes, ",");
204         this.scopes = new ArrayList<>();
205         while (st.hasMoreTokens()) {
206             this.scopes.add(st.nextToken());
207         }
208     }
209 
210     /**
211      * GAV of artifact to analyze. If null, the current project is used.
212      *
213      * @param key
214      */
215     public void setKey(String key) {
216         this.key = key;
217     }
218 
219     /**
220      * Whether to check the artifact availability (using resolve).
221      *
222      * @param check
223      */
224     public void setCheck(boolean check) {
225         this.check = check;
226     }
227 
228     /**
229      * Output file for check errors. If null, the sdterr is used.
230      *
231      * @param checkOutput
232      * @since 2.0.3
233      */
234     public void setCheckOutput(String checkOutput) {
235         this.checkOutput = checkOutput;
236     }
237 
238 }