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.io.File;
23  import java.io.IOException;
24  import java.net.MalformedURLException;
25  import java.util.List;
26  import java.util.Locale;
27  
28  import org.apache.maven.artifact.repository.ArtifactRepository;
29  import org.apache.maven.doxia.sink.Sink;
30  import org.apache.maven.doxia.tools.SiteTool;
31  import org.apache.maven.model.DistributionManagement;
32  import org.apache.maven.model.Site;
33  import org.apache.maven.plugin.logging.Log;
34  import org.apache.maven.plugins.annotations.Mojo;
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.codehaus.plexus.i18n.I18N;
41  
42  /**
43   * Generates the Project Modules report.
44   *
45   * @author ltheussl
46   * @since 2.2
47   */
48  @Mojo( name = "modules" )
49  public class ModulesReport
50      extends AbstractProjectInfoReport
51  {
52      // ----------------------------------------------------------------------
53      // Public methods
54      // ----------------------------------------------------------------------
55  
56      @Override
57      public boolean canGenerateReport()
58      {
59          boolean result = super.canGenerateReport();
60          if ( result && skipEmptyReport )
61          {
62              result = !isEmpty( getProject().getModel().getModules() );
63          }
64  
65          return result;
66      }
67  
68      @Override
69      public void executeReport( Locale locale )
70      {
71          new ModulesRenderer( getSink(), getProject(), getReactorProjects(), projectBuilder, localRepository,
72                               getI18N( locale ), locale, getLog(), siteTool ).render();
73      }
74  
75      /** {@inheritDoc} */
76      public String getOutputName()
77      {
78          return "modules";
79      }
80  
81      @Override
82      protected String getI18Nsection()
83      {
84          return "modules";
85      }
86  
87      // ----------------------------------------------------------------------
88      // Private
89      // ----------------------------------------------------------------------
90  
91      /**
92       * Internal renderer class
93       */
94      static class ModulesRenderer
95          extends AbstractProjectInfoRenderer
96      {
97  
98          protected final Log log;
99  
100         protected MavenProject project;
101 
102         protected List<MavenProject> reactorProjects;
103 
104         protected ProjectBuilder projectBuilder;
105 
106         protected ArtifactRepository localRepository;
107 
108         protected SiteTool siteTool;
109 
110         ModulesRenderer( Sink sink, MavenProject project, List<MavenProject> reactorProjects,
111                          ProjectBuilder projectBuilder, ArtifactRepository localRepository, I18N i18n,
112                          Locale locale, Log log, SiteTool siteTool )
113         {
114             super( sink, i18n, locale );
115 
116             this.project = project;
117             this.reactorProjects = reactorProjects;
118             this.projectBuilder = projectBuilder;
119             this.localRepository = localRepository;
120             this.siteTool = siteTool;
121             this.log = log;
122         }
123 
124         @Override
125         protected String getI18Nsection()
126         {
127             return "modules";
128         }
129 
130         @Override
131         public void renderBody()
132         {
133             List<String> modules = project.getModel().getModules();
134 
135             if ( modules == null || modules.isEmpty() )
136             {
137                 startSection( getTitle() );
138 
139                 paragraph( getI18nString( "nolist" ) );
140 
141                 endSection();
142 
143                 return;
144             }
145 
146             startSection( getTitle() );
147 
148             paragraph( getI18nString( "intro" ) );
149 
150             startTable();
151 
152             String name = getI18nString( "header.name" );
153             String description = getI18nString( "header.description" );
154             tableHeader( new String[] { name, description } );
155 
156             final String baseUrl = getDistMgmntSiteUrl( project );
157 
158             ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest();
159             buildingRequest.setLocalRepository( localRepository );
160             
161             for ( String module : modules )
162             {
163                 MavenProject moduleProject = getModuleFromReactor( project, reactorProjects, module );
164 
165                 if ( moduleProject == null )
166                 {
167                     log.warn( "Module " + module + " not found in reactor: loading locally" );
168 
169                     File f = new File( project.getBasedir(), module + "/pom.xml" );
170                     if ( f.exists() )
171                     {
172                         try
173                         {
174                             moduleProject = projectBuilder.build( f, buildingRequest ).getProject();
175                         }
176                         catch ( ProjectBuildingException e )
177                         {
178                             throw new IllegalStateException( "Unable to read local module POM", e );
179                         }
180                     }
181                     else
182                     {
183                         moduleProject = new MavenProject();
184                         moduleProject.setName( module );
185                         moduleProject.setDistributionManagement( new DistributionManagement() );
186                         moduleProject.getDistributionManagement().setSite( new Site() );
187                         moduleProject.getDistributionManagement().getSite().setUrl( module );
188                     }
189                 }
190                 final String moduleName =
191                     ( moduleProject.getName() == null ) ? moduleProject.getArtifactId() : moduleProject.getName();
192                 final String moduleHref =
193                     getRelativeLink( baseUrl, getDistMgmntSiteUrl( moduleProject ), moduleProject.getArtifactId() );
194 
195                 tableRow( new String[] { linkedName( moduleName, moduleHref ), moduleProject.getDescription() } );
196             }
197 
198             endTable();
199 
200             endSection();
201         }
202 
203         private MavenProject getModuleFromReactor( MavenProject project, List<MavenProject> reactorProjects,
204                                                    String module )
205         {
206             // Mainly case of unit test
207             if ( reactorProjects == null )
208             {
209                 return null;
210             }
211             try
212             {
213                 File moduleBasedir = new File( project.getBasedir(), module ).getCanonicalFile();
214 
215                 for ( MavenProject reactorProject : reactorProjects )
216                 {
217                     if ( moduleBasedir.equals( reactorProject.getBasedir() ) )
218                     {
219                         return reactorProject;
220                     }
221                 }
222             }
223             catch ( IOException e )
224             {
225                 log.error( "Error while populating modules menu: " + e.getMessage(), e );
226             }
227             // module not found in reactor
228             return null;
229         }
230 
231         /**
232          * Return distributionManagement.site.url if defined, null otherwise.
233          *
234          * @param project not null
235          * @return could be null
236          */
237         private static String getDistMgmntSiteUrl( MavenProject project )
238         {
239             return getDistMgmntSiteUrl( project.getDistributionManagement() );
240         }
241 
242         private static String getDistMgmntSiteUrl( DistributionManagement distMgmnt )
243         {
244             if ( distMgmnt != null && distMgmnt.getSite() != null && distMgmnt.getSite().getUrl() != null )
245             {
246                 return urlEncode( distMgmnt.getSite().getUrl() );
247             }
248 
249             return null;
250         }
251 
252         private static String urlEncode( final String url )
253         {
254             if ( url == null )
255             {
256                 return null;
257             }
258 
259             try
260             {
261                 return new File( url ).toURI().toURL().toExternalForm();
262             }
263             catch ( MalformedURLException ex )
264             {
265                 return url; // this will then throw somewhere else
266             }
267         }
268 
269         // adapted from DefaultSiteTool#appendMenuItem
270         private String getRelativeLink( String baseUrl, String href, String defaultHref )
271         {
272             String selectedHref = href;
273 
274             if ( selectedHref == null )
275             {
276                 selectedHref = defaultHref;
277             }
278 
279             if ( baseUrl != null )
280             {
281                 selectedHref = siteTool.getRelativePath( selectedHref, baseUrl );
282             }
283 
284             if ( selectedHref.endsWith( "/" ) )
285             {
286                 selectedHref = selectedHref.concat( "index.html" );
287             }
288             else
289             {
290                 selectedHref = selectedHref.concat( "/index.html" );
291             }
292 
293             return selectedHref;
294         }
295 
296         private String linkedName( String name, String link )
297         {
298             return "{" + name + ", ./" + link + "}";
299         }
300     }
301 }