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