KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > extension > Extension


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.excalibur.extension;
9
10 import java.util.ArrayList JavaDoc;
11 import java.util.Iterator JavaDoc;
12 import java.util.List JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.StringTokenizer JavaDoc;
15 import java.util.jar.Attributes.Name;
16 import java.util.jar.Attributes JavaDoc;
17 import java.util.jar.Manifest JavaDoc;
18 import org.apache.avalon.excalibur.util.DeweyDecimal;
19 import org.apache.avalon.excalibur.util.StringUtil;
20
21 /**
22  * <p>Utility class that represents either an available "Optional Package"
23  * (formerly known as "Standard Extension") as described in the manifest
24  * of a JAR file, or the requirement for such an optional package.</p>
25  *
26  * <p>For more information about optional packages, see the document
27  * <em>Optional Package Versioning</em> in the documentation bundle for your
28  * Java2 Standard Edition package, in file
29  * <code>guide/extensions/versioning.html</code>.</p>
30  *
31  * @author <a HREF="mailto:craigmcc@apache.org">Craig R. McClanahan</a>
32  * @author <a HREF="mailto:peter@apache.org">Peter Donald</a>
33  * @version $Revision: 1.8 $ $Date: 2001/12/11 09:53:34 $
34  */

35 public final class Extension
36 {
37     public static final Compatability COMPATIBLE =
38         new Compatability( "COMPATIBLE" );
39     public static final Compatability REQUIRE_SPECIFICATION_UPGRADE =
40         new Compatability( "REQUIRE_SPECIFICATION_UPGRADE" );
41     public static final Compatability REQUIRE_VENDOR_SWITCH =
42         new Compatability( "REQUIRE_VENDOR_SWITCH" );
43     public static final Compatability REQUIRE_IMPLEMENTATION_UPGRADE =
44         new Compatability( "REQUIRE_IMPLEMENTATION_UPGRADE" );
45     public static final Compatability INCOMPATIBLE =
46         new Compatability( "INCOMPATIBLE" );
47
48     /**
49      * The name of the optional package being made available, or required.
50      */

51     private String JavaDoc m_extensionName;
52
53     /**
54      * The version number (dotted decimal notation) of the specification
55      * to which this optional package conforms.
56      */

57     private DeweyDecimal m_specificationVersion;
58
59     /**
60      * The name of the company or organization that originated the
61      * specification to which this optional package conforms.
62      */

63     private String JavaDoc m_specificationVendor;
64
65     /**
66      * The URL from which the most recent version of this optional package
67      * can be obtained if it is not already installed.
68      */

69     private String JavaDoc m_implementationURL;
70
71     /**
72      * The name of the company or organization that produced this
73      * implementation of this optional package.
74      */

75     private String JavaDoc m_implementationVendor;
76
77     /**
78      * The unique identifier of the company that produced the optional
79      * package contained in this JAR file.
80      */

81     private String JavaDoc m_implementationVendorId;
82
83     /**
84      * The version number (dotted decimal notation) for this implementation
85      * of the optional package.
86      */

87     private DeweyDecimal m_implementationVersion;
88
89
90     /**
91      * Return an array of <code>Extension</code> objects representing optional
92      * packages that are available in the JAR file associated with the
93      * specified <code>Manifest</code>. If there are no such optional
94      * packages, a zero-length array is returned.
95      *
96      * @param manifest Manifest to be parsed
97      */

98     public static Extension[] getAvailable( final Manifest JavaDoc manifest )
99     {
100         if( null == manifest ) return new Extension[ 0 ];
101
102         final ArrayList JavaDoc results = new ArrayList JavaDoc();
103
104         final Attributes JavaDoc mainAttributes = manifest.getMainAttributes();
105         if( null != mainAttributes )
106         {
107             final Extension extension = getExtension( "", mainAttributes );
108             if( null != extension ) results.add( extension );
109         }
110
111         final Map JavaDoc entries = manifest.getEntries();
112         final Iterator JavaDoc keys = entries.keySet().iterator();
113         while( keys.hasNext() )
114         {
115             final String JavaDoc key = (String JavaDoc)keys.next();
116             final Attributes JavaDoc attributes = (Attributes JavaDoc)entries.get( key );
117             final Extension extension = getExtension( "", attributes );
118             if( null != extension ) results.add( extension );
119         }
120
121         return (Extension[])results.toArray( new Extension[ 0 ] );
122     }
123
124     /**
125      * Return the set of <code>Extension</code> objects representing optional
126      * packages that are required by the application contained in the JAR
127      * file associated with the specified <code>Manifest</code>. If there
128      * are no such optional packages, a zero-length list is returned.
129      *
130      * @param manifest Manifest to be parsed
131      */

132     public static Extension[] getRequired( final Manifest JavaDoc manifest )
133     {
134         final ArrayList JavaDoc results = new ArrayList JavaDoc();
135         final Attributes JavaDoc mainAttributes = manifest.getMainAttributes();
136
137         if( null != mainAttributes )
138         {
139             getRequired( mainAttributes, results );
140         }
141
142         final Map JavaDoc entries = manifest.getEntries();
143         final Iterator JavaDoc keys = entries.keySet().iterator();
144         while( keys.hasNext() )
145         {
146             final String JavaDoc key = (String JavaDoc)keys.next();
147             final Attributes JavaDoc attributes = (Attributes JavaDoc)entries.get( key );
148             getRequired( mainAttributes, results );
149         }
150
151         return (Extension[])results.toArray( new Extension[ 0 ] );
152     }
153
154     /**
155      * Add required optional packages defined in the specified attributes entry, if any.
156      *
157      * @param attributes Attributes to be parsed
158      * @param required list to add required optional packages to
159      */

160     private static void getRequired( final Attributes JavaDoc attributes,
161                                      final ArrayList JavaDoc required )
162     {
163         final String JavaDoc names = attributes.getValue( Name.EXTENSION_LIST );
164         if( null == names ) return;
165
166         final String JavaDoc[] extentions = StringUtil.split( names, " " );
167         for( int i = 0; i < extentions.length; i++ )
168         {
169             final String JavaDoc prefix = extentions[ i ] + "-";
170             final Extension extension = getExtension( prefix, attributes );
171
172             if( null != extension )
173             {
174                 required.add( extension );
175             }
176         }
177     }
178
179     /**
180      * Extract an Extension from Attributes.
181      * Prefix indicates the prefix checked for each string.
182      * Usually the prefix is <em>"&lt;extension&gt;-"</em> if looking for a
183      * <b>Required</b> extension. If you are looking for an <b>Available</b> extension
184      * then the prefix is <em>""</em>.
185      *
186      * @param prefix the prefix for each attribute name
187      * @param attributes Attributes to searched
188      * @return the new Extension object, or null
189      */

190     private static Extension getExtension( final String JavaDoc prefix, final Attributes JavaDoc attributes )
191     {
192         //WARNING: We trim the values of all the attributes because
193
//Some extension declarations are badly defined (ie have spaces
194
//after version or vendorID)
195
final String JavaDoc name = getTrimmedString( attributes.getValue( prefix + Name.EXTENSION_NAME ) );
196         if( null == name ) return null;
197
198         final String JavaDoc specVendor =
199             getTrimmedString( attributes.getValue( prefix + Name.SPECIFICATION_VENDOR ) );
200         final String JavaDoc specVersion =
201             getTrimmedString( attributes.getValue( prefix + Name.SPECIFICATION_VERSION ) );
202
203         final String JavaDoc impVersion =
204             getTrimmedString( attributes.getValue( prefix + Name.IMPLEMENTATION_VERSION ) );
205         final String JavaDoc impVendor =
206             getTrimmedString( attributes.getValue( prefix + Name.IMPLEMENTATION_VENDOR ) );
207         final String JavaDoc impVendorId =
208             getTrimmedString( attributes.getValue( prefix + Name.IMPLEMENTATION_VENDOR_ID ) );
209         final String JavaDoc impURL =
210             getTrimmedString( attributes.getValue( prefix + Name.IMPLEMENTATION_URL ) );
211
212         return new Extension( name, specVersion, specVendor, impVersion,
213                               impVendor, impVendorId, impURL );
214     }
215
216     private static String JavaDoc getTrimmedString( final String JavaDoc value )
217     {
218         if( null == value ) return null;
219         else
220         {
221             return value.trim();
222         }
223     }
224
225     /**
226      * The constructor to create Extension object.
227      * Note that every component is allowed to be specified
228      * but only the extensionName is mandatory.
229      *
230      * @param extensionName the name of extension.
231      * @param specificationVersion the specification Version of extension.
232      * @param specificationVendor the specification Vendor of extension.
233      * @param implementationVersion the implementation Version of extension.
234      * @param implementationVendor the implementation Vendor of extension.
235      * @param implementationVendorId the implementation VendorId of extension.
236      * @param implementationURL the implementation URL of extension.
237      */

238     public Extension( final String JavaDoc extensionName,
239                       final String JavaDoc specificationVersion,
240                       final String JavaDoc specificationVendor,
241                       final String JavaDoc implementationVersion,
242                       final String JavaDoc implementationVendor,
243                       final String JavaDoc implementationVendorId,
244                       final String JavaDoc implementationURL )
245     {
246         m_extensionName = extensionName;
247         m_specificationVendor = specificationVendor;
248
249         if( null != specificationVersion )
250         {
251             try
252             {
253                 m_specificationVersion = new DeweyDecimal( specificationVersion );
254             }
255             catch( NumberFormatException JavaDoc nfe )
256             {
257                 final String JavaDoc error = "Bad specification version format '" + specificationVersion +
258                     "' in '" + extensionName + "'. (Reason: " + nfe + ")";
259                 throw new IllegalArgumentException JavaDoc( error );
260             }
261         }
262
263         m_implementationURL = implementationURL;
264         m_implementationVendor = implementationVendor;
265         m_implementationVendorId = implementationVendorId;
266
267         if( null != implementationVersion )
268         {
269             try
270             {
271                 m_implementationVersion = new DeweyDecimal( implementationVersion );
272             }
273             catch( NumberFormatException JavaDoc nfe )
274             {
275                 final String JavaDoc error = "Bad implementation version format '" + implementationVersion +
276                     "' in '" + extensionName + "'. (Reason: " + nfe + ")";
277                 throw new IllegalArgumentException JavaDoc( error );
278             }
279         }
280
281         if( null == m_extensionName )
282         {
283             throw new NullPointerException JavaDoc( "extensionName property is null" );
284         }
285     }
286
287     public String JavaDoc getExtensionName()
288     {
289         return m_extensionName;
290     }
291
292     public String JavaDoc getSpecificationVendor()
293     {
294         return m_specificationVendor;
295     }
296
297     public DeweyDecimal getSpecificationVersion()
298     {
299         return m_specificationVersion;
300     }
301
302     public String JavaDoc getImplementationURL()
303     {
304         return m_implementationURL;
305     }
306
307     public String JavaDoc getImplementationVendor()
308     {
309         return m_implementationVendor;
310     }
311
312     public String JavaDoc getImplementationVendorId()
313     {
314         return m_implementationVendorId;
315     }
316
317     public DeweyDecimal getImplementationVersion()
318     {
319         return m_implementationVersion;
320     }
321
322
323     /**
324      * Return a Compatibility enum indicating the relationship of this
325      * <code>Extension</code> with the specified <code>Extension</code>.
326      *
327      * @param required Description of the required optional package
328      */

329     public Compatability getCompatibilityWith( final Extension required )
330     {
331         // Extension Name must match
332
if( false == m_extensionName.equals( required.getExtensionName() ) )
333         {
334             return INCOMPATIBLE;
335         }
336
337         // Available specification version must be >= required
338
final DeweyDecimal specificationVersion = required.getSpecificationVersion();
339         if( null != specificationVersion )
340         {
341             if( null == m_specificationVersion ||
342                 false == isCompatible( m_specificationVersion, specificationVersion ) )
343             {
344                 return REQUIRE_SPECIFICATION_UPGRADE;
345             }
346         }
347
348         // Implementation Vendor ID must match
349
final String JavaDoc implementationVendorId = required.getImplementationVendorId();
350         if( null != implementationVendorId )
351         {
352             if( null == m_implementationVendorId ||
353                 false == m_implementationVendorId.equals( implementationVendorId ) )
354             {
355                 return REQUIRE_VENDOR_SWITCH;
356             }
357         }
358
359         // Implementation version must be >= required
360
final DeweyDecimal implementationVersion = required.getImplementationVersion();
361         if( null != implementationVersion )
362         {
363             if( null == m_implementationVersion ||
364                 false == isCompatible( m_implementationVersion, implementationVersion ) )
365             {
366                 return REQUIRE_IMPLEMENTATION_UPGRADE;
367             }
368         }
369
370         // This available optional package satisfies the requirements
371
return COMPATIBLE;
372     }
373
374     /**
375      * Return <code>true</code> if the specified <code>Extension</code>
376      * (which represents an optional package required by an application)
377      * is satisfied by this <code>Extension</code> (which represents an
378      * optional package that is already installed. Otherwise, return
379      * <code>false</code>.
380      *
381      * @param required Description of the required optional package
382      */

383     public boolean isCompatibleWith( final Extension required )
384     {
385         return ( COMPATIBLE == getCompatibilityWith( required ) );
386     }
387
388     /**
389      * Return a String representation of this object.
390      */

391     public String JavaDoc toString()
392     {
393         final StringBuffer JavaDoc sb = new StringBuffer JavaDoc( "Extension[" );
394         sb.append( m_extensionName );
395
396         if( null != m_implementationURL )
397         {
398             sb.append( ", implementationURL=" );
399             sb.append( m_implementationURL );
400         }
401
402         if( null != m_implementationVendor )
403         {
404             sb.append( ", implementationVendor=" );
405             sb.append( m_implementationVendor );
406         }
407
408         if( null != m_implementationVendorId )
409         {
410             sb.append( ", implementationVendorId=" );
411             sb.append( m_implementationVendorId );
412         }
413
414         if( null != m_implementationVersion )
415         {
416             sb.append( ", implementationVersion=" );
417             sb.append( m_implementationVersion );
418         }
419
420         if( null != m_specificationVendor )
421         {
422             sb.append( ", specificationVendor=" );
423             sb.append( m_specificationVendor );
424         }
425
426         if( null != m_specificationVersion )
427         {
428             sb.append( ", specificationVersion=" );
429             sb.append( m_specificationVersion );
430         }
431
432         sb.append( "]" );
433
434         return sb.toString();
435     }
436
437     /**
438      * Return <code>true</code> if the first version number is greater than
439      * or equal to the second; otherwise return <code>false</code>.
440      *
441      * @param first First version number (dotted decimal)
442      * @param second Second version number (dotted decimal)
443      *
444      * @exception NumberFormatException on a malformed version number
445      */

446     private boolean isCompatible( final DeweyDecimal first, final DeweyDecimal second )
447     {
448         return first.isGreaterThanOrEqual( second );
449     }
450
451     public static final class Compatability
452     {
453         private final String JavaDoc m_name;
454
455         protected Compatability( final String JavaDoc name )
456         {
457             m_name = name;
458         }
459
460         public String JavaDoc toString()
461         {
462             return m_name;
463         }
464     }
465 }
466
Popular Tags