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