    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 }