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