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