blob: 5774d7d2ebbc1fa114a7df3e043486f963821b90 [file] [log] [blame]
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.bundleplugin.baseline;
20
21import java.io.File;
22import java.io.FileOutputStream;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.OutputStream;
26import java.util.Locale;
27import java.util.Map;
28import java.util.ResourceBundle;
29
30import org.apache.maven.doxia.sink.Sink;
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000031import org.apache.maven.plugins.annotations.LifecyclePhase;
32import org.apache.maven.plugins.annotations.Mojo;
33import org.apache.maven.plugins.annotations.Parameter;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000034import org.apache.maven.reporting.MavenReport;
35import org.apache.maven.reporting.MavenReportException;
36import org.codehaus.plexus.util.IOUtil;
37
Carsten Ziegelerccc30322015-03-03 10:48:44 +000038import aQute.bnd.version.Version;
39
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000040/**
41 * BND Baseline report.
42 *
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000043 * @since 2.4.1
44 */
Carsten Ziegeler0a4eff12015-05-12 06:04:41 +000045@Mojo( name = "baseline-report", threadSafe = true,
46 defaultPhase = LifecyclePhase.SITE)
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000047public final class BaselineReport
48 extends AbstractBaselinePlugin
49 implements MavenReport
50{
51
52 /**
53 * Specifies the directory where the report will be generated.
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000054 */
Carsten Ziegeler318c2cb2015-03-09 13:57:23 +000055 @Parameter(defaultValue = "${project.reporting.outputDirectory}")
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000056 private File outputDirectory;
57
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +000058 private static final class Context {
59 public Sink sink;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000060
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +000061 public Locale locale;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000062
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +000063 public int currentDepth = 0;
64 }
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000065
66 // AbstractBaselinePlugin events
67
68 @Override
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +000069 protected Object init(final Object context)
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +000070 {
71 failOnError = false;
72 failOnWarning = false;
73
74 final File baselineImagesDirectory = new File( outputDirectory, "images/baseline" );
75 baselineImagesDirectory.mkdirs();
76
77 for ( String resourceName : new String[]{ "access.gif",
78 "annotated.gif",
79 "annotation.gif",
80 "bundle.gif",
81 "class.gif",
82 "constant.gif",
83 "enum.gif",
84 "error.gif",
85 "extends.gif",
86 "field.gif",
87 "implements.gif",
88 "info.gif",
89 "interface.gif",
90 "method.gif",
91 "package.gif",
92 "resource.gif",
93 "return.gif",
94 "version.gif",
95 "warning.gif" } )
96 {
97 InputStream source = getClass().getResourceAsStream( resourceName );
98 OutputStream target = null;
99 File targetFile = new File( baselineImagesDirectory, resourceName );
100
101 try
102 {
103 target = new FileOutputStream( targetFile );
104 IOUtil.copy( source, target );
105 }
106 catch ( IOException e )
107 {
108 getLog().warn( "Impossible to copy " + resourceName + " image, maybe the site won't be properly rendered." );
109 }
110 finally
111 {
112 IOUtil.close( source );
113 IOUtil.close( target );
114 }
115 }
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000116 return context;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000117 }
118
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000119 @Override
120 protected void close(final Object context)
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000121 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000122 // nothing to do
123 }
124
125 @Override
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000126 protected void startBaseline( final Object context, String generationDate, String bundleName,
127 String currentVersion, String previousVersion )
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000128 {
129 final Context ctx = (Context)context;
130 final Sink sink = ctx.sink;
131
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000132 sink.head();
133 sink.title();
134
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000135 String title = getBundle( ctx.locale ).getString( "report.baseline.title" );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000136 sink.text( title );
137 sink.title_();
138 sink.head_();
139
140 sink.body();
141
142 sink.section1();
143 sink.sectionTitle1();
144 sink.text( title );
145 sink.sectionTitle1_();
146
147 sink.paragraph();
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000148 sink.text( getBundle( ctx.locale ).getString( "report.baseline.bndlink" ) + " " );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000149 sink.link( "http://www.aqute.biz/Bnd/Bnd" );
150 sink.text( "Bnd" );
151 sink.link_();
152 sink.text( "." );
153 sink.paragraph_();
154
155 sink.paragraph();
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000156 sink.text( getBundle( ctx.locale ).getString( "report.baseline.bundle" ) + " " );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000157 sink.figure();
158 sink.figureGraphics( "images/baseline/bundle.gif" );
159 sink.figure_();
160 sink.text( " " );
161 sink.bold();
162 sink.text( bundleName );
163 sink.bold_();
164 sink.listItem_();
165
166 sink.paragraph();
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000167 sink.text( getBundle( ctx.locale ).getString( "report.baseline.version.current" ) + " " );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000168 sink.bold();
169 sink.text( currentVersion );
170 sink.bold_();
171 sink.paragraph_();
172
173 sink.paragraph();
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000174 sink.text( getBundle( ctx.locale ).getString( "report.baseline.version.comparison" ) + " " );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000175 sink.bold();
176 sink.text( comparisonVersion );
177 sink.bold_();
178 sink.paragraph_();
179
180 sink.paragraph();
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000181 sink.text( getBundle( ctx.locale ).getString( "report.baseline.generationdate" ) + " " );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000182 sink.bold();
183 sink.text( generationDate );
184 sink.bold_();
185 sink.paragraph_();
186
187 sink.section1_();
188 }
189
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000190 @Override
191 protected void startPackage( final Object context,
192 boolean mismatch,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000193 String packageName,
194 String shortDelta,
195 String delta,
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000196 Version newerVersion,
197 Version olderVersion,
198 Version suggestedVersion,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000199 DiffMessage diffMessage,
200 Map<String,String> attributes )
201 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000202 final Context ctx = (Context)context;
203 final Sink sink = ctx.sink;
204
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000205 sink.list();
206
207 sink.listItem();
208
209 sink.figure();
210 sink.figureGraphics( "./images/baseline/package.gif" );
211 sink.figure_();
212 sink.text( " " );
213 sink.monospaced();
214 sink.text( packageName );
215 sink.monospaced_();
216
217 if ( diffMessage != null )
218 {
219 sink.text( " " );
220 sink.figure();
221 sink.figureGraphics( "./images/baseline/" + diffMessage.getType().name() + ".gif" );
222 sink.figure_();
223 sink.text( " " );
224 sink.italic();
225 sink.text( diffMessage.getMessage() );
226 sink.italic_();
227 sink.text( " (newer version: " );
228 sink.monospaced();
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000229 sink.text( newerVersion.toString() );
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000230 sink.monospaced_();
231 sink.text( ", older version: " );
232 sink.monospaced();
Carsten Ziegelerccc30322015-03-03 10:48:44 +0000233 sink.text( olderVersion.toString() );
234 if ( suggestedVersion != null )
235 {
236 sink.monospaced_();
237 sink.text( ", suggested version: " );
238 sink.monospaced();
239 sink.text( suggestedVersion.toString() );
240 }
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000241 sink.monospaced_();
242 sink.text( ")" );
243 }
244 }
245
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000246 @Override
247 protected void startDiff( final Object context,
248 int depth,
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000249 String type,
250 String name,
251 String delta,
252 String shortDelta )
253 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000254 final Context ctx = (Context)context;
255 final Sink sink = ctx.sink;
256
257 if ( ctx.currentDepth < depth )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000258 {
259 sink.list();
260 }
261
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000262 ctx.currentDepth = depth;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000263
264 sink.listItem();
265 sink.figure();
266 sink.figureGraphics( "images/baseline/" + type + ".gif" );
267 sink.figure_();
268 sink.text( " " );
269
270 sink.monospaced();
271 sink.text( name );
272 sink.monospaced_();
273
274 sink.text( " " );
275
276 sink.italic();
277 sink.text( delta );
278 sink.italic_();
279 }
280
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000281 @Override
282 protected void endDiff( final Object context, int depth )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000283 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000284 final Context ctx = (Context)context;
285 final Sink sink = ctx.sink;
286
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000287 sink.listItem_();
288
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000289 if ( ctx.currentDepth > depth )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000290 {
291 sink.list_();
292 }
293
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000294 ctx.currentDepth = depth;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000295 }
296
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000297 @Override
298 protected void endPackage(final Object context)
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000299 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000300 final Context ctx = (Context)context;
301 final Sink sink = ctx.sink;
302 if ( ctx.currentDepth > 0 )
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000303 {
304 sink.list_();
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000305 ctx.currentDepth = 0;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000306 }
307
308 sink.listItem_();
309 sink.list_();
310 }
311
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000312 @Override
313 protected void endBaseline(final Object context)
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000314 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000315 final Context ctx = (Context)context;
316 ctx.sink.body_();
317 ctx.sink.flush();
318 ctx.sink.close();
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000319 }
320
321 // MavenReport methods
322
323 public boolean canGenerateReport()
324 {
325 return !skip && outputDirectory != null;
326 }
327
328 public void generate( @SuppressWarnings( "deprecation" ) org.codehaus.doxia.sink.Sink sink, Locale locale )
329 throws MavenReportException
330 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000331 final Context ctx = new Context();
332 ctx.sink = sink;
333 ctx.locale = locale;
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000334
335 try
336 {
Carsten Ziegeler3fa064f2015-03-02 10:40:51 +0000337 execute(ctx);
Carsten Ziegeler70dbafd2014-05-14 09:16:49 +0000338 }
339 catch ( Exception e )
340 {
341 getLog().warn( "An error occurred while producing the report page, see nested exceptions", e );
342 }
343 }
344
345 public String getCategoryName()
346 {
347 return MavenReport.CATEGORY_PROJECT_REPORTS;
348 }
349
350 public String getDescription( Locale locale )
351 {
352 return getBundle( locale ).getString( "report.baseline.description" );
353 }
354
355 public String getName( Locale locale )
356 {
357 return getBundle( locale ).getString( "report.baseline.name" );
358 }
359
360 private ResourceBundle getBundle( Locale locale )
361 {
362 return ResourceBundle.getBundle( "baseline-report", locale, getClass().getClassLoader() );
363 }
364
365 public String getOutputName()
366 {
367 return "baseline-report";
368 }
369
370 public File getReportOutputDirectory()
371 {
372 return outputDirectory;
373 }
374
375 public boolean isExternalReport()
376 {
377 return false;
378 }
379
380 public void setReportOutputDirectory( File outputDirectory )
381 {
382 this.outputDirectory = outputDirectory;
383 }
384
385}