Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 789   Methods: 22
NCLOC: 377   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
Extension.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2002 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 package org.apache.tools.ant.taskdefs.optional.extension;
 55   
 
 56   
 import java.util.ArrayList;
 57   
 import java.util.Iterator;
 58   
 import java.util.Map;
 59   
 import java.util.StringTokenizer;
 60   
 import java.util.jar.Attributes;
 61   
 import java.util.jar.Manifest;
 62   
 
 63   
 /**
 64   
  * <p>Utility class that represents either an available "Optional Package"
 65   
  * (formerly known as "Standard Extension") as described in the manifest
 66   
  * of a JAR file, or the requirement for such an optional package.</p>
 67   
  *
 68   
  * <p>For more information about optional packages, see the document
 69   
  * <em>Optional Package Versioning</em> in the documentation bundle for your
 70   
  * Java2 Standard Edition package, in file
 71   
  * <code>guide/extensions/versioning.html</code>.</p>
 72   
  *
 73   
  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 74   
  *  This file is from excalibur.extension package. Dont edit this file
 75   
  * directly as there is no unit tests to make sure it is operational
 76   
  * in ant. Edit file in excalibur and run tests there before changing
 77   
  * ants file.
 78   
  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 79   
  *
 80   
  * @author <a href="mailto:craigmcc@apache.org">Craig R. McClanahan</a>
 81   
  * @author <a href="mailto:peter@apache.org">Peter Donald</a>
 82   
  * @version $Revision: 1.5 $ $Date: 2003/02/10 14:14:03 $
 83   
  */
 84   
 public final class Extension
 85   
 {
 86   
     /**
 87   
      * Manifest Attribute Name object for EXTENSION_LIST.
 88   
      * @see Attributes.Name#EXTENSION_LIST
 89   
      */
 90   
     public static final Attributes.Name EXTENSION_LIST =
 91   
         new Attributes.Name( "Extension-List" );//Attributes.Name.EXTENSION_LIST;
 92   
 
 93   
     /**
 94   
      * <code>Name</code> object for <code>Optional-Extension-List</code>
 95   
      * manifest attribute used for declaring optional dependencies on
 96   
      * installed extensions. Note that the dependencies declared by this method
 97   
      * are not required for the library to operate but if present will be used.
 98   
      * It is NOT part of the official "Optional Package" specification.
 99   
      *
 100   
      * @see <a href="http://java.sun.com/j2se/1.3/docs/guide/extensions/spec.html#dependnecy">
 101   
      *      Installed extension dependency</a>
 102   
      */
 103   
     public static final Attributes.Name OPTIONAL_EXTENSION_LIST =
 104   
         new Attributes.Name( "Optional-Extension-List" );
 105   
 
 106   
     /**
 107   
      * Manifest Attribute Name object for EXTENSION_NAME.
 108   
      * @see Attributes.Name#EXTENSION_NAME
 109   
      */
 110   
     public static final Attributes.Name EXTENSION_NAME =
 111   
         new Attributes.Name( "Extension-Name" );//Attributes.Name.EXTENSION_NAME;
 112   
     /**
 113   
      * Manifest Attribute Name object for SPECIFICATION_VERSION.
 114   
      * @see Attributes.Name#SPECIFICATION_VERSION
 115   
      */
 116   
     public static final Attributes.Name SPECIFICATION_VERSION = Attributes.Name.SPECIFICATION_VERSION;
 117   
 
 118   
     /**
 119   
      * Manifest Attribute Name object for SPECIFICATION_VENDOR.
 120   
      * @see Attributes.Name#SPECIFICATION_VENDOR
 121   
      */
 122   
     public static final Attributes.Name SPECIFICATION_VENDOR = Attributes.Name.SPECIFICATION_VENDOR;
 123   
 
 124   
     /**
 125   
      * Manifest Attribute Name object for IMPLEMENTATION_VERSION.
 126   
      * @see Attributes.Name#IMPLEMENTATION_VERSION
 127   
      */
 128   
     public static final Attributes.Name IMPLEMENTATION_VERSION = Attributes.Name.IMPLEMENTATION_VERSION;
 129   
 
 130   
     /**
 131   
      * Manifest Attribute Name object for IMPLEMENTATION_VENDOR.
 132   
      * @see Attributes.Name#IMPLEMENTATION_VENDOR
 133   
      */
 134   
     public static final Attributes.Name IMPLEMENTATION_VENDOR = Attributes.Name.IMPLEMENTATION_VENDOR;
 135   
 
 136   
     /**
 137   
      * Manifest Attribute Name object for IMPLEMENTATION_URL.
 138   
      * @see Attributes.Name#IMPLEMENTATION_URL
 139   
      */
 140   
     public static final Attributes.Name IMPLEMENTATION_URL =
 141   
         new Attributes.Name( "Implementation-URL" );//Attributes.Name.IMPLEMENTATION_URL;
 142   
 
 143   
     /**
 144   
      * Manifest Attribute Name object for IMPLEMENTATION_VENDOR_ID.
 145   
      * @see Attributes.Name#IMPLEMENTATION_VENDOR_ID
 146   
      */
 147   
     public static final Attributes.Name IMPLEMENTATION_VENDOR_ID =
 148   
         new Attributes.Name( "Implementation-Vendor-Id" );//Attributes.Name.IMPLEMENTATION_VENDOR_ID;
 149   
 
 150   
     /**
 151   
      * Enum indicating that extension is compatible with other extension.
 152   
      */
 153   
     public static final Compatibility COMPATIBLE =
 154   
         new Compatibility( "COMPATIBLE" );
 155   
 
 156   
     /**
 157   
      * Enum indicating that extension requires an upgrade
 158   
      * of specification to be compatible with other extension.
 159   
      */
 160   
     public static final Compatibility REQUIRE_SPECIFICATION_UPGRADE =
 161   
         new Compatibility( "REQUIRE_SPECIFICATION_UPGRADE" );
 162   
 
 163   
     /**
 164   
      * Enum indicating that extension requires a vendor
 165   
      * switch to be compatible with other extension.
 166   
      */
 167   
     public static final Compatibility REQUIRE_VENDOR_SWITCH =
 168   
         new Compatibility( "REQUIRE_VENDOR_SWITCH" );
 169   
 
 170   
     /**
 171   
      * Enum indicating that extension requires an upgrade
 172   
      * of implementation to be compatible with other extension.
 173   
      */
 174   
     public static final Compatibility REQUIRE_IMPLEMENTATION_UPGRADE =
 175   
         new Compatibility( "REQUIRE_IMPLEMENTATION_UPGRADE" );
 176   
 
 177   
     /**
 178   
      * Enum indicating that extension is incompatible with
 179   
      * other extension in ways other than other enums
 180   
      * indicate). ie For example the other extension may have
 181   
      * a different ID.
 182   
      */
 183   
     public static final Compatibility INCOMPATIBLE =
 184   
         new Compatibility( "INCOMPATIBLE" );
 185   
 
 186   
     /**
 187   
      * The name of the optional package being made available, or required.
 188   
      */
 189   
     private String m_extensionName;
 190   
 
 191   
     /**
 192   
      * The version number (dotted decimal notation) of the specification
 193   
      * to which this optional package conforms.
 194   
      */
 195   
     private DeweyDecimal m_specificationVersion;
 196   
 
 197   
     /**
 198   
      * The name of the company or organization that originated the
 199   
      * specification to which this optional package conforms.
 200   
      */
 201   
     private String m_specificationVendor;
 202   
 
 203   
     /**
 204   
      * The unique identifier of the company that produced the optional
 205   
      * package contained in this JAR file.
 206   
      */
 207   
     private String m_implementationVendorID;
 208   
 
 209   
     /**
 210   
      * The name of the company or organization that produced this
 211   
      * implementation of this optional package.
 212   
      */
 213   
     private String m_implementationVendor;
 214   
 
 215   
     /**
 216   
      * The version number (dotted decimal notation) for this implementation
 217   
      * of the optional package.
 218   
      */
 219   
     private DeweyDecimal m_implementationVersion;
 220   
 
 221   
     /**
 222   
      * The URL from which the most recent version of this optional package
 223   
      * can be obtained if it is not already installed.
 224   
      */
 225   
     private String m_implementationURL;
 226   
 
 227   
     /**
 228   
      * Return an array of <code>Extension</code> objects representing optional
 229   
      * packages that are available in the JAR file associated with the
 230   
      * specified <code>Manifest</code>.  If there are no such optional
 231   
      * packages, a zero-length array is returned.
 232   
      *
 233   
      * @param manifest Manifest to be parsed
 234   
      * @return the "available" extensions in specified manifest
 235   
      */
 236  0
     public static Extension[] getAvailable( final Manifest manifest )
 237   
     {
 238  0
         if( null == manifest )
 239   
         {
 240  0
             return new Extension[ 0 ];
 241   
         }
 242   
 
 243  0
         final ArrayList results = new ArrayList();
 244   
 
 245  0
         final Attributes mainAttributes = manifest.getMainAttributes();
 246  0
         if( null != mainAttributes )
 247   
         {
 248  0
             final Extension extension = getExtension( "", mainAttributes );
 249  0
             if( null != extension )
 250   
             {
 251  0
                 results.add( extension );
 252   
             }
 253   
         }
 254   
 
 255  0
         final Map entries = manifest.getEntries();
 256  0
         final Iterator keys = entries.keySet().iterator();
 257  0
         while( keys.hasNext() )
 258   
         {
 259  0
             final String key = (String)keys.next();
 260  0
             final Attributes attributes = (Attributes)entries.get( key );
 261  0
             final Extension extension = getExtension( "", attributes );
 262  0
             if( null != extension )
 263   
             {
 264  0
                 results.add( extension );
 265   
             }
 266   
         }
 267   
 
 268  0
         return (Extension[])results.toArray( new Extension[ 0 ] );
 269   
     }
 270   
 
 271   
     /**
 272   
      * Return the set of <code>Extension</code> objects representing optional
 273   
      * packages that are required by the application contained in the JAR
 274   
      * file associated with the specified <code>Manifest</code>.  If there
 275   
      * are no such optional packages, a zero-length list is returned.
 276   
      *
 277   
      * @param manifest Manifest to be parsed
 278   
      * @return the dependencies that are specified in manifes
 279   
      */
 280  0
     public static Extension[] getRequired( final Manifest manifest )
 281   
     {
 282  0
         return getListed( manifest, EXTENSION_LIST );
 283   
     }
 284   
 
 285   
     /**
 286   
      * Return the set of <code>Extension</code> objects representing "Optional
 287   
      * Packages" that the application declares they will use if present. If
 288   
      * there are no such optional packages, a zero-length list is returned.
 289   
      *
 290   
      * @param manifest Manifest to be parsed
 291   
      * @return the optional dependencies that are specified in manifest
 292   
      */
 293  0
     public static Extension[] getOptions( final Manifest manifest )
 294   
     {
 295  0
         return getListed( manifest, OPTIONAL_EXTENSION_LIST );
 296   
     }
 297   
 
 298   
     /**
 299   
      * Add Extension to the specified manifest Attributes.
 300   
      *
 301   
      * @param attributes the attributes of manifest to add to
 302   
      * @param extension the extension
 303   
      */
 304  0
     public static void addExtension( final Extension extension,
 305   
                                      final Attributes attributes )
 306   
     {
 307  0
         addExtension( extension, "", attributes );
 308   
     }
 309   
 
 310   
     /**
 311   
      * Add Extension to the specified manifest Attributes.
 312   
      * Use the specified prefix so that dependencies can added
 313   
      * with a prefix such as "java3d-" etc.
 314   
      *
 315   
      * @param attributes the attributes of manifest to add to
 316   
      * @param extension the extension
 317   
      * @param prefix the name to prefix to extension
 318   
      */
 319  0
     public static void addExtension( final Extension extension,
 320   
                                      final String prefix,
 321   
                                      final Attributes attributes )
 322   
     {
 323  0
         attributes.putValue( prefix + EXTENSION_NAME,
 324   
                              extension.getExtensionName() );
 325   
 
 326  0
         final String specificationVendor = extension.getSpecificationVendor();
 327  0
         if( null != specificationVendor )
 328   
         {
 329  0
             attributes.putValue( prefix + SPECIFICATION_VENDOR,
 330   
                                  specificationVendor );
 331   
         }
 332   
 
 333  0
         final DeweyDecimal specificationVersion = extension.getSpecificationVersion();
 334  0
         if( null != specificationVersion )
 335   
         {
 336  0
             attributes.putValue( prefix + SPECIFICATION_VERSION,
 337   
                                  specificationVersion.toString() );
 338   
         }
 339   
 
 340  0
         final String implementationVendorID = extension.getImplementationVendorID();
 341  0
         if( null != implementationVendorID )
 342   
         {
 343  0
             attributes.putValue( prefix + IMPLEMENTATION_VENDOR_ID,
 344   
                                  implementationVendorID );
 345   
         }
 346   
 
 347  0
         final String implementationVendor = extension.getImplementationVendor();
 348  0
         if( null != implementationVendor )
 349   
         {
 350  0
             attributes.putValue( prefix + IMPLEMENTATION_VENDOR,
 351   
                                  implementationVendor );
 352   
         }
 353   
 
 354  0
         final DeweyDecimal implementationVersion = extension.getImplementationVersion();
 355  0
         if( null != implementationVersion )
 356   
         {
 357  0
             attributes.putValue( prefix + IMPLEMENTATION_VERSION,
 358   
                                  implementationVersion.toString() );
 359   
         }
 360   
 
 361  0
         final String implementationURL = extension.getImplementationURL();
 362  0
         if( null != implementationURL )
 363   
         {
 364  0
             attributes.putValue( prefix + IMPLEMENTATION_URL,
 365   
                                  implementationURL );
 366   
         }
 367   
     }
 368   
 
 369   
     /**
 370   
      * The constructor to create Extension object.
 371   
      * Note that every component is allowed to be specified
 372   
      * but only the extensionName is mandatory.
 373   
      *
 374   
      * @param extensionName the name of extension.
 375   
      * @param specificationVersion the specification Version of extension.
 376   
      * @param specificationVendor the specification Vendor of extension.
 377   
      * @param implementationVersion the implementation Version of extension.
 378   
      * @param implementationVendor the implementation Vendor of extension.
 379   
      * @param implementationVendorId the implementation VendorId of extension.
 380   
      * @param implementationURL the implementation URL of extension.
 381   
      */
 382  0
     public Extension( final String extensionName,
 383   
                       final String specificationVersion,
 384   
                       final String specificationVendor,
 385   
                       final String implementationVersion,
 386   
                       final String implementationVendor,
 387   
                       final String implementationVendorId,
 388   
                       final String implementationURL )
 389   
     {
 390  0
         m_extensionName = extensionName;
 391  0
         m_specificationVendor = specificationVendor;
 392   
 
 393  0
         if( null != specificationVersion )
 394   
         {
 395  0
             try
 396   
             {
 397  0
                 m_specificationVersion = new DeweyDecimal( specificationVersion );
 398   
             }
 399   
             catch( final NumberFormatException nfe )
 400   
             {
 401  0
                 final String error = "Bad specification version format '" + specificationVersion +
 402   
                     "' in '" + extensionName + "'. (Reason: " + nfe + ")";
 403  0
                 throw new IllegalArgumentException( error );
 404   
             }
 405   
         }
 406   
 
 407  0
         m_implementationURL = implementationURL;
 408  0
         m_implementationVendor = implementationVendor;
 409  0
         m_implementationVendorID = implementationVendorId;
 410   
 
 411  0
         if( null != implementationVersion )
 412   
         {
 413  0
             try
 414   
             {
 415  0
                 m_implementationVersion = new DeweyDecimal( implementationVersion );
 416   
             }
 417   
             catch( final NumberFormatException nfe )
 418   
             {
 419  0
                 final String error = "Bad implementation version format '" + implementationVersion +
 420   
                     "' in '" + extensionName + "'. (Reason: " + nfe + ")";
 421  0
                 throw new IllegalArgumentException( error );
 422   
             }
 423   
         }
 424   
 
 425  0
         if( null == m_extensionName )
 426   
         {
 427  0
             throw new NullPointerException( "extensionName property is null" );
 428   
         }
 429   
     }
 430   
 
 431   
     /**
 432   
      * Get the name of the extension.
 433   
      *
 434   
      * @return the name of the extension
 435   
      */
 436  0
     public String getExtensionName()
 437   
     {
 438  0
         return m_extensionName;
 439   
     }
 440   
 
 441   
     /**
 442   
      * Get the vendor of the extensions specification.
 443   
      *
 444   
      * @return the vendor of the extensions specification.
 445   
      */
 446  0
     public String getSpecificationVendor()
 447   
     {
 448  0
         return m_specificationVendor;
 449   
     }
 450   
 
 451   
     /**
 452   
      * Get the version of the extensions specification.
 453   
      *
 454   
      * @return the version of the extensions specification.
 455   
      */
 456  0
     public DeweyDecimal getSpecificationVersion()
 457   
     {
 458  0
         return m_specificationVersion;
 459   
     }
 460   
 
 461   
     /**
 462   
      * Get the url of the extensions implementation.
 463   
      *
 464   
      * @return the url of the extensions implementation.
 465   
      */
 466  0
     public String getImplementationURL()
 467   
     {
 468  0
         return m_implementationURL;
 469   
     }
 470   
 
 471   
     /**
 472   
      * Get the vendor of the extensions implementation.
 473   
      *
 474   
      * @return the vendor of the extensions implementation.
 475   
      */
 476  0
     public String getImplementationVendor()
 477   
     {
 478  0
         return m_implementationVendor;
 479   
     }
 480   
 
 481   
     /**
 482   
      * Get the vendorID of the extensions implementation.
 483   
      *
 484   
      * @return the vendorID of the extensions implementation.
 485   
      */
 486  0
     public String getImplementationVendorID()
 487   
     {
 488  0
         return m_implementationVendorID;
 489   
     }
 490   
 
 491   
     /**
 492   
      * Get the version of the extensions implementation.
 493   
      *
 494   
      * @return the version of the extensions implementation.
 495   
      */
 496  0
     public DeweyDecimal getImplementationVersion()
 497   
     {
 498  0
         return m_implementationVersion;
 499   
     }
 500   
 
 501   
     /**
 502   
      * Return a Compatibility enum indicating the relationship of this
 503   
      * <code>Extension</code> with the specified <code>Extension</code>.
 504   
      *
 505   
      * @param required Description of the required optional package
 506   
      * @return the enum indicating the compatibility (or lack thereof)
 507   
      *         of specifed extension
 508   
      */
 509  0
     public Compatibility getCompatibilityWith( final Extension required )
 510   
     {
 511   
         // Extension Name must match
 512  0
         if( !m_extensionName.equals( required.getExtensionName() ) )
 513   
         {
 514  0
             return INCOMPATIBLE;
 515   
         }
 516   
 
 517   
         // Available specification version must be >= required
 518  0
         final DeweyDecimal specificationVersion = required.getSpecificationVersion();
 519  0
         if( null != specificationVersion )
 520   
         {
 521  0
             if( null == m_specificationVersion ||
 522   
                 !isCompatible( m_specificationVersion, specificationVersion ) )
 523   
             {
 524  0
                 return REQUIRE_SPECIFICATION_UPGRADE;
 525   
             }
 526   
         }
 527   
 
 528   
         // Implementation Vendor ID must match
 529  0
         final String implementationVendorId = required.getImplementationVendorID();
 530  0
         if( null != implementationVendorId )
 531   
         {
 532  0
             if( null == m_implementationVendorID ||
 533   
                 !m_implementationVendorID.equals( implementationVendorId ) )
 534   
             {
 535  0
                 return REQUIRE_VENDOR_SWITCH;
 536   
             }
 537   
         }
 538   
 
 539   
         // Implementation version must be >= required
 540  0
         final DeweyDecimal implementationVersion = required.getImplementationVersion();
 541  0
         if( null != implementationVersion )
 542   
         {
 543  0
             if( null == m_implementationVersion ||
 544   
                 !isCompatible( m_implementationVersion, implementationVersion ) )
 545   
             {
 546  0
                 return REQUIRE_IMPLEMENTATION_UPGRADE;
 547   
             }
 548   
         }
 549   
 
 550   
         // This available optional package satisfies the requirements
 551  0
         return COMPATIBLE;
 552   
     }
 553   
 
 554   
     /**
 555   
      * Return <code>true</code> if the specified <code>Extension</code>
 556   
      * (which represents an optional package required by an application)
 557   
      * is satisfied by this <code>Extension</code> (which represents an
 558   
      * optional package that is already installed.  Otherwise, return
 559   
      * <code>false</code>.
 560   
      *
 561   
      * @param required Description of the required optional package
 562   
      * @return true if the specified extension is compatible with this extension
 563   
      */
 564  0
     public boolean isCompatibleWith( final Extension required )
 565   
     {
 566  0
         return ( COMPATIBLE == getCompatibilityWith( required ) );
 567   
     }
 568   
 
 569   
     /**
 570   
      * Return a String representation of this object.
 571   
      *
 572   
      * @return string representation of object.
 573   
      */
 574  0
     public String toString()
 575   
     {
 576  0
         final String lineSeparator = System.getProperty( "line.separator" );
 577  0
         final String brace = ": ";
 578   
 
 579  0
         final StringBuffer sb = new StringBuffer( EXTENSION_NAME.toString() );
 580  0
         sb.append( brace );
 581  0
         sb.append( m_extensionName );
 582  0
         sb.append( lineSeparator );
 583   
 
 584  0
         if( null != m_specificationVersion )
 585   
         {
 586  0
             sb.append( SPECIFICATION_VERSION );
 587  0
             sb.append( brace );
 588  0
             sb.append( m_specificationVersion );
 589  0
             sb.append( lineSeparator );
 590   
         }
 591   
 
 592  0
         if( null != m_specificationVendor )
 593   
         {
 594  0
             sb.append( SPECIFICATION_VENDOR );
 595  0
             sb.append( brace );
 596  0
             sb.append( m_specificationVendor );
 597  0
             sb.append( lineSeparator );
 598   
         }
 599   
 
 600  0
         if( null != m_implementationVersion )
 601   
         {
 602  0
             sb.append( IMPLEMENTATION_VERSION );
 603  0
             sb.append( brace );
 604  0
             sb.append( m_implementationVersion );
 605  0
             sb.append( lineSeparator );
 606   
         }
 607   
 
 608  0
         if( null != m_implementationVendorID )
 609   
         {
 610  0
             sb.append( IMPLEMENTATION_VENDOR_ID );
 611  0
             sb.append( brace );
 612  0
             sb.append( m_implementationVendorID );
 613  0
             sb.append( lineSeparator );
 614   
         }
 615   
 
 616  0
         if( null != m_implementationVendor )
 617   
         {
 618  0
             sb.append( IMPLEMENTATION_VENDOR );
 619  0
             sb.append( brace );
 620  0
             sb.append( m_implementationVendor );
 621  0
             sb.append( lineSeparator );
 622   
         }
 623   
 
 624  0
         if( null != m_implementationURL )
 625   
         {
 626  0
             sb.append( IMPLEMENTATION_URL );
 627  0
             sb.append( brace );
 628  0
             sb.append( m_implementationURL );
 629  0
             sb.append( lineSeparator );
 630   
         }
 631   
 
 632  0
         return sb.toString();
 633   
     }
 634   
 
 635   
     /**
 636   
      * Return <code>true</code> if the first version number is greater than
 637   
      * or equal to the second; otherwise return <code>false</code>.
 638   
      *
 639   
      * @param first First version number (dotted decimal)
 640   
      * @param second Second version number (dotted decimal)
 641   
      */
 642  0
     private boolean isCompatible( final DeweyDecimal first, final DeweyDecimal second )
 643   
     {
 644  0
         return first.isGreaterThanOrEqual( second );
 645   
     }
 646   
 
 647   
     /**
 648   
      * Retrieve all the extensions listed under a particular key
 649   
      * (Usually EXTENSION_LIST or OPTIONAL_EXTENSION_LIST).
 650   
      *
 651   
      * @param manifest the manifest to extract extensions from
 652   
      * @param listKey the key used to get list (Usually
 653   
      *        EXTENSION_LIST or OPTIONAL_EXTENSION_LIST)
 654   
      * @return the list of listed extensions
 655   
      */
 656  0
     private static Extension[] getListed( final Manifest manifest,
 657   
                                           final Attributes.Name listKey )
 658   
     {
 659  0
         final ArrayList results = new ArrayList();
 660  0
         final Attributes mainAttributes = manifest.getMainAttributes();
 661   
 
 662  0
         if( null != mainAttributes )
 663   
         {
 664  0
             getExtension( mainAttributes, results, listKey );
 665   
         }
 666   
 
 667  0
         final Map entries = manifest.getEntries();
 668  0
         final Iterator keys = entries.keySet().iterator();
 669  0
         while( keys.hasNext() )
 670   
         {
 671  0
             final String key = (String)keys.next();
 672  0
             final Attributes attributes = (Attributes)entries.get( key );
 673  0
             getExtension( attributes, results, listKey );
 674   
         }
 675   
 
 676  0
         return (Extension[])results.toArray( new Extension[ 0 ] );
 677   
     }
 678   
 
 679   
     /**
 680   
      * Add required optional packages defined in the specified attributes entry, if any.
 681   
      *
 682   
      * @param attributes Attributes to be parsed
 683   
      * @param required list to add required optional packages to
 684   
      * @param listKey the key to use to lookup list, usually EXTENSION_LIST
 685   
      *    or OPTIONAL_EXTENSION_LIST
 686   
      */
 687  0
     private static void getExtension( final Attributes attributes,
 688   
                                      final ArrayList required,
 689   
                                      final Attributes.Name listKey )
 690   
     {
 691  0
         final String names = attributes.getValue( listKey );
 692  0
         if( null == names )
 693   
         {
 694  0
             return;
 695   
         }
 696   
 
 697  0
         final String[] extentions = split( names, " " );
 698  0
         for( int i = 0; i < extentions.length; i++ )
 699   
         {
 700  0
             final String prefix = extentions[ i ] + "-";
 701  0
             final Extension extension = getExtension( prefix, attributes );
 702   
 
 703  0
             if( null != extension )
 704   
             {
 705  0
                 required.add( extension );
 706   
             }
 707   
         }
 708   
     }
 709   
 
 710   
     /**
 711   
      * Splits the string on every token into an array of strings.
 712   
      *
 713   
      * @param string the string
 714   
      * @param onToken the token
 715   
      * @return the resultant array
 716   
      */
 717  0
     private static final String[] split( final String string, final String onToken )
 718   
     {
 719  0
         final StringTokenizer tokenizer = new StringTokenizer( string, onToken );
 720  0
         final String[] result = new String[ tokenizer.countTokens() ];
 721   
 
 722  0
         for( int i = 0; i < result.length; i++ )
 723   
         {
 724  0
             result[ i ] = tokenizer.nextToken();
 725   
         }
 726   
 
 727  0
         return result;
 728   
     }
 729   
 
 730   
     /**
 731   
      * Extract an Extension from Attributes.
 732   
      * Prefix indicates the prefix checked for each string.
 733   
      * Usually the prefix is <em>"&lt;extension&gt;-"</em> if looking for a
 734   
      * <b>Required</b> extension. If you are looking for an <b>Available</b> extension
 735   
      * then the prefix is <em>""</em>.
 736   
      *
 737   
      * @param prefix the prefix for each attribute name
 738   
      * @param attributes Attributes to searched
 739   
      * @return the new Extension object, or null
 740   
      */
 741  0
     private static Extension getExtension( final String prefix, final Attributes attributes )
 742   
     {
 743   
         //WARNING: We trim the values of all the attributes because
 744   
         //Some extension declarations are badly defined (ie have spaces
 745   
         //after version or vendorID)
 746  0
         final String nameKey = prefix + EXTENSION_NAME;
 747  0
         final String name = getTrimmedString( attributes.getValue( nameKey ) );
 748  0
         if( null == name )
 749   
         {
 750  0
             return null;
 751   
         }
 752   
 
 753  0
         final String specVendorKey = prefix + SPECIFICATION_VENDOR;
 754  0
         final String specVendor = getTrimmedString( attributes.getValue( specVendorKey ) );
 755  0
         final String specVersionKey = prefix + SPECIFICATION_VERSION;
 756  0
         final String specVersion = getTrimmedString( attributes.getValue( specVersionKey ) );
 757   
 
 758  0
         final String impVersionKey = prefix + IMPLEMENTATION_VERSION;
 759  0
         final String impVersion = getTrimmedString( attributes.getValue( impVersionKey ) );
 760  0
         final String impVendorKey = prefix + IMPLEMENTATION_VENDOR;
 761  0
         final String impVendor = getTrimmedString( attributes.getValue( impVendorKey ) );
 762  0
         final String impVendorIDKey = prefix + IMPLEMENTATION_VENDOR_ID;
 763  0
         final String impVendorId = getTrimmedString( attributes.getValue( impVendorIDKey ) );
 764  0
         final String impURLKey = prefix + IMPLEMENTATION_URL;
 765  0
         final String impURL = getTrimmedString( attributes.getValue( impURLKey ) );
 766   
 
 767  0
         return new Extension( name, specVersion, specVendor, impVersion,
 768   
                               impVendor, impVendorId, impURL );
 769   
     }
 770   
 
 771   
     /**
 772   
      * Trim the supplied string if the string is non-null
 773   
      *
 774   
      * @param value the string to trim or null
 775   
      * @return the trimmed string or null
 776   
      */
 777  0
     private static String getTrimmedString( final String value )
 778   
     {
 779  0
         if( null == value )
 780   
         {
 781  0
             return null;
 782   
         }
 783   
         else
 784   
         {
 785  0
             return value.trim();
 786   
         }
 787   
     }
 788   
 }
 789