KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > extension > Extension


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package org.apache.tools.ant.taskdefs.optional.extension;
19
20 import java.util.ArrayList JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.StringTokenizer JavaDoc;
24 import java.util.jar.Attributes JavaDoc;
25 import java.util.jar.Manifest JavaDoc;
26
27 import org.apache.tools.ant.util.StringUtils;
28
29 /**
30  * <p>Utility class that represents either an available "Optional Package"
31  * (formerly known as "Standard Extension") as described in the manifest
32  * of a JAR file, or the requirement for such an optional package.</p>
33  *
34  * <p>For more information about optional packages, see the document
35  * <em>Optional Package Versioning</em> in the documentation bundle for your
36  * Java2 Standard Edition package, in file
37  * <code>guide/extensions/versioning.html</code>.</p>
38  *
39  */

40 public final class Extension {
41     /**
42      * Manifest Attribute Name object for EXTENSION_LIST.
43      */

44     public static final Attributes.Name JavaDoc EXTENSION_LIST
45         = new Attributes.Name JavaDoc("Extension-List");
46
47     /**
48      * <code>Name</code> object for <code>Optional-Extension-List</code>
49      * manifest attribute used for declaring optional dependencies on
50      * installed extensions. Note that the dependencies declared by this method
51      * are not required for the library to operate but if present will be used.
52      * It is NOT part of the official "Optional Package" specification.
53      *
54      * @see <a HREF="http://java.sun.com/j2se/1.3/docs/guide/extensions/spec.html#dependnecy">
55      * Installed extension dependency</a>
56      */

57     public static final Attributes.Name JavaDoc OPTIONAL_EXTENSION_LIST
58         = new Attributes.Name JavaDoc("Optional-Extension-List");
59
60     /**
61      * Manifest Attribute Name object for EXTENSION_NAME.
62      */

63     public static final Attributes.Name JavaDoc EXTENSION_NAME =
64         new Attributes.Name JavaDoc("Extension-Name");
65     /**
66      * Manifest Attribute Name object for SPECIFICATION_VERSION.
67      */

68     public static final Attributes.Name JavaDoc SPECIFICATION_VERSION
69         = Attributes.Name.SPECIFICATION_VERSION;
70
71     /**
72      * Manifest Attribute Name object for SPECIFICATION_VENDOR.
73      */

74     public static final Attributes.Name JavaDoc SPECIFICATION_VENDOR
75         = Attributes.Name.SPECIFICATION_VENDOR;
76
77     /**
78      * Manifest Attribute Name object for IMPLEMENTATION_VERSION.
79      */

80     public static final Attributes.Name JavaDoc IMPLEMENTATION_VERSION
81         = Attributes.Name.IMPLEMENTATION_VERSION;
82
83     /**
84      * Manifest Attribute Name object for IMPLEMENTATION_VENDOR.
85      */

86     public static final Attributes.Name JavaDoc IMPLEMENTATION_VENDOR
87         = Attributes.Name.IMPLEMENTATION_VENDOR;
88
89     /**
90      * Manifest Attribute Name object for IMPLEMENTATION_URL.
91      */

92     public static final Attributes.Name JavaDoc IMPLEMENTATION_URL
93         = new Attributes.Name JavaDoc("Implementation-URL");
94
95     /**
96      * Manifest Attribute Name object for IMPLEMENTATION_VENDOR_ID.
97      */

98     public static final Attributes.Name JavaDoc IMPLEMENTATION_VENDOR_ID
99         = new Attributes.Name JavaDoc("Implementation-Vendor-Id");
100
101     /**
102      * Enum indicating that extension is compatible with other extension.
103      */

104     public static final Compatibility COMPATIBLE
105         = new Compatibility("COMPATIBLE");
106
107     /**
108      * Enum indicating that extension requires an upgrade
109      * of specification to be compatible with other extension.
110      */

111     public static final Compatibility REQUIRE_SPECIFICATION_UPGRADE
112         = new Compatibility("REQUIRE_SPECIFICATION_UPGRADE");
113
114     /**
115      * Enum indicating that extension requires a vendor
116      * switch to be compatible with other extension.
117      */

118     public static final Compatibility REQUIRE_VENDOR_SWITCH
119         = new Compatibility("REQUIRE_VENDOR_SWITCH");
120
121     /**
122      * Enum indicating that extension requires an upgrade
123      * of implementation to be compatible with other extension.
124      */

125     public static final Compatibility REQUIRE_IMPLEMENTATION_UPGRADE
126         = new Compatibility("REQUIRE_IMPLEMENTATION_UPGRADE");
127
128     /**
129      * Enum indicating that extension is incompatible with
130      * other extension in ways other than other enums
131      * indicate). For example the other extension may have
132      * a different ID.
133      */

134     public static final Compatibility INCOMPATIBLE
135         = new Compatibility("INCOMPATIBLE");
136
137     /**
138      * The name of the optional package being made available, or required.
139      */

140     private String JavaDoc extensionName;
141
142     /**
143      * The version number (dotted decimal notation) of the specification
144      * to which this optional package conforms.
145      */

146     private DeweyDecimal specificationVersion;
147
148     /**
149      * The name of the company or organization that originated the
150      * specification to which this optional package conforms.
151      */

152     private String JavaDoc specificationVendor;
153
154     /**
155      * The unique identifier of the company that produced the optional
156      * package contained in this JAR file.
157      */

158     private String JavaDoc implementationVendorID;
159
160     /**
161      * The name of the company or organization that produced this
162      * implementation of this optional package.
163      */

164     private String JavaDoc implementationVendor;
165
166     /**
167      * The version number (dotted decimal notation) for this implementation
168      * of the optional package.
169      */

170     private DeweyDecimal implementationVersion;
171
172     /**
173      * The URL from which the most recent version of this optional package
174      * can be obtained if it is not already installed.
175      */

176     private String JavaDoc implementationURL;
177
178     /**
179      * Return an array of <code>Extension</code> objects representing optional
180      * packages that are available in the JAR file associated with the
181      * specified <code>Manifest</code>. If there are no such optional
182      * packages, a zero-length array is returned.
183      *
184      * @param manifest Manifest to be parsed
185      * @return the "available" extensions in specified manifest
186      */

187     public static Extension[] getAvailable(final Manifest JavaDoc manifest) {
188         if (null == manifest) {
189             return new Extension[ 0 ];
190         }
191
192         final ArrayList JavaDoc results = new ArrayList JavaDoc();
193
194         final Attributes JavaDoc mainAttributes = manifest.getMainAttributes();
195         if (null != mainAttributes) {
196             final Extension extension = getExtension("", mainAttributes);
197             if (null != extension) {
198                 results.add(extension);
199             }
200         }
201
202         final Map JavaDoc entries = manifest.getEntries();
203         final Iterator JavaDoc keys = entries.keySet().iterator();
204         while (keys.hasNext()) {
205             final String JavaDoc key = (String JavaDoc) keys.next();
206             final Attributes JavaDoc attributes = (Attributes JavaDoc) entries.get(key);
207             final Extension extension = getExtension("", attributes);
208             if (null != extension) {
209                 results.add(extension);
210             }
211         }
212
213         return (Extension[]) results.toArray(new Extension[results.size()]);
214     }
215
216     /**
217      * Return the set of <code>Extension</code> objects representing optional
218      * packages that are required by the application contained in the JAR
219      * file associated with the specified <code>Manifest</code>. If there
220      * are no such optional packages, a zero-length list is returned.
221      *
222      * @param manifest Manifest to be parsed
223      * @return the dependencies that are specified in manifes
224      */

225     public static Extension[] getRequired(final Manifest JavaDoc manifest) {
226         return getListed(manifest, Attributes.Name.EXTENSION_LIST);
227     }
228
229     /**
230      * Return the set of <code>Extension</code> objects representing "Optional
231      * Packages" that the application declares they will use if present. If
232      * there are no such optional packages, a zero-length list is returned.
233      *
234      * @param manifest Manifest to be parsed
235      * @return the optional dependencies that are specified in manifest
236      */

237     public static Extension[] getOptions(final Manifest JavaDoc manifest) {
238         return getListed(manifest, OPTIONAL_EXTENSION_LIST);
239     }
240
241     /**
242      * Add Extension to the specified manifest Attributes.
243      *
244      * @param attributes the attributes of manifest to add to
245      * @param extension the extension
246      */

247     public static void addExtension(final Extension extension,
248                                      final Attributes JavaDoc attributes) {
249         addExtension(extension, "", attributes);
250     }
251
252     /**
253      * Add Extension to the specified manifest Attributes.
254      * Use the specified prefix so that dependencies can added
255      * with a prefix such as "java3d-" etc.
256      *
257      * @param attributes the attributes of manifest to add to
258      * @param extension the extension
259      * @param prefix the name to prefix to extension
260      */

261     public static void addExtension(final Extension extension,
262                                      final String JavaDoc prefix,
263                                      final Attributes JavaDoc attributes) {
264         attributes.putValue(prefix + EXTENSION_NAME,
265                              extension.getExtensionName());
266
267         final String JavaDoc specificationVendor = extension.getSpecificationVendor();
268         if (null != specificationVendor) {
269             attributes.putValue(prefix + SPECIFICATION_VENDOR,
270                                  specificationVendor);
271         }
272
273         final DeweyDecimal specificationVersion
274             = extension.getSpecificationVersion();
275         if (null != specificationVersion) {
276             attributes.putValue(prefix + SPECIFICATION_VERSION,
277                                  specificationVersion.toString());
278         }
279
280         final String JavaDoc implementationVendorID
281             = extension.getImplementationVendorID();
282         if (null != implementationVendorID) {
283             attributes.putValue(prefix + IMPLEMENTATION_VENDOR_ID,
284                                  implementationVendorID);
285         }
286
287         final String JavaDoc implementationVendor = extension.getImplementationVendor();
288         if (null != implementationVendor) {
289             attributes.putValue(prefix + IMPLEMENTATION_VENDOR,
290                                  implementationVendor);
291         }
292
293         final DeweyDecimal implementationVersion
294             = extension.getImplementationVersion();
295         if (null != implementationVersion) {
296             attributes.putValue(prefix + IMPLEMENTATION_VERSION,
297                                  implementationVersion.toString());
298         }
299
300         final String JavaDoc implementationURL = extension.getImplementationURL();
301         if (null != implementationURL) {
302             attributes.putValue(prefix + IMPLEMENTATION_URL,
303                                  implementationURL);
304         }
305     }
306
307     /**
308      * The constructor to create Extension object.
309      * Note that every component is allowed to be specified
310      * but only the extensionName is mandatory.
311      *
312      * @param extensionName the name of extension.
313      * @param specificationVersion the specification Version of extension.
314      * @param specificationVendor the specification Vendor of extension.
315      * @param implementationVersion the implementation Version of extension.
316      * @param implementationVendor the implementation Vendor of extension.
317      * @param implementationVendorId the implementation VendorId of extension.
318      * @param implementationURL the implementation URL of extension.
319      */

320     public Extension(final String JavaDoc extensionName,
321                       final String JavaDoc specificationVersion,
322                       final String JavaDoc specificationVendor,
323                       final String JavaDoc implementationVersion,
324                       final String JavaDoc implementationVendor,
325                       final String JavaDoc implementationVendorId,
326                       final String JavaDoc implementationURL) {
327         this.extensionName = extensionName;
328         this.specificationVendor = specificationVendor;
329
330         if (null != specificationVersion) {
331             try {
332                 this.specificationVersion
333                     = new DeweyDecimal(specificationVersion);
334             } catch (final NumberFormatException JavaDoc nfe) {
335                 final String JavaDoc error = "Bad specification version format '"
336                     + specificationVersion + "' in '" + extensionName
337                     + "'. (Reason: " + nfe + ")";
338                 throw new IllegalArgumentException JavaDoc(error);
339             }
340         }
341
342         this.implementationURL = implementationURL;
343         this.implementationVendor = implementationVendor;
344         this.implementationVendorID = implementationVendorId;
345
346         if (null != implementationVersion) {
347             try {
348                 this.implementationVersion
349                     = new DeweyDecimal(implementationVersion);
350             } catch (final NumberFormatException JavaDoc nfe) {
351                 final String JavaDoc error = "Bad implementation version format '"
352                     + implementationVersion + "' in '" + extensionName
353                     + "'. (Reason: " + nfe + ")";
354                 throw new IllegalArgumentException JavaDoc(error);
355             }
356         }
357
358         if (null == this.extensionName) {
359             throw new NullPointerException JavaDoc("extensionName property is null");
360         }
361     }
362
363     /**
364      * Get the name of the extension.
365      *
366      * @return the name of the extension
367      */

368     public String JavaDoc getExtensionName() {
369         return extensionName;
370     }
371
372     /**
373      * Get the vendor of the extensions specification.
374      *
375      * @return the vendor of the extensions specification.
376      */

377     public String JavaDoc getSpecificationVendor() {
378         return specificationVendor;
379     }
380
381     /**
382      * Get the version of the extensions specification.
383      *
384      * @return the version of the extensions specification.
385      */

386     public DeweyDecimal getSpecificationVersion() {
387         return specificationVersion;
388     }
389
390     /**
391      * Get the url of the extensions implementation.
392      *
393      * @return the url of the extensions implementation.
394      */

395     public String JavaDoc getImplementationURL() {
396         return implementationURL;
397     }
398
399     /**
400      * Get the vendor of the extensions implementation.
401      *
402      * @return the vendor of the extensions implementation.
403      */

404     public String JavaDoc getImplementationVendor() {
405         return implementationVendor;
406     }
407
408     /**
409      * Get the vendorID of the extensions implementation.
410      *
411      * @return the vendorID of the extensions implementation.
412      */

413     public String JavaDoc getImplementationVendorID() {
414         return implementationVendorID;
415     }
416
417     /**
418      * Get the version of the extensions implementation.
419      *
420      * @return the version of the extensions implementation.
421      */

422     public DeweyDecimal getImplementationVersion() {
423         return implementationVersion;
424     }
425
426     /**
427      * Return a Compatibility enum indicating the relationship of this
428      * <code>Extension</code> with the specified <code>Extension</code>.
429      *
430      * @param required Description of the required optional package
431      * @return the enum indicating the compatibility (or lack thereof)
432      * of specifed extension
433      */

434     public Compatibility getCompatibilityWith(final Extension required) {
435         // Extension Name must match
436
if (!extensionName.equals(required.getExtensionName())) {
437             return INCOMPATIBLE;
438         }
439
440         // Available specification version must be >= required
441
final DeweyDecimal requiredSpecificationVersion
442             = required.getSpecificationVersion();
443         if (null != requiredSpecificationVersion) {
444             if (null == specificationVersion
445                 || !isCompatible(specificationVersion, requiredSpecificationVersion)) {
446                 return REQUIRE_SPECIFICATION_UPGRADE;
447             }
448         }
449
450         // Implementation Vendor ID must match
451
final String JavaDoc requiredImplementationVendorID
452             = required.getImplementationVendorID();
453         if (null != requiredImplementationVendorID) {
454             if (null == implementationVendorID
455                 || !implementationVendorID.equals(requiredImplementationVendorID)) {
456                 return REQUIRE_VENDOR_SWITCH;
457             }
458         }
459
460         // Implementation version must be >= required
461
final DeweyDecimal requiredImplementationVersion
462             = required.getImplementationVersion();
463         if (null != requiredImplementationVersion) {
464             if (null == implementationVersion
465                 || !isCompatible(implementationVersion, requiredImplementationVersion)) {
466                 return REQUIRE_IMPLEMENTATION_UPGRADE;
467             }
468         }
469
470         // This available optional package satisfies the requirements
471
return COMPATIBLE;
472     }
473
474     /**
475      * Return <code>true</code> if the specified <code>Extension</code>
476      * (which represents an optional package required by an application)
477      * is satisfied by this <code>Extension</code> (which represents an
478      * optional package that is already installed. Otherwise, return
479      * <code>false</code>.
480      *
481      * @param required Description of the required optional package
482      * @return true if the specified extension is compatible with this extension
483      */

484     public boolean isCompatibleWith(final Extension required) {
485         return (COMPATIBLE == getCompatibilityWith(required));
486     }
487
488     /**
489      * Return a String representation of this object.
490      *
491      * @return string representation of object.
492      */

493     public String JavaDoc toString() {
494         final String JavaDoc brace = ": ";
495
496         final StringBuffer JavaDoc sb = new StringBuffer JavaDoc(EXTENSION_NAME.toString());
497         sb.append(brace);
498         sb.append(extensionName);
499         sb.append(StringUtils.LINE_SEP);
500
501         if (null != specificationVersion) {
502             sb.append(SPECIFICATION_VERSION);
503             sb.append(brace);
504             sb.append(specificationVersion);
505             sb.append(StringUtils.LINE_SEP);
506         }
507
508         if (null != specificationVendor) {
509             sb.append(SPECIFICATION_VENDOR);
510             sb.append(brace);
511             sb.append(specificationVendor);
512             sb.append(StringUtils.LINE_SEP);
513         }
514
515         if (null != implementationVersion) {
516             sb.append(IMPLEMENTATION_VERSION);
517             sb.append(brace);
518             sb.append(implementationVersion);
519             sb.append(StringUtils.LINE_SEP);
520         }
521
522         if (null != implementationVendorID) {
523             sb.append(IMPLEMENTATION_VENDOR_ID);
524             sb.append(brace);
525             sb.append(implementationVendorID);
526             sb.append(StringUtils.LINE_SEP);
527         }
528
529         if (null != implementationVendor) {
530             sb.append(IMPLEMENTATION_VENDOR);
531             sb.append(brace);
532             sb.append(implementationVendor);
533             sb.append(StringUtils.LINE_SEP);
534         }
535
536         if (null != implementationURL) {
537             sb.append(IMPLEMENTATION_URL);
538             sb.append(brace);
539             sb.append(implementationURL);
540             sb.append(StringUtils.LINE_SEP);
541         }
542
543         return sb.toString();
544     }
545
546     /**
547      * Return <code>true</code> if the first version number is greater than
548      * or equal to the second; otherwise return <code>false</code>.
549      *
550      * @param first First version number (dotted decimal)
551      * @param second Second version number (dotted decimal)
552      */

553     private boolean isCompatible(final DeweyDecimal first,
554                                  final DeweyDecimal second) {
555         return first.isGreaterThanOrEqual(second);
556     }
557
558     /**
559      * Retrieve all the extensions listed under a particular key
560      * (Usually EXTENSION_LIST or OPTIONAL_EXTENSION_LIST).
561      *
562      * @param manifest the manifest to extract extensions from
563      * @param listKey the key used to get list (Usually
564      * EXTENSION_LIST or OPTIONAL_EXTENSION_LIST)
565      * @return the list of listed extensions
566      */

567     private static Extension[] getListed(final Manifest JavaDoc manifest,
568                                           final Attributes.Name JavaDoc listKey) {
569         final ArrayList JavaDoc results = new ArrayList JavaDoc();
570         final Attributes JavaDoc mainAttributes = manifest.getMainAttributes();
571
572         if (null != mainAttributes) {
573             getExtension(mainAttributes, results, listKey);
574         }
575
576         final Map JavaDoc entries = manifest.getEntries();
577         final Iterator JavaDoc keys = entries.keySet().iterator();
578         while (keys.hasNext()) {
579             final String JavaDoc key = (String JavaDoc) keys.next();
580             final Attributes JavaDoc attributes = (Attributes JavaDoc) entries.get(key);
581             getExtension(attributes, results, listKey);
582         }
583
584         return (Extension[]) results.toArray(new Extension[results.size()]);
585     }
586
587     /**
588      * Add required optional packages defined in the specified
589      * attributes entry, if any.
590      *
591      * @param attributes Attributes to be parsed
592      * @param required list to add required optional packages to
593      * @param listKey the key to use to lookup list, usually EXTENSION_LIST
594      * or OPTIONAL_EXTENSION_LIST
595      */

596     private static void getExtension(final Attributes JavaDoc attributes,
597                                      final ArrayList JavaDoc required,
598                                      final Attributes.Name JavaDoc listKey) {
599         final String JavaDoc names = attributes.getValue(listKey);
600         if (null == names) {
601             return;
602         }
603
604         final String JavaDoc[] extentions = split(names, " ");
605         for (int i = 0; i < extentions.length; i++) {
606             final String JavaDoc prefix = extentions[ i ] + "-";
607             final Extension extension = getExtension(prefix, attributes);
608
609             if (null != extension) {
610                 required.add(extension);
611             }
612         }
613     }
614
615     /**
616      * Splits the string on every token into an array of strings.
617      *
618      * @param string the string
619      * @param onToken the token
620      * @return the resultant array
621      */

622     private static String JavaDoc[] split(final String JavaDoc string,
623                                         final String JavaDoc onToken) {
624         final StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(string, onToken);
625         final String JavaDoc[] result = new String JavaDoc[ tokenizer.countTokens() ];
626
627         for (int i = 0; i < result.length; i++) {
628             result[ i ] = tokenizer.nextToken();
629         }
630
631         return result;
632     }
633
634     /**
635      * Extract an Extension from Attributes.
636      * Prefix indicates the prefix checked for each string.
637      * Usually the prefix is <em>"&lt;extension&gt;-"</em> if looking for a
638      * <b>Required</b> extension. If you are looking for an
639      * <b>Available</b> extension
640      * then the prefix is <em>""</em>.
641      *
642      * @param prefix the prefix for each attribute name
643      * @param attributes Attributes to searched
644      * @return the new Extension object, or null
645      */

646     private static Extension getExtension(final String JavaDoc prefix,
647                                           final Attributes JavaDoc attributes) {
648         //WARNING: We trim the values of all the attributes because
649
//Some extension declarations are badly defined (ie have spaces
650
//after version or vendorID)
651
final String JavaDoc nameKey = prefix + EXTENSION_NAME;
652         final String JavaDoc name = getTrimmedString(attributes.getValue(nameKey));
653         if (null == name) {
654             return null;
655         }
656
657         final String JavaDoc specVendorKey = prefix + SPECIFICATION_VENDOR;
658         final String JavaDoc specVendor
659             = getTrimmedString(attributes.getValue(specVendorKey));
660         final String JavaDoc specVersionKey = prefix + SPECIFICATION_VERSION;
661         final String JavaDoc specVersion
662             = getTrimmedString(attributes.getValue(specVersionKey));
663
664         final String JavaDoc impVersionKey = prefix + IMPLEMENTATION_VERSION;
665         final String JavaDoc impVersion
666             = getTrimmedString(attributes.getValue(impVersionKey));
667         final String JavaDoc impVendorKey = prefix + IMPLEMENTATION_VENDOR;
668         final String JavaDoc impVendor
669             = getTrimmedString(attributes.getValue(impVendorKey));
670         final String JavaDoc impVendorIDKey = prefix + IMPLEMENTATION_VENDOR_ID;
671         final String JavaDoc impVendorId
672             = getTrimmedString(attributes.getValue(impVendorIDKey));
673         final String JavaDoc impURLKey = prefix + IMPLEMENTATION_URL;
674         final String JavaDoc impURL = getTrimmedString(attributes.getValue(impURLKey));
675
676         return new Extension(name, specVersion, specVendor, impVersion,
677                               impVendor, impVendorId, impURL);
678     }
679
680     /**
681      * Trim the supplied string if the string is non-null
682      *
683      * @param value the string to trim or null
684      * @return the trimmed string or null
685      */

686     private static String JavaDoc getTrimmedString(final String JavaDoc value) {
687         return null == value ? null : value.trim();
688     }
689 }
690
Popular Tags