View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.dependency.resolvers;
20  
21  import java.io.IOException;
22  import java.util.LinkedHashSet;
23  import java.util.Objects;
24  import java.util.Set;
25  
26  import org.apache.maven.artifact.Artifact;
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugins.annotations.LifecyclePhase;
29  import org.apache.maven.plugins.annotations.Mojo;
30  import org.apache.maven.plugins.annotations.Parameter;
31  import org.apache.maven.plugins.dependency.utils.DependencyUtil;
32  import org.apache.maven.project.ProjectBuildingRequest;
33  import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
34  import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
35  import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
36  import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
37  import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
38  import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
39  import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
40  import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
41  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
42  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
43  import org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate;
44  import org.apache.maven.shared.transfer.dependencies.DependableCoordinate;
45  import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
46  
47  /**
48   * Goal that resolves all project plugins and reports and their dependencies.
49   *
50   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
51   * @since 2.0
52   */
53  @Mojo(name = "resolve-plugins", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
54  public class ResolvePluginsMojo extends AbstractResolveMojo {
55  
56      @Parameter(property = "outputEncoding", defaultValue = "${project.reporting.outputEncoding}")
57      private String outputEncoding;
58  
59      /**
60       * Output absolute filename for resolved artifacts
61       *
62       * @since 2.0
63       */
64      @Parameter(property = "outputAbsoluteArtifactFilename", defaultValue = "false")
65      private boolean outputAbsoluteArtifactFilename;
66  
67      /**
68       * Main entry into mojo. Gets the list of dependencies and iterates through displaying the resolved version.
69       *
70       * @throws MojoExecutionException with a message if an error occurs.
71       */
72      @Override
73      protected void doExecute() throws MojoExecutionException {
74          try {
75              // ideally this should either be DependencyCoordinates or DependencyNode
76              final Set<Artifact> plugins = resolvePluginArtifacts();
77  
78              StringBuilder sb = new StringBuilder();
79              sb.append(System.lineSeparator());
80              sb.append("The following plugins have been resolved:");
81              sb.append(System.lineSeparator());
82              if (plugins == null || plugins.isEmpty()) {
83                  sb.append("   none");
84                  sb.append(System.lineSeparator());
85              } else {
86                  for (Artifact plugin : plugins) {
87                      String artifactFilename = null;
88                      if (outputAbsoluteArtifactFilename) {
89                          try {
90                              // we want to print the absolute file name here
91                              artifactFilename =
92                                      plugin.getFile().getAbsoluteFile().getPath();
93                          } catch (NullPointerException e) {
94                              // ignore the null pointer, we'll output a null string
95                              artifactFilename = null;
96                          }
97                      }
98  
99                      String id = plugin.toString();
100                     sb.append("   ")
101                             .append(id)
102                             .append(outputAbsoluteArtifactFilename ? ":" + artifactFilename : "")
103                             .append(System.lineSeparator());
104 
105                     if (!excludeTransitive) {
106                         DefaultDependableCoordinate pluginCoordinate = new DefaultDependableCoordinate();
107                         pluginCoordinate.setGroupId(plugin.getGroupId());
108                         pluginCoordinate.setArtifactId(plugin.getArtifactId());
109                         pluginCoordinate.setVersion(plugin.getVersion());
110 
111                         for (final Artifact artifact : resolveArtifactDependencies(pluginCoordinate)) {
112                             artifactFilename = null;
113                             if (outputAbsoluteArtifactFilename) {
114                                 try {
115                                     // we want to print the absolute file name here
116                                     artifactFilename =
117                                             artifact.getFile().getAbsoluteFile().getPath();
118                                 } catch (NullPointerException e) {
119                                     // ignore the null pointer, we'll output a null string
120                                     artifactFilename = null;
121                                 }
122                             }
123 
124                             id = artifact.toString();
125                             sb.append("      ")
126                                     .append(id)
127                                     .append(outputAbsoluteArtifactFilename ? ":" + artifactFilename : "")
128                                     .append(System.lineSeparator());
129                         }
130                     }
131                 }
132                 sb.append(System.lineSeparator());
133 
134                 String output = sb.toString();
135                 if (outputFile == null) {
136                     DependencyUtil.log(output, getLog());
137                 } else {
138                     String encoding = Objects.toString(outputEncoding, "UTF-8");
139                     DependencyUtil.write(output, outputFile, appendOutput, encoding);
140                 }
141             }
142         } catch (IOException | ArtifactFilterException | ArtifactResolverException | DependencyResolverException e) {
143             throw new MojoExecutionException(e.getMessage(), e);
144         }
145     }
146 
147     /**
148      * This method resolves all transitive dependencies of an artifact.
149      *
150      * @param artifact the artifact used to retrieve dependencies
151      * @return resolved set of dependencies
152      * @throws DependencyResolverException in case of error while resolving artifacts.
153      */
154     private Set<Artifact> resolveArtifactDependencies(final DependableCoordinate artifact)
155             throws DependencyResolverException {
156         ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest();
157 
158         Iterable<ArtifactResult> artifactResults =
159                 getDependencyResolver().resolveDependencies(buildingRequest, artifact, null);
160 
161         Set<Artifact> artifacts = new LinkedHashSet<>();
162 
163         for (final ArtifactResult artifactResult : artifactResults) {
164             artifacts.add(artifactResult.getArtifact());
165         }
166 
167         return artifacts;
168     }
169 
170     /**
171      * @return {@link FilterArtifacts}
172      */
173     private FilterArtifacts getArtifactsFilter() {
174         final FilterArtifacts filter = new FilterArtifacts();
175 
176         if (excludeReactor) {
177 
178             filter.addFilter(new ExcludeReactorProjectsArtifactFilter(reactorProjects, getLog()));
179         }
180 
181         filter.addFilter(new ScopeFilter(
182                 DependencyUtil.cleanToBeTokenizedString(this.includeScope),
183                 DependencyUtil.cleanToBeTokenizedString(this.excludeScope)));
184 
185         filter.addFilter(new TypeFilter(
186                 DependencyUtil.cleanToBeTokenizedString(this.includeTypes),
187                 DependencyUtil.cleanToBeTokenizedString(this.excludeTypes)));
188 
189         filter.addFilter(new ClassifierFilter(
190                 DependencyUtil.cleanToBeTokenizedString(this.includeClassifiers),
191                 DependencyUtil.cleanToBeTokenizedString(this.excludeClassifiers)));
192 
193         filter.addFilter(new GroupIdFilter(
194                 DependencyUtil.cleanToBeTokenizedString(this.includeGroupIds),
195                 DependencyUtil.cleanToBeTokenizedString(this.excludeGroupIds)));
196 
197         filter.addFilter(new ArtifactIdFilter(
198                 DependencyUtil.cleanToBeTokenizedString(this.includeArtifactIds),
199                 DependencyUtil.cleanToBeTokenizedString(this.excludeArtifactIds)));
200 
201         return filter;
202     }
203 
204     /**
205      * This method resolves the plugin artifacts from the project.
206      *
207      * @return set of resolved plugin artifacts
208      * @throws ArtifactFilterException in case of an error
209      * @throws ArtifactResolverException in case of an error
210      */
211     private Set<Artifact> resolvePluginArtifacts() throws ArtifactFilterException, ArtifactResolverException {
212         final Set<Artifact> plugins = getProject().getPluginArtifacts();
213         final Set<Artifact> reports = getProject().getReportArtifacts();
214 
215         Set<Artifact> artifacts = new LinkedHashSet<>();
216         artifacts.addAll(reports);
217         artifacts.addAll(plugins);
218 
219         final FilterArtifacts filter = getArtifactsFilter();
220         artifacts = filter.filter(artifacts);
221 
222         // final ArtifactFilter filter = getPluginFilter();
223         for (final Artifact artifact : new LinkedHashSet<>(artifacts)) {
224             // if ( !filter.include( artifact ) )
225             // {
226             // final String logStr =
227             // String.format( " Plugin SKIPPED: %s", DependencyUtil.getFormattedFileName( artifact, false ) );
228             //
229             // if ( !silent )
230             // {
231             // this.getLog().info( logStr );
232             // }
233             //
234             // artifacts.remove( artifact );
235             // continue;
236             // }
237 
238             ProjectBuildingRequest buildingRequest = newResolvePluginProjectBuildingRequest();
239 
240             // resolve the new artifact
241             getArtifactResolver().resolveArtifact(buildingRequest, artifact).getArtifact();
242         }
243         return artifacts;
244     }
245 
246     @Override
247     protected ArtifactsFilter getMarkedArtifactFilter() {
248         return null;
249     }
250 }