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