1 package org.apache.maven.plugins.site.render;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.LinkedHashMap;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.Map;
32
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.doxia.site.decoration.DecorationModel;
35 import org.apache.maven.doxia.site.decoration.Menu;
36 import org.apache.maven.doxia.site.decoration.MenuItem;
37 import org.apache.maven.doxia.siterenderer.DocumentRenderer;
38 import org.apache.maven.doxia.siterenderer.Renderer;
39 import org.apache.maven.doxia.siterenderer.RendererException;
40 import org.apache.maven.doxia.siterenderer.RenderingContext;
41 import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
42 import org.apache.maven.doxia.tools.SiteToolException;
43 import org.apache.maven.execution.MavenSession;
44 import org.apache.maven.model.ReportPlugin;
45 import org.apache.maven.model.Reporting;
46 import org.apache.maven.plugin.MojoExecutionException;
47 import org.apache.maven.plugin.MojoFailureException;
48 import org.apache.maven.plugin.descriptor.PluginDescriptor;
49 import org.apache.maven.plugins.annotations.Component;
50 import org.apache.maven.plugins.annotations.Parameter;
51 import org.apache.maven.plugins.site.descriptor.AbstractSiteDescriptorMojo;
52 import org.apache.maven.reporting.MavenReport;
53 import org.apache.maven.reporting.exec.MavenReportExecution;
54 import org.apache.maven.reporting.exec.MavenReportExecutor;
55 import org.apache.maven.reporting.exec.MavenReportExecutorRequest;
56 import org.codehaus.plexus.PlexusConstants;
57 import org.codehaus.plexus.PlexusContainer;
58 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
59 import org.codehaus.plexus.context.Context;
60 import org.codehaus.plexus.context.ContextException;
61 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
62 import org.codehaus.plexus.util.ReaderFactory;
63 import org.codehaus.plexus.util.StringUtils;
64
65 import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
66
67
68
69
70
71
72
73 public abstract class AbstractSiteRenderingMojo
74 extends AbstractSiteDescriptorMojo implements Contextualizable
75 {
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 @Parameter
93 private Map<String, String> moduleExcludes;
94
95
96
97
98
99
100
101 @Parameter( property = "templateFile" )
102 private File templateFile;
103
104
105
106
107
108 @Parameter
109 private Map<String, Object> attributes;
110
111
112
113
114 @Component
115 protected Renderer siteRenderer;
116
117
118
119
120 @Parameter( defaultValue = "${reports}", required = true, readonly = true )
121 protected List<MavenReport> reports;
122
123
124
125
126
127
128 @Parameter( defaultValue = "${basedir}/xdocs" )
129 private File xdocDirectory;
130
131
132
133
134
135
136
137
138
139
140
141 @Parameter( alias = "workingDirectory", defaultValue = "${project.build.directory}/generated-site" )
142 protected File generatedSiteDirectory;
143
144
145
146
147 @Parameter( defaultValue = "${session}", readonly = true, required = true )
148 protected MavenSession mavenSession;
149
150
151
152
153
154
155
156 @Parameter( defaultValue = "${project.reporting}", readonly = true )
157 private Reporting reporting;
158
159 private PlexusContainer container;
160
161
162
163
164
165
166 @Parameter( property = "generateProjectInfo", defaultValue = "true" )
167 private boolean generateProjectInfo;
168
169
170
171
172
173
174 @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}" )
175 private String inputEncoding;
176
177
178
179
180
181
182 @Parameter( property = "outputEncoding", defaultValue = "${project.reporting.outputEncoding}" )
183 private String outputEncoding;
184
185
186
187
188
189
190 protected String getInputEncoding()
191 {
192 return ( StringUtils.isEmpty( inputEncoding ) ) ? ReaderFactory.FILE_ENCODING : inputEncoding;
193 }
194
195
196
197
198
199
200 protected String getOutputEncoding()
201 {
202 return ( outputEncoding == null ) ? ReaderFactory.UTF_8 : outputEncoding;
203 }
204
205
206
207
208
209
210
211 @Parameter
212 private boolean saveProcessedContent;
213
214
215 public void contextualize( Context context )
216 throws ContextException
217 {
218 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
219 }
220
221 protected void checkInputEncoding()
222 {
223 if ( StringUtils.isEmpty( inputEncoding ) )
224 {
225 getLog().warn( "Input file encoding has not been set, using platform encoding "
226 + ReaderFactory.FILE_ENCODING + ", i.e. build is platform dependent!" );
227 }
228 }
229
230 protected List<MavenReportExecution> getReports()
231 throws MojoExecutionException
232 {
233 List<MavenReportExecution> allReports;
234
235 if ( isMaven3OrMore() )
236 {
237
238 MavenReportExecutorRequest mavenReportExecutorRequest = new MavenReportExecutorRequest();
239 mavenReportExecutorRequest.setLocalRepository( localRepository );
240 mavenReportExecutorRequest.setMavenSession( mavenSession );
241 mavenReportExecutorRequest.setProject( project );
242 mavenReportExecutorRequest.setReportPlugins( getReportingPlugins() );
243
244 MavenReportExecutor mavenReportExecutor;
245 try
246 {
247 mavenReportExecutor = (MavenReportExecutor) container.lookup( MavenReportExecutor.class.getName() );
248 }
249 catch ( ComponentLookupException e )
250 {
251 throw new MojoExecutionException( "could not get MavenReportExecutor component", e );
252 }
253
254 allReports = mavenReportExecutor.buildMavenReports( mavenReportExecutorRequest );
255 }
256 else
257 {
258
259 allReports = new ArrayList<MavenReportExecution>( reports.size() );
260 for ( MavenReport report : reports )
261 {
262 allReports.add( new MavenReportExecution( report ) );
263 }
264 }
265
266
267 List<MavenReportExecution> reportExecutions = new ArrayList<MavenReportExecution>( allReports.size() );
268 for ( MavenReportExecution exec : allReports )
269 {
270 if ( exec.canGenerateReport() )
271 {
272 reportExecutions.add( exec );
273 }
274 }
275
276 return reportExecutions;
277 }
278
279
280
281
282
283
284
285
286 private ReportPlugin[] getReportingPlugins()
287 {
288 List<ReportPlugin> reportingPlugins = reporting.getPlugins();
289
290
291 boolean hasMavenProjectInfoReportsPlugin = false;
292 for ( ReportPlugin plugin : reportingPlugins )
293 {
294 if ( "org.apache.maven.plugins".equals( plugin.getGroupId() )
295 && "maven-project-info-reports-plugin".equals( plugin.getArtifactId() ) )
296 {
297 hasMavenProjectInfoReportsPlugin = true;
298 break;
299 }
300 }
301
302 if ( !reporting.isExcludeDefaults() && !hasMavenProjectInfoReportsPlugin )
303 {
304 ReportPlugin mpir = new ReportPlugin();
305 mpir.setArtifactId( "maven-project-info-reports-plugin" );
306 reportingPlugins.add( mpir );
307 }
308 return reportingPlugins.toArray( new ReportPlugin[reportingPlugins.size()] );
309 }
310
311 protected SiteRenderingContext createSiteRenderingContext( Locale locale )
312 throws MojoExecutionException, IOException, MojoFailureException
313 {
314 DecorationModel decorationModel = prepareDecorationModel( locale );
315 if ( attributes == null )
316 {
317 attributes = new HashMap<String, Object>();
318 }
319
320 if ( attributes.get( "project" ) == null )
321 {
322 attributes.put( "project", project );
323 }
324
325 if ( attributes.get( "inputEncoding" ) == null )
326 {
327 attributes.put( "inputEncoding", getInputEncoding() );
328 }
329
330 if ( attributes.get( "outputEncoding" ) == null )
331 {
332 attributes.put( "outputEncoding", getOutputEncoding() );
333 }
334
335
336 for ( Map.Entry<Object, Object> entry : project.getProperties().entrySet() )
337 {
338 attributes.put( (String) entry.getKey(), entry.getValue() );
339 }
340
341 SiteRenderingContext context;
342 if ( templateFile != null )
343 {
344 getLog().info( buffer().a( "Rendering content with " ).strong( templateFile
345 + " template file" ).a( '.' ).toString() );
346
347 if ( !templateFile.exists() )
348 {
349 throw new MojoFailureException( "Template file '" + templateFile + "' does not exist" );
350 }
351 context = siteRenderer.createContextForTemplate( templateFile, attributes, decorationModel,
352 project.getName(), locale );
353 }
354 else
355 {
356 try
357 {
358 Artifact skinArtifact =
359 siteTool.getSkinArtifactFromRepository( localRepository, repositories, decorationModel );
360
361 getLog().info( buffer().a( "Rendering content with " ).strong( skinArtifact.getId()
362 + " skin" ).a( '.' ).toString() );
363
364 context = siteRenderer.createContextForSkin( skinArtifact, attributes, decorationModel,
365 project.getName(), locale );
366 }
367 catch ( SiteToolException e )
368 {
369 throw new MojoExecutionException( "SiteToolException while preparing skin: " + e.getMessage(), e );
370 }
371 catch ( RendererException e )
372 {
373 throw new MojoExecutionException( "RendererException while preparing context for skin: "
374 + e.getMessage(), e );
375 }
376 }
377
378
379 context.setRootDirectory( project.getBasedir() );
380 if ( !locale.getLanguage().equals( Locale.getDefault().getLanguage() ) )
381 {
382 context.addSiteDirectory( new File( siteDirectory, locale.getLanguage() ) );
383 context.addModuleDirectory( new File( xdocDirectory, locale.getLanguage() ), "xdoc" );
384 context.addModuleDirectory( new File( xdocDirectory, locale.getLanguage() ), "fml" );
385 }
386 else
387 {
388 context.addSiteDirectory( siteDirectory );
389 context.addModuleDirectory( xdocDirectory, "xdoc" );
390 context.addModuleDirectory( xdocDirectory, "fml" );
391 }
392
393 if ( moduleExcludes != null )
394 {
395 context.setModuleExcludes( moduleExcludes );
396 }
397
398 if ( saveProcessedContent )
399 {
400 context.setProcessedContentOutput( new File( generatedSiteDirectory, "processed" ) );
401 }
402
403 return context;
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419 protected Map<String, MavenReport> locateReports( List<MavenReportExecution> reports,
420 Map<String, DocumentRenderer> documents, Locale locale )
421 {
422
423 List<MavenReportExecution> filtered = new ArrayList<MavenReportExecution>( reports );
424
425 Map<String, MavenReport> reportsByOutputName = new LinkedHashMap<String, MavenReport>();
426 for ( MavenReportExecution mavenReportExecution : filtered )
427 {
428 MavenReport report = mavenReportExecution.getMavenReport();
429
430 String outputName = report.getOutputName() + ".html";
431
432
433 reportsByOutputName.put( report.getOutputName(), report );
434
435 if ( documents.containsKey( outputName ) )
436 {
437 String reportMojoInfo =
438 ( mavenReportExecution.getGoal() == null ) ? "" : ( " ("
439 + mavenReportExecution.getPlugin().getArtifactId() + ':'
440 + mavenReportExecution.getPlugin().getVersion() + ':' + mavenReportExecution.getGoal() + ')' );
441
442 getLog().info( "Skipped \"" + report.getName( locale ) + "\" report" + reportMojoInfo + ", file \""
443 + outputName + "\" already exists." );
444
445 reports.remove( mavenReportExecution );
446 }
447 else
448 {
449 String reportMojoInfo = mavenReportExecution.getPlugin().getGroupId() + ':'
450 + mavenReportExecution.getPlugin().getArtifactId() + ':'
451 + mavenReportExecution.getPlugin().getVersion() + ':' + mavenReportExecution.getGoal();
452 RenderingContext renderingContext = new RenderingContext( siteDirectory, outputName, reportMojoInfo );
453 DocumentRenderer renderer =
454 new ReportDocumentRenderer( mavenReportExecution, renderingContext, getLog() );
455 documents.put( outputName, renderer );
456 }
457 }
458 return reportsByOutputName;
459 }
460
461
462
463
464
465
466
467
468 protected Map<String, List<MavenReport>> categoriseReports( Collection<MavenReport> reports )
469 {
470 Map<String, List<MavenReport>> categories = new LinkedHashMap<String, List<MavenReport>>();
471 for ( MavenReport report : reports )
472 {
473 List<MavenReport> categoryReports = categories.get( report.getCategoryName() );
474 if ( categoryReports == null )
475 {
476 categoryReports = new ArrayList<MavenReport>();
477 categories.put( report.getCategoryName(), categoryReports );
478 }
479 categoryReports.add( report );
480 }
481 return categories;
482 }
483
484
485
486
487
488
489
490
491
492 protected Map<String, DocumentRenderer> locateDocuments( SiteRenderingContext context,
493 List<MavenReportExecution> reports, Locale locale )
494 throws IOException, RendererException
495 {
496 Map<String, DocumentRenderer> documents = siteRenderer.locateDocumentFiles( context, true );
497
498 Map<String, MavenReport> reportsByOutputName = locateReports( reports, documents, locale );
499
500
501 Map<String, List<MavenReport>> categories = categoriseReports( reportsByOutputName.values() );
502
503 siteTool.populateReportsMenu( context.getDecoration(), locale, categories );
504 populateReportItems( context.getDecoration(), locale, reportsByOutputName );
505
506 if ( categories.containsKey( MavenReport.CATEGORY_PROJECT_INFORMATION ) && generateProjectInfo )
507 {
508
509 List<MavenReport> categoryReports = categories.get( MavenReport.CATEGORY_PROJECT_INFORMATION );
510
511 RenderingContext renderingContext =
512 new RenderingContext( siteDirectory, "project-info.html",
513 getSitePluginInfo() + ":CategorySummaryDocumentRenderer" );
514 String title = i18n.getString( "site-plugin", locale, "report.information.title" );
515 String desc1 = i18n.getString( "site-plugin", locale, "report.information.description1" );
516 String desc2 = i18n.getString( "site-plugin", locale, "report.information.description2" );
517 DocumentRenderer renderer = new CategorySummaryDocumentRenderer( renderingContext, title, desc1, desc2,
518 i18n, categoryReports, getLog() );
519
520 if ( !documents.containsKey( renderer.getOutputName() ) )
521 {
522 documents.put( renderer.getOutputName(), renderer );
523 }
524 else
525 {
526 getLog().info( "Category summary '" + renderer.getOutputName() + "' skipped; already exists" );
527 }
528 }
529
530 if ( categories.containsKey( MavenReport.CATEGORY_PROJECT_REPORTS ) )
531 {
532
533 List<MavenReport> categoryReports = categories.get( MavenReport.CATEGORY_PROJECT_REPORTS );
534 RenderingContext renderingContext =
535 new RenderingContext( siteDirectory, "project-reports.html",
536 getSitePluginInfo() + ":CategorySummaryDocumentRenderer" );
537 String title = i18n.getString( "site-plugin", locale, "report.project.title" );
538 String desc1 = i18n.getString( "site-plugin", locale, "report.project.description1" );
539 String desc2 = i18n.getString( "site-plugin", locale, "report.project.description2" );
540 DocumentRenderer renderer = new CategorySummaryDocumentRenderer( renderingContext, title, desc1, desc2,
541 i18n, categoryReports, getLog() );
542
543 if ( !documents.containsKey( renderer.getOutputName() ) )
544 {
545 documents.put( renderer.getOutputName(), renderer );
546 }
547 else
548 {
549 getLog().info( "Category summary '" + renderer.getOutputName() + "' skipped; already exists" );
550 }
551 }
552 return documents;
553 }
554
555 private String getSitePluginInfo()
556 {
557 PluginDescriptor pluginDescriptor = (PluginDescriptor) getPluginContext().get( "pluginDescriptor" );
558 return pluginDescriptor.getId();
559 }
560 protected void populateReportItems( DecorationModel decorationModel, Locale locale,
561 Map<String, MavenReport> reportsByOutputName )
562 {
563 for ( Menu menu : decorationModel.getMenus() )
564 {
565 populateItemRefs( menu.getItems(), locale, reportsByOutputName );
566 }
567 }
568
569 private void populateItemRefs( List<MenuItem> items, Locale locale, Map<String, MavenReport> reportsByOutputName )
570 {
571 for ( Iterator<MenuItem> i = items.iterator(); i.hasNext(); )
572 {
573 MenuItem item = i.next();
574
575 if ( item.getRef() != null )
576 {
577 MavenReport report = reportsByOutputName.get( item.getRef() );
578
579 if ( report != null )
580 {
581 if ( item.getName() == null )
582 {
583 item.setName( report.getName( locale ) );
584 }
585
586 if ( item.getHref() == null || item.getHref().length() == 0 )
587 {
588 item.setHref( report.getOutputName() + ".html" );
589 }
590 }
591 else
592 {
593 getLog().warn( "Unrecognised reference: '" + item.getRef() + "'" );
594 i.remove();
595 }
596 }
597
598 populateItemRefs( item.getItems(), locale, reportsByOutputName );
599 }
600 }
601 }