1 package org.apache.maven.reporting;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.artifact.Artifact;
23 import org.apache.maven.artifact.repository.ArtifactRepository;
24 import org.apache.maven.doxia.sink.Sink;
25 import org.apache.maven.doxia.sink.SinkFactory;
26 import org.apache.maven.doxia.site.decoration.DecorationModel;
27 import org.apache.maven.doxia.site.decoration.Skin;
28 import org.apache.maven.doxia.siterenderer.Renderer;
29 import org.apache.maven.doxia.siterenderer.RendererException;
30 import org.apache.maven.doxia.siterenderer.RenderingContext;
31 import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
32 import org.apache.maven.doxia.siterenderer.sink.SiteRendererSink;
33 import org.apache.maven.doxia.tools.SiteTool;
34 import org.apache.maven.doxia.tools.SiteToolException;
35 import org.apache.maven.plugin.AbstractMojo;
36 import org.apache.maven.plugin.MojoExecutionException;
37 import org.apache.maven.plugins.annotations.Component;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.project.MavenProject;
40 import org.apache.maven.shared.utils.WriterFactory;
41 import org.codehaus.plexus.util.ReaderFactory;
42
43 import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
44
45 import java.io.File;
46 import java.io.FileOutputStream;
47 import java.io.IOException;
48 import java.io.OutputStreamWriter;
49 import java.io.Writer;
50 import java.util.HashMap;
51 import java.util.List;
52 import java.util.Locale;
53 import java.util.Map;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public abstract class AbstractMavenReport
72 extends AbstractMojo
73 implements MavenMultiPageReport
74 {
75
76
77
78
79
80 @Parameter( defaultValue = "${project.reporting.outputDirectory}", readonly = true, required = true )
81 protected File outputDirectory;
82
83
84
85
86 @Parameter( defaultValue = "${project}", readonly = true, required = true )
87 protected MavenProject project;
88
89
90
91
92 @Parameter( property = "encoding", defaultValue = "${project.build.sourceEncoding}", readonly = true )
93 private String inputEncoding;
94
95
96
97
98 @Parameter( property = "outputEncoding", defaultValue = "${project.reporting.outputEncoding}", readonly = true )
99 private String outputEncoding;
100
101
102
103
104 @Parameter( defaultValue = "${localRepository}", readonly = true, required = true )
105 protected ArtifactRepository localRepository;
106
107
108
109
110 @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
111 protected List<ArtifactRepository> remoteRepositories;
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 @Parameter
128 protected Skin skin;
129
130
131
132
133 @Component
134 protected SiteTool siteTool;
135
136
137
138
139 @Component
140 protected Renderer siteRenderer;
141
142
143 private Sink sink;
144
145
146 private SinkFactory sinkFactory;
147
148
149 private File reportOutputDirectory;
150
151
152
153
154
155
156
157 @Override
158 public void execute()
159 throws MojoExecutionException
160 {
161 if ( !canGenerateReport() )
162 {
163 return;
164 }
165
166 File outputDirectory = new File( getOutputDirectory() );
167
168 String filename = getOutputName() + ".html";
169
170 Locale locale = Locale.getDefault();
171
172 try
173 {
174 SiteRenderingContext siteContext = createSiteRenderingContext( locale );
175
176
177 siteRenderer.copyResources( siteContext, outputDirectory );
178
179
180 RenderingContext docRenderingContext = new RenderingContext( outputDirectory, filename, null );
181
182 SiteRendererSink sink = new SiteRendererSink( docRenderingContext );
183
184 generate( sink, null, locale );
185
186 if ( !isExternalReport() )
187 {
188 outputDirectory.mkdirs();
189
190 try ( Writer writer =
191 new OutputStreamWriter( new FileOutputStream( new File( outputDirectory, filename ) ),
192 getOutputEncoding() ) )
193 {
194
195 getSiteRenderer().mergeDocumentIntoSite( writer, sink, siteContext );
196 }
197 }
198
199
200 siteRenderer.copyResources( siteContext, outputDirectory );
201 }
202 catch ( RendererException | IOException | MavenReportException e )
203 {
204 throw new MojoExecutionException(
205 "An error has occurred in " + getName( Locale.ENGLISH ) + " report generation.", e );
206 }
207 }
208
209 private SiteRenderingContext createSiteRenderingContext( Locale locale )
210 throws MavenReportException, IOException
211 {
212 DecorationModel decorationModel = new DecorationModel();
213 decorationModel.setSkin( getSkin() );
214
215 Map<String, Object> templateProperties = new HashMap<>();
216
217 templateProperties.put( "standalone", Boolean.TRUE );
218 templateProperties.put( "project", getProject() );
219 templateProperties.put( "inputEncoding", getInputEncoding() );
220 templateProperties.put( "outputEncoding", getOutputEncoding() );
221
222 for ( Map.Entry<Object, Object> entry : getProject().getProperties().entrySet() )
223 {
224 templateProperties.put( (String) entry.getKey(), entry.getValue() );
225 }
226
227 SiteRenderingContext context;
228 try
229 {
230 Artifact skinArtifact =
231 siteTool.getSkinArtifactFromRepository( localRepository, remoteRepositories, decorationModel );
232
233 getLog().info( buffer().a( "Rendering content with " ).strong( skinArtifact.getId()
234 + " skin" ).a( '.' ).toString() );
235
236 context = siteRenderer.createContextForSkin( skinArtifact, templateProperties, decorationModel,
237 project.getName(), locale );
238 }
239 catch ( SiteToolException e )
240 {
241 throw new MavenReportException( "Failed to retrieve skin artifact", e );
242 }
243 catch ( RendererException e )
244 {
245 throw new MavenReportException( "Failed to create context for skin", e );
246 }
247
248
249 context.setRootDirectory( project.getBasedir() );
250
251 return context;
252 }
253
254
255
256
257
258
259
260
261
262 @Deprecated
263 @Override
264 public void generate( Sink sink, Locale locale )
265 throws MavenReportException
266 {
267 generate( sink, null, locale );
268 }
269
270
271
272
273
274
275
276
277
278 @Override
279 public void generate( Sink sink, SinkFactory sinkFactory, Locale locale )
280 throws MavenReportException
281 {
282 if ( !canGenerateReport() )
283 {
284 getLog().info( "This report cannot be generated as part of the current build. "
285 + "The report name should be referenced in this line of output." );
286 return;
287 }
288
289 this.sink = sink;
290
291 this.sinkFactory = sinkFactory;
292
293 executeReport( locale );
294
295 closeReport();
296 }
297
298
299
300
301 @Override
302 public String getCategoryName()
303 {
304 return CATEGORY_PROJECT_REPORTS;
305 }
306
307 @Override
308 public File getReportOutputDirectory()
309 {
310 if ( reportOutputDirectory == null )
311 {
312 reportOutputDirectory = new File( getOutputDirectory() );
313 }
314
315 return reportOutputDirectory;
316 }
317
318 @Override
319 public void setReportOutputDirectory( File reportOutputDirectory )
320 {
321 this.reportOutputDirectory = reportOutputDirectory;
322 this.outputDirectory = reportOutputDirectory;
323 }
324
325 protected String getOutputDirectory()
326 {
327 return outputDirectory.getAbsolutePath();
328 }
329
330 protected MavenProject getProject()
331 {
332 return project;
333 }
334
335 protected Renderer getSiteRenderer()
336 {
337 return siteRenderer;
338 }
339
340
341
342
343
344
345 protected String getInputEncoding()
346 {
347 return ( inputEncoding == null ) ? ReaderFactory.FILE_ENCODING : inputEncoding;
348 }
349
350
351
352
353
354
355 protected String getOutputEncoding()
356 {
357 return ( outputEncoding == null ) ? WriterFactory.UTF_8 : outputEncoding;
358 }
359
360
361
362
363
364
365 protected Skin getSkin()
366 {
367 if ( skin == null )
368 {
369 Skin skin = new Skin();
370 skin.setGroupId( "org.apache.maven.skins" );
371 skin.setArtifactId( "maven-fluido-skin" );
372 skin.setVersion( "1.11.1" );
373 return skin;
374 }
375 else
376 {
377 return skin;
378 }
379 }
380
381
382
383
384 protected void closeReport()
385 {
386 getSink().close();
387 }
388
389
390
391
392 public Sink getSink()
393 {
394 return sink;
395 }
396
397
398
399
400 public SinkFactory getSinkFactory()
401 {
402 return sinkFactory;
403 }
404
405
406
407
408
409 @Override
410 public boolean isExternalReport()
411 {
412 return false;
413 }
414
415 @Override
416 public boolean canGenerateReport()
417 {
418 return true;
419 }
420
421
422
423
424
425
426
427 protected abstract void executeReport( Locale locale )
428 throws MavenReportException;
429 }