1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.felix.bundleplugin.baseline;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.util.Locale;
26 import java.util.Map;
27 import java.util.ResourceBundle;
28
29 import org.apache.maven.doxia.sink.Sink;
30 import org.apache.maven.plugins.annotations.LifecyclePhase;
31 import org.apache.maven.plugins.annotations.Mojo;
32 import org.apache.maven.plugins.annotations.Parameter;
33 import org.apache.maven.reporting.MavenReport;
34 import org.apache.maven.reporting.MavenReportException;
35 import org.codehaus.plexus.util.IOUtil;
36
37 import aQute.bnd.version.Version;
38
39
40
41
42
43
44 @Mojo( name = "baseline-report", threadSafe = true,
45 defaultPhase = LifecyclePhase.SITE)
46 public final class BaselineReport
47 extends AbstractBaselinePlugin
48 implements MavenReport
49 {
50
51
52
53
54 @Parameter(defaultValue = "${project.reporting.outputDirectory}")
55 private File outputDirectory;
56
57 private static final class Context {
58 public Sink sink;
59
60 public Locale locale;
61
62 public int currentDepth = 0;
63 }
64
65
66
67 @Override
68 protected Object init(final Object context)
69 {
70 failOnError = false;
71 failOnWarning = false;
72
73 final File baselineImagesDirectory = new File( outputDirectory, "images/baseline" );
74 baselineImagesDirectory.mkdirs();
75
76 for ( String resourceName : new String[]{ "access.gif",
77 "annotated.gif",
78 "annotation.gif",
79 "bundle.gif",
80 "class.gif",
81 "constant.gif",
82 "enum.gif",
83 "error.gif",
84 "extends.gif",
85 "field.gif",
86 "implements.gif",
87 "info.gif",
88 "interface.gif",
89 "method.gif",
90 "package.gif",
91 "resource.gif",
92 "return.gif",
93 "version.gif",
94 "warning.gif" } )
95 {
96 InputStream source = getClass().getResourceAsStream( resourceName );
97 OutputStream target = null;
98 File targetFile = new File( baselineImagesDirectory, resourceName );
99
100 try
101 {
102 target = buildContext.newFileOutputStream( targetFile );
103 IOUtil.copy( source, target );
104 }
105 catch ( IOException e )
106 {
107 getLog().warn( "Impossible to copy " + resourceName + " image, maybe the site won't be properly rendered." );
108 }
109 finally
110 {
111 IOUtil.close( source );
112 IOUtil.close( target );
113 }
114 }
115 return context;
116 }
117
118 @Override
119 protected void close(final Object context)
120 {
121
122 }
123
124 @Override
125 protected void startBaseline( final Object context, String generationDate, String bundleName,
126 String currentVersion, String previousVersion )
127 {
128 final Context ctx = (Context)context;
129 final Sink sink = ctx.sink;
130
131 sink.head();
132 sink.title();
133
134 String title = getBundle( ctx.locale ).getString( "report.baseline.title" );
135 sink.text( title );
136 sink.title_();
137 sink.head_();
138
139 sink.body();
140
141 sink.section1();
142 sink.sectionTitle1();
143 sink.text( title );
144 sink.sectionTitle1_();
145
146 sink.paragraph();
147 sink.text( getBundle( ctx.locale ).getString( "report.baseline.bndlink" ) + " " );
148 sink.link( "http://www.aqute.biz/Bnd/Bnd" );
149 sink.text( "Bnd" );
150 sink.link_();
151 sink.text( "." );
152 sink.paragraph_();
153
154 sink.paragraph();
155 sink.text( getBundle( ctx.locale ).getString( "report.baseline.bundle" ) + " " );
156 sink.figure();
157 sink.figureGraphics( "images/baseline/bundle.gif" );
158 sink.figure_();
159 sink.text( " " );
160 sink.bold();
161 sink.text( bundleName );
162 sink.bold_();
163 sink.listItem_();
164
165 sink.paragraph();
166 sink.text( getBundle( ctx.locale ).getString( "report.baseline.version.current" ) + " " );
167 sink.bold();
168 sink.text( currentVersion );
169 sink.bold_();
170 sink.paragraph_();
171
172 sink.paragraph();
173 sink.text( getBundle( ctx.locale ).getString( "report.baseline.version.comparison" ) + " " );
174 sink.bold();
175 sink.text( comparisonVersion );
176 sink.bold_();
177 sink.paragraph_();
178
179 sink.paragraph();
180 sink.text( getBundle( ctx.locale ).getString( "report.baseline.generationdate" ) + " " );
181 sink.bold();
182 sink.text( generationDate );
183 sink.bold_();
184 sink.paragraph_();
185
186 sink.section1_();
187 }
188
189 @Override
190 protected void startPackage( final Object context,
191 boolean mismatch,
192 String packageName,
193 String shortDelta,
194 String delta,
195 Version newerVersion,
196 Version olderVersion,
197 Version suggestedVersion,
198 DiffMessage diffMessage,
199 Map<String,String> attributes )
200 {
201 final Context ctx = (Context)context;
202 final Sink sink = ctx.sink;
203
204 sink.list();
205
206 sink.listItem();
207
208 sink.figure();
209 sink.figureGraphics( "./images/baseline/package.gif" );
210 sink.figure_();
211 sink.text( " " );
212 sink.monospaced();
213 sink.text( packageName );
214 sink.monospaced_();
215
216 if ( diffMessage != null )
217 {
218 sink.text( " " );
219 sink.figure();
220 sink.figureGraphics( "./images/baseline/" + diffMessage.getType().name() + ".gif" );
221 sink.figure_();
222 sink.text( " " );
223 sink.italic();
224 sink.text( diffMessage.getMessage() );
225 sink.italic_();
226 sink.text( " (newer version: " );
227 sink.monospaced();
228 sink.text( newerVersion.toString() );
229 sink.monospaced_();
230 sink.text( ", older version: " );
231 sink.monospaced();
232 sink.text( olderVersion.toString() );
233 if ( suggestedVersion != null )
234 {
235 sink.monospaced_();
236 sink.text( ", suggested version: " );
237 sink.monospaced();
238 sink.text( suggestedVersion.toString() );
239 }
240 sink.monospaced_();
241 sink.text( ")" );
242 }
243 }
244
245 @Override
246 protected void startDiff( final Object context,
247 int depth,
248 String type,
249 String name,
250 String delta,
251 String shortDelta )
252 {
253 final Context ctx = (Context)context;
254 final Sink sink = ctx.sink;
255
256 if ( ctx.currentDepth < depth )
257 {
258 sink.list();
259 }
260
261 ctx.currentDepth = depth;
262
263 sink.listItem();
264 sink.figure();
265 sink.figureGraphics( "images/baseline/" + type + ".gif" );
266 sink.figure_();
267 sink.text( " " );
268
269 sink.monospaced();
270 sink.text( name );
271 sink.monospaced_();
272
273 sink.text( " " );
274
275 sink.italic();
276 sink.text( delta );
277 sink.italic_();
278 }
279
280 @Override
281 protected void endDiff( final Object context, int depth )
282 {
283 final Context ctx = (Context)context;
284 final Sink sink = ctx.sink;
285
286 sink.listItem_();
287
288 if ( ctx.currentDepth > depth )
289 {
290 sink.list_();
291 }
292
293 ctx.currentDepth = depth;
294 }
295
296 @Override
297 protected void endPackage(final Object context)
298 {
299 final Context ctx = (Context)context;
300 final Sink sink = ctx.sink;
301 if ( ctx.currentDepth > 0 )
302 {
303 sink.list_();
304 ctx.currentDepth = 0;
305 }
306
307 sink.listItem_();
308 sink.list_();
309 }
310
311 @Override
312 protected void endBaseline(final Object context)
313 {
314 final Context ctx = (Context)context;
315 ctx.sink.body_();
316 ctx.sink.flush();
317 ctx.sink.close();
318 }
319
320
321
322 public boolean canGenerateReport()
323 {
324 return !skip && outputDirectory != null;
325 }
326
327 public void generate( @SuppressWarnings( "deprecation" ) org.codehaus.doxia.sink.Sink sink, Locale locale )
328 throws MavenReportException
329 {
330 final Context ctx = new Context();
331 ctx.sink = sink;
332 ctx.locale = locale;
333
334 try
335 {
336 execute(ctx);
337 }
338 catch ( Exception e )
339 {
340 getLog().warn( "An error occurred while producing the report page, see nested exceptions", e );
341 }
342 }
343
344 public String getCategoryName()
345 {
346 return MavenReport.CATEGORY_PROJECT_REPORTS;
347 }
348
349 public String getDescription( Locale locale )
350 {
351 return getBundle( locale ).getString( "report.baseline.description" );
352 }
353
354 public String getName( Locale locale )
355 {
356 return getBundle( locale ).getString( "report.baseline.name" );
357 }
358
359 private ResourceBundle getBundle( Locale locale )
360 {
361 return ResourceBundle.getBundle( "baseline-report", locale, getClass().getClassLoader() );
362 }
363
364 public String getOutputName()
365 {
366 return "baseline-report";
367 }
368
369 public File getReportOutputDirectory()
370 {
371 return outputDirectory;
372 }
373
374 public boolean isExternalReport()
375 {
376 return false;
377 }
378
379 public void setReportOutputDirectory( File outputDirectory )
380 {
381 this.outputDirectory = outputDirectory;
382 }
383
384 }