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.HashSet;
23  import java.util.LinkedHashSet;
24  import java.util.Objects;
25  import java.util.Set;
26  
27  import org.apache.maven.RepositoryUtils;
28  import org.apache.maven.artifact.Artifact;
29  import org.apache.maven.plugin.MojoExecutionException;
30  import org.apache.maven.plugins.annotations.LifecyclePhase;
31  import org.apache.maven.plugins.annotations.Mojo;
32  import org.apache.maven.plugins.annotations.Parameter;
33  import org.apache.maven.plugins.dependency.utils.DependencyUtil;
34  import org.apache.maven.project.ProjectBuildingRequest;
35  import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
36  import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
37  import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
38  import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
39  import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
40  import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
41  import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
42  import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
43  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
44  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
45  import org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate;
46  import org.apache.maven.shared.transfer.dependencies.DependableCoordinate;
47  import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
48  import org.eclipse.aether.resolution.ArtifactResolutionException;
49  
50  /**
51   * Goal that resolves all project plugins and reports and their dependencies.
52   *
53   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
54   * @since 2.0
55   */
56  @Mojo(name = "resolve-plugins", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
57  public class ResolvePluginsMojo extends AbstractResolveMojo {
58  
59      @Parameter(property = "outputEncoding", defaultValue = "${project.reporting.outputEncoding}")
60      private String outputEncoding;
61  
62      /**
63       * Output absolute filename for resolved artifacts
64       *
65       * @since 2.0
66       */
67      @Parameter(property = "outputAbsoluteArtifactFilename", defaultValue = "false")
68      private boolean outputAbsoluteArtifactFilename;
69  
70      /**
71       * Main entry into mojo. Gets the list of dependencies and iterates through displaying the resolved version.
72       *
73       * @throws MojoExecutionException with a message if an error occurs.
74       */
75      @Override
76      protected void doExecute() throws MojoExecutionException {
77          try {
78              // ideally this should either be DependencyCoordinates or DependencyNode
79              final Set<Artifact> plugins = resolvePluginArtifacts();
80  
81              StringBuilder sb = new StringBuilder();
82              sb.append(System.lineSeparator());
83              sb.append("The following plugins have been resolved:");
84              sb.append(System.lineSeparator());
85              if (plugins == null || plugins.isEmpty()) {
86                  sb.append("   none");
87                  sb.append(System.lineSeparator());
88              } else {
89                  for (Artifact plugin : plugins) {
90                      String artifactFilename = null;
91                      if (outputAbsoluteArtifactFilename) {
92                          try {
93                              // we want to print the absolute file name here
94                              artifactFilename =
95                                      plugin.getFile().getAbsoluteFile().getPath();
96                          } catch (NullPointerException e) {
97                              // ignore the null pointer, we'll output a null string
98                              artifactFilename = null;
99                          }
100                     }
101 
102                     String id = plugin.toString();
103                     sb.append("   ")
104                             .append(id)
105                             .append(outputAbsoluteArtifactFilename ? ":" + artifactFilename : "")
106                             .append(System.lineSeparator());
107 
108                     if (!excludeTransitive) {
109                         DefaultDependableCoordinate pluginCoordinate = new DefaultDependableCoordinate();
110                         pluginCoordinate.setGroupId(plugin.getGroupId());
111                         pluginCoordinate.setArtifactId(plugin.getArtifactId());
112                         pluginCoordinate.setVersion(plugin.getVersion());
113 
114                         for (final Artifact artifact : resolveArtifactDependencies(pluginCoordinate)) {
115                             artifactFilename = null;
116                             if (outputAbsoluteArtifactFilename) {
117                                 try {
118                                     // we want to print the absolute file name here
119                                     artifactFilename =
120                                             artifact.getFile().getAbsoluteFile().getPath();
121                                 } catch (NullPointerException e) {
122                                     // ignore the null pointer, we'll output a null string
123                                     artifactFilename = null;
124                                 }
125                             }
126 
127                             id = artifact.toString();
128                             sb.append("      ")
129                                     .append(id)
130                                     .append(outputAbsoluteArtifactFilename ? ":" + artifactFilename : "")
131                                     .append(System.lineSeparator());
132                         }
133                     }
134                 }
135                 sb.append(System.lineSeparator());
136 
137                 String output = sb.toString();
138                 if (outputFile == null) {
139                     DependencyUtil.log(output, getLog());
140                 } else {
141                     String encoding = Objects.toString(outputEncoding, "UTF-8");
142                     DependencyUtil.write(output, outputFile, appendOutput, encoding);
143                 }
144             }
145         } catch (IOException
146                 | ArtifactFilterException
147                 | ArtifactResolverException
148                 | DependencyResolverException
149                 | ArtifactResolutionException e) {
150             throw new MojoExecutionException(e.getMessage(), e);
151         }
152     }
153 
154     /**
155      * This method resolves all transitive dependencies of an artifact.
156      *
157      * @param artifact the artifact used to retrieve dependencies
158      * @return resolved set of dependencies
159      * @throws DependencyResolverException in case of error while resolving artifacts.
160      */
161     private Set<Artifact> resolveArtifactDependencies(final DependableCoordinate artifact)
162             throws DependencyResolverException {
163         ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest();
164 
165         Iterable<ArtifactResult> artifactResults =
166                 getDependencyResolver().resolveDependencies(buildingRequest, artifact, null);
167 
168         Set<Artifact> artifacts = new LinkedHashSet<>();
169 
170         for (final ArtifactResult artifactResult : artifactResults) {
171             artifacts.add(artifactResult.getArtifact());
172         }
173 
174         return artifacts;
175     }
176 
177     /**
178      * @return {@link FilterArtifacts}
179      */
180     private FilterArtifacts getArtifactsFilter() {
181         final FilterArtifacts filter = new FilterArtifacts();
182 
183         if (excludeReactor) {
184 
185             filter.addFilter(new ExcludeReactorProjectsArtifactFilter(reactorProjects, getLog()));
186         }
187 
188         filter.addFilter(new ScopeFilter(
189                 DependencyUtil.cleanToBeTokenizedString(this.includeScope),
190                 DependencyUtil.cleanToBeTokenizedString(this.excludeScope)));
191 
192         filter.addFilter(new TypeFilter(
193                 DependencyUtil.cleanToBeTokenizedString(this.includeTypes),
194                 DependencyUtil.cleanToBeTokenizedString(this.excludeTypes)));
195 
196         filter.addFilter(new ClassifierFilter(
197                 DependencyUtil.cleanToBeTokenizedString(this.includeClassifiers),
198                 DependencyUtil.cleanToBeTokenizedString(this.excludeClassifiers)));
199 
200         filter.addFilter(new GroupIdFilter(
201                 DependencyUtil.cleanToBeTokenizedString(this.includeGroupIds),
202                 DependencyUtil.cleanToBeTokenizedString(this.excludeGroupIds)));
203 
204         filter.addFilter(new ArtifactIdFilter(
205                 DependencyUtil.cleanToBeTokenizedString(this.includeArtifactIds),
206                 DependencyUtil.cleanToBeTokenizedString(this.excludeArtifactIds)));
207 
208         return filter;
209     }
210 
211     /**
212      * This method resolves the plugin artifacts from the project.
213      *
214      * @return set of resolved plugin artifacts
215      * @throws ArtifactFilterException in case of an error
216      * @throws ArtifactResolverException in case of an error
217      */
218     private Set<Artifact> resolvePluginArtifacts()
219             throws ArtifactFilterException, ArtifactResolverException, ArtifactResolutionException {
220         final Set<Artifact> plugins = getProject().getPluginArtifacts();
221         final Set<Artifact> reports = getProject().getReportArtifacts();
222 
223         Set<Artifact> artifacts = new HashSet<>();
224         artifacts.addAll(reports);
225         artifacts.addAll(plugins);
226 
227         final FilterArtifacts filter = getArtifactsFilter();
228         artifacts = filter.filter(artifacts);
229 
230         Set<Artifact> result = new HashSet<>();
231         for (final Artifact artifact : new LinkedHashSet<>(artifacts)) {
232 
233             org.eclipse.aether.artifact.Artifact resolveArtifact = getResolverUtil()
234                     .resolveArtifact(
235                             RepositoryUtils.toArtifact(artifact), getProject().getRemotePluginRepositories());
236             result.add(RepositoryUtils.toArtifact(resolveArtifact));
237         }
238         return result;
239     }
240 
241     @Override
242     protected ArtifactsFilter getMarkedArtifactFilter() {
243         return null;
244     }
245 }