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