View Javadoc
1   package org.apache.maven.report.projectinfo;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.Comparator;
25  import java.util.List;
26  import java.util.Locale;
27  
28  import org.apache.maven.artifact.Artifact;
29  import org.apache.maven.artifact.factory.ArtifactFactory;
30  import org.apache.maven.artifact.repository.ArtifactRepository;
31  import org.apache.maven.artifact.versioning.VersionRange;
32  import org.apache.maven.doxia.sink.Sink;
33  import org.apache.maven.model.Plugin;
34  import org.apache.maven.model.ReportPlugin;
35  import org.apache.maven.plugin.logging.Log;
36  import org.apache.maven.plugins.annotations.Component;
37  import org.apache.maven.plugins.annotations.Mojo;
38  import org.apache.maven.plugins.annotations.ResolutionScope;
39  import org.apache.maven.project.MavenProject;
40  import org.apache.maven.project.MavenProjectBuilder;
41  import org.apache.maven.project.ProjectBuildingException;
42  import org.codehaus.plexus.i18n.I18N;
43  import org.codehaus.plexus.util.StringUtils;
44  
45  /**
46   * Generates the Project Plugins report.
47   *
48   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
49   * @version $Id: PluginsReport.html 964486 2015-09-05 21:32:50Z hboutemy $
50   * @since 2.1
51   */
52  @Mojo( name = "plugins", requiresDependencyResolution = ResolutionScope.TEST )
53  public class PluginsReport
54      extends AbstractProjectInfoReport
55  {
56      // ----------------------------------------------------------------------
57      // Mojo components
58      // ----------------------------------------------------------------------
59  
60      /**
61       * Maven Project Builder component.
62       */
63      @Component
64      private MavenProjectBuilder mavenProjectBuilder;
65  
66      /**
67       * Maven Artifact Factory component.
68       */
69      @Component
70      private ArtifactFactory artifactFactory;
71  
72      // ----------------------------------------------------------------------
73      // Public methods
74      // ----------------------------------------------------------------------
75  
76      @Override
77      public boolean canGenerateReport()
78      {
79          boolean result = super.canGenerateReport();
80          if ( result && skipEmptyReport )
81          {
82              result = !isEmpty( getProject().getBuildPlugins() ) || !isEmpty( getProject().getReportPlugins() );
83          }
84  
85          return result;
86      }
87  
88      @Override
89      public void executeReport( Locale locale )
90      {
91          @SuppressWarnings( "unchecked" )
92          PluginsRenderer r =
93              new PluginsRenderer( getLog(), getSink(), locale, getI18N( locale ), project.getBuildPlugins(),
94                                   project.getReportPlugins(), project, mavenProjectBuilder, artifactFactory,
95                                   localRepository );
96          r.render();
97      }
98  
99      /** {@inheritDoc} */
100     public String getOutputName()
101     {
102         return "plugins";
103     }
104 
105     @Override
106     protected String getI18Nsection()
107     {
108         return "plugins";
109     }
110 
111     // ----------------------------------------------------------------------
112     // Private
113     // ----------------------------------------------------------------------
114 
115     /**
116      * Internal renderer class
117      */
118     protected static class PluginsRenderer
119         extends AbstractProjectInfoRenderer
120     {
121         private final Log log;
122 
123         private final List<Plugin> plugins;
124 
125         private final List<ReportPlugin> reports;
126 
127         private final MavenProject project;
128 
129         private final MavenProjectBuilder mavenProjectBuilder;
130 
131         private final ArtifactFactory artifactFactory;
132 
133         private final ArtifactRepository localRepository;
134 
135         /**
136          * @param log {@link #log}
137          * @param sink {@link Sink}
138          * @param locale {@link Locale}
139          * @param i18n {@link I18N}
140          * @param plugins {@link Artifact}
141          * @param reports {@link Artifact}
142          * @param project {@link MavenProject}
143          * @param mavenProjectBuilder {@link MavenProjectBuilder}
144          * @param artifactFactory {@link ArtifactFactory}
145          * @param localRepository {@link ArtifactRepository}
146          *
147          */
148         public PluginsRenderer( Log log, Sink sink, Locale locale, I18N i18n, List<Plugin> plugins,
149                                 List<ReportPlugin> reports, MavenProject project,
150                                 MavenProjectBuilder mavenProjectBuilder, ArtifactFactory artifactFactory,
151                                 ArtifactRepository localRepository )
152         {
153             super( sink, i18n, locale );
154 
155             this.log = log;
156 
157             this.plugins = new ArrayList<Plugin>( plugins );
158 
159             this.reports = new ArrayList<ReportPlugin>( reports );
160 
161             this.project = project;
162 
163             this.mavenProjectBuilder = mavenProjectBuilder;
164 
165             this.artifactFactory = artifactFactory;
166 
167             this.localRepository = localRepository;
168         }
169 
170         @Override
171         protected String getI18Nsection()
172         {
173             return "plugins";
174         }
175 
176         @Override
177         public void renderBody()
178         {
179             // === Section: Project Plugins.
180             renderSectionPlugins( true );
181 
182             // === Section: Project Reports.
183             renderSectionPlugins( false );
184         }
185 
186         /**
187          * @param isPlugins <code>true</code> to use <code>plugins</code> variable, <code>false</code> to use
188          * <code>reports</code> variable.
189          */
190         private void renderSectionPlugins( boolean isPlugins )
191         {
192             List<GAV> list = isPlugins ? GAV.pluginsToGAV( plugins ) : GAV.reportPluginsToGAV( reports, project );
193             String[] tableHeader = getPluginTableHeader();
194 
195             startSection( getI18nString( isPlugins ? "title" : "report.title" ) );
196 
197             if ( list == null || list.isEmpty() )
198             {
199 
200                 paragraph( getI18nString( isPlugins ? "nolist" : "report.nolist" ) ) ;
201                 endSection();
202                 return;
203             }
204 
205             Collections.sort( list, getPluginComparator() );
206 
207             startTable();
208             tableHeader( tableHeader );
209 
210             for ( GAV plugin : list )
211             {
212                 VersionRange versionRange = VersionRange.createFromVersion( plugin.getVersion() );
213 
214                 Artifact pluginArtifact =
215                     artifactFactory.createParentArtifact( plugin.getGroupId(), plugin.getArtifactId(),
216                                                           versionRange.toString() );
217                 @SuppressWarnings( "unchecked" )
218                 List<ArtifactRepository> artifactRepositories = project.getPluginArtifactRepositories();
219                 if ( artifactRepositories == null )
220                 {
221                     artifactRepositories = new ArrayList<ArtifactRepository>();
222                 }
223                 try
224                 {
225                     MavenProject pluginProject = mavenProjectBuilder.buildFromRepository( pluginArtifact,
226                                                                                           artifactRepositories,
227                                                                                           localRepository );
228                     tableRow( getPluginRow( pluginProject.getGroupId(), pluginProject.getArtifactId(), pluginProject
229                                             .getVersion(), pluginProject.getUrl() ) );
230                 }
231                 catch ( ProjectBuildingException e )
232                 {
233                     log.info( "Could not build project for " + plugin.getArtifactId() + ": " + e.getMessage(), e );
234                     tableRow( getPluginRow( plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(),
235                                             null ) );
236                 }
237 
238             }
239             endTable();
240 
241             endSection();
242         }
243 
244         // ----------------------------------------------------------------------
245         // Private methods
246         // ----------------------------------------------------------------------
247 
248         private String[] getPluginTableHeader()
249         {
250             // reused key...
251             String groupId = getI18nString( "dependencyManagement", "column.groupId" );
252             String artifactId = getI18nString( "dependencyManagement", "column.artifactId" );
253             String version = getI18nString( "dependencyManagement", "column.version" );
254             return new String[] { groupId, artifactId, version };
255         }
256 
257         private String[] getPluginRow( String groupId, String artifactId, String version, String link )
258         {
259             artifactId = ProjectInfoReportUtils.getArtifactIdCell( artifactId, link );
260             return new String[] { groupId, artifactId, version };
261         }
262 
263         private static class GAV
264         {
265             private final String groupId;
266             private final String artifactId;
267             private final String version;
268 
269             private GAV( Plugin plugin )
270             {
271                 groupId = plugin.getGroupId();
272                 artifactId = plugin.getArtifactId();
273                 version = StringUtils.isEmpty( plugin.getVersion() ) ? Artifact.RELEASE_VERSION : plugin.getVersion();
274             }
275 
276             private GAV( ReportPlugin reportPlugin, MavenProject project )
277             {
278                 groupId = reportPlugin.getGroupId();
279                 artifactId = reportPlugin.getArtifactId();
280                 version = resolveReportPluginVersion( reportPlugin, project );
281             }
282 
283             public String getGroupId()
284             {
285                 return groupId;
286             }
287 
288             public String getArtifactId()
289             {
290                 return artifactId;
291             }
292 
293             public String getVersion()
294             {
295                 return version;
296             }
297 
298             public static List<GAV> pluginsToGAV( List<Plugin> plugins )
299             {
300                 List<GAV> result = new ArrayList<GAV>( plugins.size() );
301                 for ( Plugin plugin : plugins )
302                 {
303                     result.add( new GAV( plugin ) );
304                 }
305                 return result;
306             }
307 
308             public static List<GAV> reportPluginsToGAV( List<ReportPlugin> reportPlugins, MavenProject project )
309             {
310                 List<GAV> result = new ArrayList<GAV>( reportPlugins.size() );
311                 for ( ReportPlugin reportPlugin : reportPlugins )
312                 {
313                     result.add( new GAV( reportPlugin, project ) );
314                 }
315                 return result;
316             }
317         }
318 
319         private Comparator<GAV> getPluginComparator()
320         {
321             return new Comparator<GAV>()
322             {
323                 /** {@inheritDoc} */
324                 public int compare( GAV a1, GAV a2 )
325                 {
326                     int result = a1.groupId.compareTo( a2.groupId );
327                     if ( result == 0 )
328                     {
329                         result = a1.artifactId.compareTo( a2.artifactId );
330                     }
331                     return result;
332                 }
333             };
334         }
335 
336         /**
337          * Resolve report plugin version. Steps to find a plugin version stop after each step if a non <code>null</code>
338          * value has been found:
339          * <ol>
340          * <li>use the one defined in the reportPlugin configuration,</li>
341          * <li>search similar (same groupId and artifactId) mojo in the build/plugins section of the pom,</li>
342          * <li>search similar (same groupId and artifactId) mojo in the build/pluginManagement section of the pom,</li>
343          * <li>default value is RELEASE.</li>
344          * </ol>
345          * 
346          * @param reportPlugin the report plugin to resolve the version
347          * @param project the current project
348          * @return the report plugin version
349          */
350         protected static String resolveReportPluginVersion( ReportPlugin reportPlugin, MavenProject project )
351         {
352             // look for version defined in the reportPlugin configuration
353             if ( reportPlugin.getVersion() != null )
354             {
355                 return reportPlugin.getVersion();
356             }
357 
358             // search in the build section
359             if ( project.getBuild() != null )
360             {
361                 Plugin plugin = find( reportPlugin, project.getBuild().getPlugins() );
362 
363                 if ( plugin != null && plugin.getVersion() != null )
364                 {
365                     return plugin.getVersion();
366                 }
367             }
368 
369             // search in pluginManagement section
370             if ( project.getBuild() != null && project.getBuild().getPluginManagement() != null )
371             {
372                 Plugin plugin = find( reportPlugin, project.getBuild().getPluginManagement().getPlugins() );
373 
374                 if ( plugin != null && plugin.getVersion() != null )
375                 {
376                     return plugin.getVersion();
377                 }
378             }
379 
380             // empty version
381             return Artifact.RELEASE_VERSION;
382         }
383 
384         /**
385          * Search similar (same groupId and artifactId) plugin as a given report plugin.
386          * 
387          * @param reportPlugin the report plugin to search for a similar plugin
388          * @param plugins the candidate plugins
389          * @return the first similar plugin
390          */
391         private static Plugin find( ReportPlugin reportPlugin, List<Plugin> plugins )
392         {
393             if ( plugins == null )
394             {
395                 return null;
396             }
397             for ( Plugin plugin : plugins )
398             {
399                 if ( StringUtils.equals( plugin.getArtifactId(), reportPlugin.getArtifactId() )
400                     && StringUtils.equals( plugin.getGroupId(), reportPlugin.getGroupId() ) )
401                 {
402                     return plugin;
403                 }
404             }
405             return null;
406         }
407     }
408 }