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 static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
23
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.io.Writer;
28 import java.io.File;
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.util.ArrayList;
32 import java.util.Locale;
33 import java.util.List;
34
35 import org.apache.maven.doxia.sink.Sink;
36 import org.apache.maven.doxia.sink.SinkFactory;
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.siterenderer.sink.SiteRendererSink;
43 import org.apache.maven.doxia.tools.MojoLogWrapper;
44 import org.apache.maven.plugin.logging.Log;
45 import org.apache.maven.reporting.MavenMultiPageReport;
46 import org.apache.maven.reporting.MavenReport;
47 import org.apache.maven.reporting.MavenReportException;
48 import org.apache.maven.reporting.exec.MavenReportExecution;
49 import org.codehaus.plexus.util.IOUtil;
50 import org.codehaus.plexus.util.StringUtils;
51 import org.codehaus.plexus.util.WriterFactory;
52
53
54
55
56
57
58 public class ReportDocumentRenderer
59 implements DocumentRenderer
60 {
61 private final MavenReport report;
62
63 private final RenderingContext renderingContext;
64
65 private final String reportMojoInfo;
66
67 private final ClassLoader classLoader;
68
69 private final Log log;
70
71 public ReportDocumentRenderer( MavenReportExecution mavenReportExecution, RenderingContext renderingContext,
72 Log log )
73 {
74 this.report = mavenReportExecution.getMavenReport();
75
76 this.renderingContext = renderingContext;
77
78 if ( mavenReportExecution.getPlugin() == null )
79 {
80
81 this.reportMojoInfo = getPluginInfo( report );
82 }
83 else
84 {
85
86 this.reportMojoInfo =
87 mavenReportExecution.getPlugin().getArtifactId() + ':' + mavenReportExecution.getPlugin().getVersion()
88 + ':' + mavenReportExecution.getGoal();
89 }
90
91 this.classLoader = mavenReportExecution.getClassLoader();
92
93 this.log = log;
94 }
95
96
97
98
99
100
101
102
103 private String getPluginInfo( MavenReport report )
104 {
105 Package pkg = report.getClass().getPackage();
106
107 if ( pkg != null )
108 {
109 String title = pkg.getSpecificationTitle();
110 String version = pkg.getSpecificationVersion();
111
112 if ( title == null )
113 {
114 return version;
115 }
116 else if ( version == null )
117 {
118 return title;
119 }
120 else
121 {
122 return title + ' ' + version;
123 }
124 }
125
126 return null;
127 }
128
129 private static class MultiPageSubSink
130 extends SiteRendererSink
131 {
132 private File outputDir;
133
134 private String outputName;
135
136 public MultiPageSubSink( File outputDir, String outputName, RenderingContext ctx )
137 {
138 super( ctx );
139 this.outputName = outputName;
140 this.outputDir = outputDir;
141 }
142
143 public String getOutputName()
144 {
145 return outputName;
146 }
147
148 public File getOutputDir()
149 {
150 return outputDir;
151 }
152
153 }
154
155 private static class MultiPageSinkFactory
156 implements SinkFactory
157 {
158 private RenderingContext context;
159
160 private List<MultiPageSubSink> sinks = new ArrayList<MultiPageSubSink>();
161
162 public MultiPageSinkFactory( RenderingContext ctx )
163 {
164 this.context = ctx;
165 }
166
167 public Sink createSink( File outputDir, String outputName )
168 {
169 MultiPageSubSink sink = new MultiPageSubSink( outputDir, outputName, context );
170 sinks.add( sink );
171 return sink;
172 }
173
174 public Sink createSink( File arg0, String arg1, String arg2 )
175 throws IOException
176 {
177
178 return null;
179 }
180
181 public Sink createSink( OutputStream arg0 )
182 throws IOException
183 {
184
185 return null;
186 }
187
188 public Sink createSink( OutputStream arg0, String arg1 )
189 throws IOException
190 {
191
192 return null;
193 }
194
195 public List<MultiPageSubSink> sinks()
196 {
197 return sinks;
198 }
199 }
200
201 public void renderDocument( Writer writer, Renderer renderer, SiteRenderingContext siteRenderingContext )
202 throws RendererException, FileNotFoundException
203 {
204 Locale locale = siteRenderingContext.getLocale();
205 String localReportName = report.getName( locale );
206
207 String msg = "Generating \"" + buffer().strong( localReportName ) + "\" report";
208
209 log.info( reportMojoInfo == null ? ( msg + '.' )
210 : ( StringUtils.rightPad( msg, 40 ) + buffer().strong( " --- " ).mojo( reportMojoInfo ) ) );
211
212
213
214 SiteRendererSink mainSink = new SiteRendererSink( renderingContext );
215
216 MultiPageSinkFactory multiPageSinkFactory = new MultiPageSinkFactory( renderingContext );
217
218 ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
219 try
220 {
221 if ( classLoader != null )
222 {
223 Thread.currentThread().setContextClassLoader( classLoader );
224 }
225
226 if ( report instanceof MavenMultiPageReport )
227 {
228
229 ( (MavenMultiPageReport) report ).generate( mainSink, multiPageSinkFactory, locale );
230 }
231 else if ( generateMultiPage( locale, multiPageSinkFactory, mainSink ) )
232 {
233
234 }
235 else
236 {
237
238 report.generate( mainSink, locale );
239 }
240 }
241 catch ( MavenReportException e )
242 {
243 String report = ( reportMojoInfo == null ) ? ( '"' + localReportName + "\" report" ) : reportMojoInfo;
244 throw new RendererException( "Error generating " + report + ": " + e.getMessage(), e );
245 }
246 catch ( LinkageError e )
247 {
248 String report = ( reportMojoInfo == null ) ? ( '"' + localReportName + "\" report" ) : reportMojoInfo;
249 log.warn( "An issue has occurred with " + report + ", skipping LinkageError "
250 + e.getMessage() + ", please report an issue to Maven dev team.", e );
251 }
252 finally
253 {
254 if ( classLoader != null )
255 {
256 Thread.currentThread().setContextClassLoader( originalClassLoader );
257 }
258 mainSink.close();
259 }
260
261 if ( report.isExternalReport() )
262 {
263
264 return;
265 }
266
267
268 renderer.generateDocument( writer, mainSink, siteRenderingContext );
269
270
271 try
272 {
273 List<MultiPageSubSink> sinks = multiPageSinkFactory.sinks();
274
275 log.debug( "Multipage report: " + sinks.size() + " subreports" );
276
277 for ( MultiPageSubSink mySink : sinks )
278 {
279 mySink.enableLogging( new MojoLogWrapper( log ) );
280
281 log.debug( " Rendering " + mySink.getOutputName() );
282
283 File outputFile = new File( mySink.getOutputDir(), mySink.getOutputName() );
284
285 Writer out = null;
286 try
287 {
288 out = WriterFactory.newWriter( outputFile, siteRenderingContext.getOutputEncoding() );
289 renderer.generateDocument( out, mySink, siteRenderingContext );
290 mySink.close();
291 mySink = null;
292 out.close();
293 out = null;
294 }
295 finally
296 {
297 IOUtil.close( out );
298
299 if ( mySink != null )
300 {
301 mySink.close();
302 }
303 }
304 }
305 }
306 catch ( IOException e )
307 {
308 throw new RendererException( "Cannot create writer", e );
309 }
310 }
311
312
313
314
315
316
317 private boolean generateMultiPage( Locale locale, SinkFactory sf, Sink sink )
318 throws MavenReportException
319 {
320 try
321 {
322
323
324 Method generate =
325 report.getClass().getMethod( "generate", Sink.class, SinkFactory.class, Locale.class );
326
327 generate.invoke( report, sink, sf, locale );
328
329 return true;
330 }
331 catch ( SecurityException se )
332 {
333 return false;
334 }
335 catch ( NoSuchMethodException nsme )
336 {
337 return false;
338 }
339 catch ( IllegalArgumentException iae )
340 {
341 throw new MavenReportException( "error while invoking generate", iae );
342 }
343 catch ( IllegalAccessException iae )
344 {
345 throw new MavenReportException( "error while invoking generate", iae );
346 }
347 catch ( InvocationTargetException ite )
348 {
349 throw new MavenReportException( "error while invoking generate", ite );
350 }
351 }
352
353 public String getOutputName()
354 {
355 return renderingContext.getOutputName();
356 }
357
358 public RenderingContext getRenderingContext()
359 {
360 return renderingContext;
361 }
362
363 public boolean isOverwrite()
364 {
365
366 return true;
367 }
368
369
370
371
372 public boolean isExternalReport()
373 {
374 return report.isExternalReport();
375 }
376 }