    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.FileWriter;
    23  import java.io.IOException;
    24  import java.util.Map;
    25  import java.util.Map.Entry;
    26
    27  import org.codehaus.plexus.util.IOUtil;
    28  import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;
    29
    30  /**
    31   * BND Baseline check between two bundles.
    32   *
    33   * @goal baseline
    34   * @phase verify
    35   * @threadSafe true
    36   * @since 2.4.1
    37   */
    38  public final class BaselinePlugin
    39      extends AbstractBaselinePlugin
    40  {
    41
    42      private static final String TABLE_PATTERN = "%s %-50s %-10s %-10s %-10s %-10s %-10s";
    43
    44      /**
    45       * An XML output file to render to <code>${project.build.directory}/baseline.xml</code>.
    46       *
    47       * @parameter expression="${project.build.directory}/baseline.xml"
    48       */
    49      private File xmlOutputFile;
    50
    51      /**
    52       * Whether to log the results to the console or not, true by default.
    53       *
    54       * @parameter expression="${logResults}" default-value="true"
    55       */
    56      private boolean logResults;
    57
    58      private FileWriter xmlFileWriter;
    59
    60      private PrettyPrintXMLWriter xmlWriter;
    61
    62      protected void init()
    63      {
    64          if ( xmlOutputFile != null )
    65          {
    66              xmlOutputFile.getParentFile().mkdirs();
    67              try
    68              {
    69                  xmlFileWriter = new FileWriter( xmlOutputFile );
    70                  xmlWriter = new PrettyPrintXMLWriter( xmlFileWriter );
    71              }
    72              catch ( IOException e )
    73              {
    74                  getLog().warn( "No XML report will be produced, cannot write data to " + xmlOutputFile, e );
    75              }
    76          }
    77      }
    78
    79      protected void startBaseline( String generationDate,
    80                                    String bundleName,
    81                                    String currentVersion,
    82                                    String previousVersion )
    83      {
    84          if ( isLoggingResults() )
    85          {
    86              log( "Baseline Report - Generated by Apache Felix Maven Bundle Plugin on %s based on Bnd - see http://www.aqute.biz/Bnd/Bnd",
    87                   generationDate );
    88              log( "Comparing bundle %s version %s to version %s", bundleName, currentVersion, previousVersion );
    89              log( "" );
    90              log( TABLE_PATTERN,
    91                   " ",
    92                   "PACKAGE_NAME",
    93                   "DELTA",
    94                   "CUR_VER",
    95                   "BASE_VER",
    96                   "REC_VER",
    97                   "WARNINGS",
    98                   "ATTRIBUTES" );
    99              log( TABLE_PATTERN,
    100                  "=",
    101                  "==================================================",
    102                  "==========",
    103                  "==========",
    104                  "==========",
    105                  "==========",
    106                  "==========",
    107                  "==========" );
    108         }
    109
    110         if ( isProducingXml() )
    111         {
    112             xmlWriter.startElement( "baseline" );
    113             xmlWriter.addAttribute( "version", "1.0.0" );
    114             xmlWriter.addAttribute( "vendor", "The Apache Software Foundation" );
    115             xmlWriter.addAttribute( "vendorURL", "http://www.apache.org/" );
    116             xmlWriter.addAttribute( "generator", "Apache Felix Maven Bundle Plugin" );
    117             xmlWriter.addAttribute( "generatorURL", "http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html" );
    118             xmlWriter.addAttribute( "analyzer", "Bnd" );
    119             xmlWriter.addAttribute( "analyzerURL", "http://www.aqute.biz/Bnd/Bnd" );
    120             xmlWriter.addAttribute( "generatedOn", generationDate );
    121             xmlWriter.addAttribute( "bundleName", bundleName );
    122             xmlWriter.addAttribute( "currentVersion", currentVersion );
    123             xmlWriter.addAttribute( "previousVersion", previousVersion );
    124         }
    125     }
    126
    127     protected void startPackage( boolean mismatch,
    128                                  String name,
    129                                  String shortDelta,
    130                                  String delta,
    131                                  String newerVersion,
    132                                  String olderVersion,
    133                                  String suggestedVersion,
    134                                  DiffMessage diffMessage,
    135                                  Map<String,String> attributes )
    136     {
    137         if ( isLoggingResults() )
    138         {
    139             log( TABLE_PATTERN,
    140                  mismatch ? '*' : shortDelta,
    141                  name,
    142                  delta,
    143                  newerVersion,
    144                  olderVersion,
    145                  suggestedVersion,
    146                  diffMessage != null ? diffMessage : '-',
    147                  attributes );
    148         }
    149
    150         if ( isProducingXml() )
    151         {
    152             xmlWriter.startElement( "package" );
    153             xmlWriter.addAttribute( "name", name );
    154             xmlWriter.addAttribute( "delta", delta );
    155             simpleElement( "mismatch", String.valueOf( mismatch ) );
    156             simpleElement( "newerVersion", newerVersion );
    157             simpleElement( "olderVersion", olderVersion );
    158             simpleElement( "suggestedVersion", suggestedVersion );
    159
    160             if ( diffMessage != null )
    161             {
    162                 simpleElement( diffMessage.getType().name(), diffMessage.getMessage() );
    163             }
    164
    165             xmlWriter.startElement( "attributes" );
    166             if (attributes != null)
    167             {
    168                 for (Entry<String, String> attribute : attributes.entrySet())
    169                 {
    170                     String attributeName = attribute.getKey();
    171                     if (':' == attributeName.charAt(attributeName.length() - 1))
    172                     {
    173                         attributeName = attributeName.substring(0, attributeName.length() - 1);
    174                     }
    175                     String attributeValue = attribute.getValue();
    176
    177                     xmlWriter.startElement(attributeName);
    178                     xmlWriter.writeText(attributeValue);
    179                     xmlWriter.endElement();
    180                 }
    181             }
    182             xmlWriter.endElement();
    183         }
    184     }
    185
    186     protected void startDiff( int depth, String type, String name, String delta, String shortDelta )
    187     {
    188         if ( isLoggingResults() )
    189         {
    190             log( "%-" + (depth * 4) + "s %s %s %s",
    191                  "",
    192                  shortDelta,
    193                  type,
    194                  name );
    195         }
    196
    197         if ( isProducingXml() )
    198         {
    199             xmlWriter.startElement( type );
    200             xmlWriter.addAttribute( "name", name );
    201             xmlWriter.addAttribute( "delta", delta );
    202         }
    203     }
    204
    205     protected void endDiff( int depth )
    206     {
    207         if ( isProducingXml() )
    208         {
    209             xmlWriter.endElement();
    210         }
    211     }
    212
    213     protected void endPackage()
    214     {
    215         if ( isLoggingResults() )
    216         {
    217             log( "-----------------------------------------------------------------------------------------------------------" );
    218         }
    219
    220         if ( isProducingXml() )
    221         {
    222             xmlWriter.endElement();
    223         }
    224     }
    225
    226     protected void endBaseline()
    227     {
    228         if ( xmlWriter != null )
    229         {
    230             xmlWriter.endElement();
    231             IOUtil.close( xmlFileWriter );
    232         }
    233     }
    234
    235     private boolean isProducingXml()
    236     {
    237         return xmlFileWriter!= null && xmlWriter != null;
    238     }
    239
    240     private boolean isLoggingResults()
    241     {
    242         return logResults && getLog().isInfoEnabled();
    243     }
    244
    245     private void log( String format, Object...args )
    246     {
    247         getLog().info( String.format( format, args ) );
    248     }
    249
    250     private void simpleElement( String name, String value )
    251     {
    252         xmlWriter.startElement( name );
    253         xmlWriter.writeText( value );
    254         xmlWriter.endElement();
    255     }
    256
    257 }