View Javadoc
1   package org.apache.maven.plugins.site.render;
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.util.ArrayList;
25  import java.util.Collections;
26  import java.util.List;
27  import java.util.Locale;
28  import java.util.Map;
29  import java.util.TreeMap;
30  
31  import org.apache.maven.doxia.siterenderer.DocumentRenderer;
32  import org.apache.maven.doxia.siterenderer.DoxiaDocumentRenderer;
33  import org.apache.maven.doxia.siterenderer.RendererException;
34  import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
35  import org.apache.maven.plugin.MojoExecutionException;
36  import org.apache.maven.plugin.MojoFailureException;
37  import org.apache.maven.plugins.annotations.Mojo;
38  import org.apache.maven.plugins.annotations.Parameter;
39  import org.apache.maven.plugins.annotations.ResolutionScope;
40  import org.apache.maven.project.MavenProject;
41  import org.apache.maven.reporting.MavenReport;
42  import org.apache.maven.reporting.exec.MavenReportExecution;
43  
44  /**
45   * Generates the site for a single project.
46   * <p>
47   * Note that links between module sites in a multi module build will <b>not</b>
48   * work, since local build directory structure doesn't match deployed site.
49   * </p>
50   *
51   * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
52   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
53   * @version $Id: SiteMojo.html 914946 2014-07-03 23:00:36Z hboutemy $
54   */
55  @Mojo( name = "site", requiresDependencyResolution = ResolutionScope.TEST, requiresReports = true )
56  public class SiteMojo
57      extends AbstractSiteRenderingMojo
58  {
59      /**
60       * Directory where the project sites and report distributions will be generated.
61       */
62      @Parameter( property = "siteOutputDirectory", defaultValue = "${project.reporting.outputDirectory}" )
63      protected File outputDirectory;
64  
65      /**
66       * Convenience parameter that allows you to disable report generation.
67       */
68      @Parameter( property = "generateReports", defaultValue = "true" )
69      private boolean generateReports;
70  
71      /**
72       * Generate a sitemap. The result will be a "sitemap.html" file at the site root.
73       *
74       * @since 2.1
75       */
76      @Parameter( property = "generateSitemap", defaultValue = "false" )
77      private boolean generateSitemap;
78  
79      /**
80       * Whether to validate xml input documents.
81       * If set to true, <strong>all</strong> input documents in xml format
82       * (in particular xdoc and fml) will be validated and any error will
83       * lead to a build failure.
84       *
85       * @since 2.1.1
86       */
87      @Parameter( property = "validate", defaultValue = "false" )
88      private boolean validate;
89  
90      /**
91       * Set this to 'true' to skip site generation and staging.
92       *
93       * @since 3.0
94       */
95      @Parameter( property = "maven.site.skip", defaultValue = "false" )
96      private boolean skip;
97  
98      /**
99       * {@inheritDoc}
100      *
101      * Generate the project site
102      * <p/>
103      * throws MojoExecutionException if any
104      *
105      * @see org.apache.maven.plugin.Mojo#execute()
106      */
107     public void execute()
108         throws MojoExecutionException, MojoFailureException
109     {
110         if ( skip )
111         {
112             getLog().info( "maven.site.skip = true: Skipping site generation" );
113             return;
114         }
115 
116         if ( getLog().isDebugEnabled() )
117         {
118             getLog().debug( "executing Site Mojo" );
119         }
120 
121         List<MavenReportExecution> reports;
122         if ( generateReports )
123         {
124             reports = getReports();
125         }
126         else
127         {
128             reports = Collections.emptyList();
129         }
130 
131         try
132         {
133             List<Locale> localesList = siteTool.getAvailableLocales( locales );
134 
135             // Default is first in the list
136             Locale defaultLocale = localesList.get( 0 );
137             Locale.setDefault( defaultLocale );
138 
139             for ( Locale locale : localesList )
140             {
141                 renderLocale( locale, reports );
142             }
143         }
144         catch ( RendererException e )
145         {
146             throw new MojoExecutionException( e.getMessage(), e );
147         }
148         catch ( IOException e )
149         {
150             throw new MojoExecutionException( "Error during site generation", e );
151         }
152     }
153 
154     private void renderLocale( Locale locale, List<MavenReportExecution> reports )
155         throws IOException, RendererException, MojoFailureException, MojoExecutionException
156     {
157         SiteRenderingContext context = createSiteRenderingContext( locale );
158 
159         context.setInputEncoding( getInputEncoding() );
160         context.setOutputEncoding( getOutputEncoding() );
161         context.setValidate( validate );
162         if ( validate )
163         {
164             getLog().info( "Validation is switched on, xml input documents will be validated!" );
165         }
166 
167         File outputDir = getOutputDirectory( locale );
168 
169         Map<String, DocumentRenderer> documents = locateDocuments( context, reports, locale );
170 
171         // 1. render Doxia documents first
172         List<DocumentRenderer> reportDocuments = renderDoxiaDocuments( documents, context, outputDir, false );
173 
174         // 2. then reports
175         // For external reports
176         for ( MavenReportExecution mavenReportExecution : reports )
177         {
178             MavenReport report = mavenReportExecution.getMavenReport();
179             report.setReportOutputDirectory( outputDir );
180         }
181 
182         siteRenderer.render( reportDocuments, context, outputDir );
183 
184         if ( generateSitemap )
185         {
186             getLog().info( "Generating Sitemap." );
187 
188             new SiteMap( getOutputEncoding(), i18n )
189                     .generate( context.getDecoration(), generatedSiteDirectory, locale );
190         }
191 
192         // 3. Generated docs must be done afterwards as they are often generated by reports
193         context.getSiteDirectories().clear();
194         context.addSiteDirectory( generatedSiteDirectory );
195 
196         Map<String, DocumentRenderer> generatedDocuments = siteRenderer.locateDocumentFiles( context );
197 
198         renderDoxiaDocuments( generatedDocuments, context, outputDir, true );
199     }
200 
201     /**
202      * Renders Doxia documents, but not reports.
203      * @param documents a collection of documents
204      * @return the sublist of documents that are not Doxia parsed
205      */
206     private List<DocumentRenderer> renderDoxiaDocuments( Map<String, DocumentRenderer> documents,
207                                                          SiteRenderingContext context, File outputDir, boolean generated )
208         throws RendererException, IOException
209     {
210         Map<String, DocumentRenderer> doxiaDocuments = new TreeMap<String, DocumentRenderer>();
211         List<DocumentRenderer> nonDoxiaDocuments = new ArrayList<DocumentRenderer>();
212 
213         Map<String, Integer> counts = new TreeMap<String, Integer>();
214 
215         for ( Map.Entry<String, DocumentRenderer> entry: documents.entrySet() )
216         {
217             DocumentRenderer doc = entry.getValue();
218 
219             if ( doc instanceof DoxiaDocumentRenderer )
220             {
221                 doxiaDocuments.put( entry.getKey(), doc );
222 
223                 DoxiaDocumentRenderer doxia = (DoxiaDocumentRenderer) doc;
224 
225                 // count documents per parserId
226                 String parserId = doxia.getRenderingContext().getParserId();
227                 Integer count = counts.get( parserId );
228                 if ( count == null )
229                 {
230                     count = 1;
231                 }
232                 else
233                 {
234                     count++;
235                 }
236                 counts.put( parserId, count );
237             }
238             else
239             {
240                 nonDoxiaDocuments.add( doc );
241             }
242         }
243 
244         if ( doxiaDocuments.size() > 0 )
245         {
246             StringBuilder sb = new StringBuilder( 15 * counts.size() );
247             for ( Map.Entry<String, Integer> entry: counts.entrySet() )
248             {
249                 if ( sb.length() > 0 )
250                 {
251                     sb.append( ", " );
252                 }
253                 sb.append( entry.getValue() );
254                 sb.append( ' ' );
255                 sb.append( entry.getKey() );
256             }
257 
258             getLog().info( "Rendering " + doxiaDocuments.size() + ( generated ? " generated" : "" )
259                                + " Doxia document" + ( doxiaDocuments.size() > 1 ? "s" : "" ) + ": " + sb.toString() );
260 
261             siteRenderer.render( doxiaDocuments.values(), context, outputDir );
262         }
263 
264         return nonDoxiaDocuments;
265     }
266 
267     private File getOutputDirectory( Locale locale )
268     {
269         File file;
270         if ( locale.getLanguage().equals( Locale.getDefault().getLanguage() ) )
271         {
272             file = outputDirectory;
273         }
274         else
275         {
276             file = new File( outputDirectory, locale.getLanguage() );
277         }
278 
279         // Safety
280         if ( !file.exists() )
281         {
282             file.mkdirs();
283         }
284 
285         return file;
286     }
287 
288     public MavenProject getProject()
289     {
290         return project;
291     }
292 }