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.report.projectinfo;
20  
21  import java.util.Collections;
22  import java.util.Comparator;
23  import java.util.List;
24  import java.util.Locale;
25  
26  import org.apache.maven.artifact.Artifact;
27  import org.apache.maven.artifact.versioning.VersionRange;
28  import org.apache.maven.doxia.sink.Sink;
29  import org.apache.maven.model.Plugin;
30  import org.apache.maven.model.PluginManagement;
31  import org.apache.maven.plugin.logging.Log;
32  import org.apache.maven.plugins.annotations.Mojo;
33  import org.apache.maven.plugins.annotations.Parameter;
34  import org.apache.maven.plugins.annotations.ResolutionScope;
35  import org.apache.maven.project.DefaultProjectBuildingRequest;
36  import org.apache.maven.project.MavenProject;
37  import org.apache.maven.project.ProjectBuilder;
38  import org.apache.maven.project.ProjectBuildingException;
39  import org.apache.maven.project.ProjectBuildingRequest;
40  import org.apache.maven.reporting.MavenReportException;
41  import org.apache.maven.repository.RepositorySystem;
42  import org.apache.maven.shared.artifact.filter.PatternExcludesArtifactFilter;
43  import org.codehaus.plexus.i18n.I18N;
44  import org.codehaus.plexus.util.StringUtils;
45  
46  /**
47   * Generates the Project Plugin Management report.
48   *
49   * @author Nick Stolwijk
50   * @since 2.1
51   */
52  @Mojo(name = "plugin-management", requiresDependencyResolution = ResolutionScope.TEST)
53  public class PluginManagementReport extends AbstractProjectInfoReport {
54  
55      /**
56       * Specify the excluded plugins. This can be a list of artifacts in the format
57       * groupId[:artifactId[:type[:version]]]. <br>
58       * Plugins matching any exclude will not be present in the report.
59       *
60       * @since 3.0.1
61       */
62      @Parameter
63      private List<String> pluginManagementExcludes = null;
64  
65      // ----------------------------------------------------------------------
66      // Public methods
67      // ----------------------------------------------------------------------
68  
69      @Override
70      public void executeReport(Locale locale) {
71          PluginManagementRenderer r = new PluginManagementRenderer(
72                  getLog(),
73                  getSink(),
74                  locale,
75                  getI18N(locale),
76                  project.getPluginManagement().getPlugins(),
77                  project,
78                  projectBuilder,
79                  repositorySystem,
80                  getSession().getProjectBuildingRequest(),
81                  pluginManagementExcludes);
82          r.render();
83      }
84  
85      /** {@inheritDoc} */
86      public String getOutputName() {
87          return "plugin-management";
88      }
89  
90      @Override
91      protected String getI18Nsection() {
92          return "plugin-management";
93      }
94  
95      @Override
96      public boolean canGenerateReport() throws MavenReportException {
97          boolean result = super.canGenerateReport();
98          if (result && skipEmptyReport) {
99              result = getProject().getPluginManagement() != null
100                     && !isEmpty(project.getPluginManagement().getPlugins());
101         }
102 
103         return result;
104     }
105 
106     // ----------------------------------------------------------------------
107     // Private
108     // ----------------------------------------------------------------------
109 
110     /**
111      * Internal renderer class
112      *
113      * @author Nick Stolwijk
114      */
115     protected static class PluginManagementRenderer extends AbstractProjectInfoRenderer {
116 
117         private final Log log;
118 
119         private final List<Plugin> pluginManagement;
120 
121         private final MavenProject project;
122 
123         private final ProjectBuilder projectBuilder;
124 
125         private final RepositorySystem repositorySystem;
126 
127         private final ProjectBuildingRequest buildingRequest;
128 
129         private final PatternExcludesArtifactFilter patternExcludesArtifactFilter;
130 
131         /**
132          * @param log {@link #log}
133          * @param sink {@link Sink}
134          * @param locale {@link Locale}
135          * @param i18n {@link I18N}
136          * @param plugins {@link Plugin}
137          * @param project {@link MavenProject}
138          * @param projectBuilder {@link ProjectBuilder}
139          * @param repositorySystem {@link RepositorySystem}
140          * @param buildingRequest {@link ProjectBuildingRequest}
141          * @param excludes the list of plugins to be excluded from the report
142          */
143         public PluginManagementRenderer(
144                 Log log,
145                 Sink sink,
146                 Locale locale,
147                 I18N i18n,
148                 List<Plugin> plugins,
149                 MavenProject project,
150                 ProjectBuilder projectBuilder,
151                 RepositorySystem repositorySystem,
152                 ProjectBuildingRequest buildingRequest,
153                 List<String> excludes) {
154             super(sink, i18n, locale);
155 
156             this.log = log;
157 
158             this.pluginManagement = plugins;
159 
160             this.project = project;
161 
162             this.projectBuilder = projectBuilder;
163 
164             this.repositorySystem = repositorySystem;
165 
166             this.buildingRequest = buildingRequest;
167 
168             this.patternExcludesArtifactFilter = new PatternExcludesArtifactFilter(excludes);
169         }
170 
171         @Override
172         protected String getI18Nsection() {
173             return "plugin-management";
174         }
175 
176         @Override
177         protected void renderBody() {
178             PluginManagement projectPluginManagement = project.getPluginManagement();
179 
180             if (projectPluginManagement == null
181                     || projectPluginManagement.getPlugins() == null
182                     || projectPluginManagement.getPlugins().isEmpty()) {
183                 startSection(getTitle());
184 
185                 paragraph(getI18nString("nolist"));
186 
187                 endSection();
188 
189                 return;
190             }
191 
192             // === Section: Project PluginManagement.
193             renderSectionPluginManagement();
194         }
195 
196         private void renderSectionPluginManagement() {
197             String[] tableHeader = getPluginTableHeader();
198 
199             startSection(getTitle());
200 
201             // can't use straight artifact comparison because we want optional last
202             Collections.sort(pluginManagement, getPluginComparator());
203 
204             startTable();
205             tableHeader(tableHeader);
206 
207             ProjectBuildingRequest buildRequest = new DefaultProjectBuildingRequest(buildingRequest);
208             buildRequest.setRemoteRepositories(project.getPluginArtifactRepositories());
209             buildRequest.setProcessPlugins(false);
210 
211             for (Plugin plugin : pluginManagement) {
212                 VersionRange versionRange;
213                 if (StringUtils.isEmpty(plugin.getVersion())) {
214                     versionRange = VersionRange.createFromVersion(Artifact.RELEASE_VERSION);
215                 } else {
216                     versionRange = VersionRange.createFromVersion(plugin.getVersion());
217                 }
218 
219                 Artifact pluginArtifact = repositorySystem.createProjectArtifact(
220                         plugin.getGroupId(), plugin.getArtifactId(), versionRange.toString());
221 
222                 if (patternExcludesArtifactFilter.include(pluginArtifact)) {
223                     try {
224                         MavenProject pluginProject = projectBuilder
225                                 .build(pluginArtifact, buildRequest)
226                                 .getProject();
227 
228                         tableRow(getPluginRow(
229                                 pluginProject.getGroupId(), pluginProject.getArtifactId(),
230                                 pluginProject.getVersion(), pluginProject.getUrl()));
231                     } catch (ProjectBuildingException e) {
232                         log.info("Could not build project for " + plugin.getArtifactId(), e);
233                         tableRow(getPluginRow(plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(), null));
234                     }
235                 } else {
236                     log.debug("Excluding plugin " + pluginArtifact.getId() + " from report");
237                 }
238             }
239             endTable();
240 
241             endSection();
242         }
243 
244         // ----------------------------------------------------------------------
245         // Private methods
246         // ----------------------------------------------------------------------
247 
248         private String[] getPluginTableHeader() {
249             // reused key...
250             String groupId = getI18nString("dependency-management", "column.groupId");
251             String artifactId = getI18nString("dependency-management", "column.artifactId");
252             String version = getI18nString("dependency-management", "column.version");
253             return new String[] {groupId, artifactId, version};
254         }
255 
256         private String[] getPluginRow(String groupId, String artifactId, String version, String link) {
257             artifactId = ProjectInfoReportUtils.getArtifactIdCell(artifactId, link);
258             return new String[] {groupId, artifactId, version};
259         }
260 
261         private Comparator<Plugin> getPluginComparator() {
262             return new Comparator<Plugin>() {
263                 /** {@inheritDoc} */
264                 public int compare(Plugin a1, Plugin a2) {
265                     int result = a1.getGroupId().compareTo(a2.getGroupId());
266                     if (result == 0) {
267                         result = a1.getArtifactId().compareTo(a2.getArtifactId());
268                     }
269                     return result;
270                 }
271             };
272         }
273     }
274 }