diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java | 690 |
1 files changed, 690 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java new file mode 100644 index 00000000..d13d2f4e --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/extension/Extension.java @@ -0,0 +1,690 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.taskdefs.optional.extension; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import org.apache.tools.ant.util.DeweyDecimal; +import org.apache.tools.ant.util.StringUtils; + +/** + * <p>Utility class that represents either an available "Optional Package" + * (formerly known as "Standard Extension") as described in the manifest + * of a JAR file, or the requirement for such an optional package.</p> + * + * <p>For more information about optional packages, see the document + * <em>Optional Package Versioning</em> in the documentation bundle for your + * Java2 Standard Edition package, in file + * <code>guide/extensions/versioning.html</code>.</p> + * + */ +public final class Extension { + /** + * Manifest Attribute Name object for EXTENSION_LIST. + */ + public static final Attributes.Name EXTENSION_LIST + = new Attributes.Name("Extension-List"); + + /** + * <code>Name</code> object for <code>Optional-Extension-List</code> + * manifest attribute used for declaring optional dependencies on + * installed extensions. Note that the dependencies declared by this method + * are not required for the library to operate but if present will be used. + * It is NOT part of the official "Optional Package" specification. + * + * @see <a href="http://java.sun.com/j2se/1.3/docs/guide/extensions/spec.html#dependency"> + * Installed extension dependency</a> + */ + public static final Attributes.Name OPTIONAL_EXTENSION_LIST + = new Attributes.Name("Optional-Extension-List"); + + /** + * Manifest Attribute Name object for EXTENSION_NAME. + */ + public static final Attributes.Name EXTENSION_NAME = + new Attributes.Name("Extension-Name"); + /** + * Manifest Attribute Name object for SPECIFICATION_VERSION. + */ + public static final Attributes.Name SPECIFICATION_VERSION + = Attributes.Name.SPECIFICATION_VERSION; + + /** + * Manifest Attribute Name object for SPECIFICATION_VENDOR. + */ + public static final Attributes.Name SPECIFICATION_VENDOR + = Attributes.Name.SPECIFICATION_VENDOR; + + /** + * Manifest Attribute Name object for IMPLEMENTATION_VERSION. + */ + public static final Attributes.Name IMPLEMENTATION_VERSION + = Attributes.Name.IMPLEMENTATION_VERSION; + + /** + * Manifest Attribute Name object for IMPLEMENTATION_VENDOR. + */ + public static final Attributes.Name IMPLEMENTATION_VENDOR + = Attributes.Name.IMPLEMENTATION_VENDOR; + + /** + * Manifest Attribute Name object for IMPLEMENTATION_URL. + */ + public static final Attributes.Name IMPLEMENTATION_URL + = new Attributes.Name("Implementation-URL"); + + /** + * Manifest Attribute Name object for IMPLEMENTATION_VENDOR_ID. + */ + public static final Attributes.Name IMPLEMENTATION_VENDOR_ID + = new Attributes.Name("Implementation-Vendor-Id"); + + /** + * Enum indicating that extension is compatible with other extension. + */ + public static final Compatibility COMPATIBLE + = new Compatibility("COMPATIBLE"); + + /** + * Enum indicating that extension requires an upgrade + * of specification to be compatible with other extension. + */ + public static final Compatibility REQUIRE_SPECIFICATION_UPGRADE + = new Compatibility("REQUIRE_SPECIFICATION_UPGRADE"); + + /** + * Enum indicating that extension requires a vendor + * switch to be compatible with other extension. + */ + public static final Compatibility REQUIRE_VENDOR_SWITCH + = new Compatibility("REQUIRE_VENDOR_SWITCH"); + + /** + * Enum indicating that extension requires an upgrade + * of implementation to be compatible with other extension. + */ + public static final Compatibility REQUIRE_IMPLEMENTATION_UPGRADE + = new Compatibility("REQUIRE_IMPLEMENTATION_UPGRADE"); + + /** + * Enum indicating that extension is incompatible with + * other extension in ways other than other enums + * indicate). For example the other extension may have + * a different ID. + */ + public static final Compatibility INCOMPATIBLE + = new Compatibility("INCOMPATIBLE"); + + /** + * The name of the optional package being made available, or required. + */ + private String extensionName; + + /** + * The version number (dotted decimal notation) of the specification + * to which this optional package conforms. + */ + private DeweyDecimal specificationVersion; + + /** + * The name of the company or organization that originated the + * specification to which this optional package conforms. + */ + private String specificationVendor; + + /** + * The unique identifier of the company that produced the optional + * package contained in this JAR file. + */ + private String implementationVendorID; + + /** + * The name of the company or organization that produced this + * implementation of this optional package. + */ + private String implementationVendor; + + /** + * The version number (dotted decimal notation) for this implementation + * of the optional package. + */ + private DeweyDecimal implementationVersion; + + /** + * The URL from which the most recent version of this optional package + * can be obtained if it is not already installed. + */ + private String implementationURL; + + /** + * Return an array of <code>Extension</code> objects representing optional + * packages that are available in the JAR file associated with the + * specified <code>Manifest</code>. If there are no such optional + * packages, a zero-length array is returned. + * + * @param manifest Manifest to be parsed + * @return the "available" extensions in specified manifest + */ + public static Extension[] getAvailable(final Manifest manifest) { + if (null == manifest) { + return new Extension[ 0 ]; + } + + final ArrayList results = new ArrayList(); + + final Attributes mainAttributes = manifest.getMainAttributes(); + if (null != mainAttributes) { + final Extension extension = getExtension("", mainAttributes); + if (null != extension) { + results.add(extension); + } + } + + final Map entries = manifest.getEntries(); + final Iterator keys = entries.keySet().iterator(); + while (keys.hasNext()) { + final String key = (String) keys.next(); + final Attributes attributes = (Attributes) entries.get(key); + final Extension extension = getExtension("", attributes); + if (null != extension) { + results.add(extension); + } + } + + return (Extension[]) results.toArray(new Extension[results.size()]); + } + + /** + * Return the set of <code>Extension</code> objects representing optional + * packages that are required by the application contained in the JAR + * file associated with the specified <code>Manifest</code>. If there + * are no such optional packages, a zero-length list is returned. + * + * @param manifest Manifest to be parsed + * @return the dependencies that are specified in manifest + */ + public static Extension[] getRequired(final Manifest manifest) { + return getListed(manifest, Attributes.Name.EXTENSION_LIST); + } + + /** + * Return the set of <code>Extension</code> objects representing "Optional + * Packages" that the application declares they will use if present. If + * there are no such optional packages, a zero-length list is returned. + * + * @param manifest Manifest to be parsed + * @return the optional dependencies that are specified in manifest + */ + public static Extension[] getOptions(final Manifest manifest) { + return getListed(manifest, OPTIONAL_EXTENSION_LIST); + } + + /** + * Add Extension to the specified manifest Attributes. + * + * @param attributes the attributes of manifest to add to + * @param extension the extension + */ + public static void addExtension(final Extension extension, + final Attributes attributes) { + addExtension(extension, "", attributes); + } + + /** + * Add Extension to the specified manifest Attributes. + * Use the specified prefix so that dependencies can added + * with a prefix such as "java3d-" etc. + * + * @param attributes the attributes of manifest to add to + * @param extension the extension + * @param prefix the name to prefix to extension + */ + public static void addExtension(final Extension extension, + final String prefix, + final Attributes attributes) { + attributes.putValue(prefix + EXTENSION_NAME, + extension.getExtensionName()); + + final String specificationVendor = extension.getSpecificationVendor(); + if (null != specificationVendor) { + attributes.putValue(prefix + SPECIFICATION_VENDOR, + specificationVendor); + } + + final DeweyDecimal specificationVersion + = extension.getSpecificationVersion(); + if (null != specificationVersion) { + attributes.putValue(prefix + SPECIFICATION_VERSION, + specificationVersion.toString()); + } + + final String implementationVendorID + = extension.getImplementationVendorID(); + if (null != implementationVendorID) { + attributes.putValue(prefix + IMPLEMENTATION_VENDOR_ID, + implementationVendorID); + } + + final String implementationVendor = extension.getImplementationVendor(); + if (null != implementationVendor) { + attributes.putValue(prefix + IMPLEMENTATION_VENDOR, + implementationVendor); + } + + final DeweyDecimal implementationVersion + = extension.getImplementationVersion(); + if (null != implementationVersion) { + attributes.putValue(prefix + IMPLEMENTATION_VERSION, + implementationVersion.toString()); + } + + final String implementationURL = extension.getImplementationURL(); + if (null != implementationURL) { + attributes.putValue(prefix + IMPLEMENTATION_URL, + implementationURL); + } + } + + /** + * The constructor to create Extension object. + * Note that every component is allowed to be specified + * but only the extensionName is mandatory. + * + * @param extensionName the name of extension. + * @param specificationVersion the specification Version of extension. + * @param specificationVendor the specification Vendor of extension. + * @param implementationVersion the implementation Version of extension. + * @param implementationVendor the implementation Vendor of extension. + * @param implementationVendorId the implementation VendorId of extension. + * @param implementationURL the implementation URL of extension. + */ + public Extension(final String extensionName, + final String specificationVersion, + final String specificationVendor, + final String implementationVersion, + final String implementationVendor, + final String implementationVendorId, + final String implementationURL) { + this.extensionName = extensionName; + this.specificationVendor = specificationVendor; + + if (null != specificationVersion) { + try { + this.specificationVersion + = new DeweyDecimal(specificationVersion); + } catch (final NumberFormatException nfe) { + final String error = "Bad specification version format '" + + specificationVersion + "' in '" + extensionName + + "'. (Reason: " + nfe + ")"; + throw new IllegalArgumentException(error); + } + } + + this.implementationURL = implementationURL; + this.implementationVendor = implementationVendor; + this.implementationVendorID = implementationVendorId; + + if (null != implementationVersion) { + try { + this.implementationVersion + = new DeweyDecimal(implementationVersion); + } catch (final NumberFormatException nfe) { + final String error = "Bad implementation version format '" + + implementationVersion + "' in '" + extensionName + + "'. (Reason: " + nfe + ")"; + throw new IllegalArgumentException(error); + } + } + + if (null == this.extensionName) { + throw new NullPointerException("extensionName property is null"); + } + } + + /** + * Get the name of the extension. + * + * @return the name of the extension + */ + public String getExtensionName() { + return extensionName; + } + + /** + * Get the vendor of the extensions specification. + * + * @return the vendor of the extensions specification. + */ + public String getSpecificationVendor() { + return specificationVendor; + } + + /** + * Get the version of the extensions specification. + * + * @return the version of the extensions specification. + */ + public DeweyDecimal getSpecificationVersion() { + return specificationVersion; + } + + /** + * Get the url of the extensions implementation. + * + * @return the url of the extensions implementation. + */ + public String getImplementationURL() { + return implementationURL; + } + + /** + * Get the vendor of the extensions implementation. + * + * @return the vendor of the extensions implementation. + */ + public String getImplementationVendor() { + return implementationVendor; + } + + /** + * Get the vendorID of the extensions implementation. + * + * @return the vendorID of the extensions implementation. + */ + public String getImplementationVendorID() { + return implementationVendorID; + } + + /** + * Get the version of the extensions implementation. + * + * @return the version of the extensions implementation. + */ + public DeweyDecimal getImplementationVersion() { + return implementationVersion; + } + + /** + * Return a Compatibility enum indicating the relationship of this + * <code>Extension</code> with the specified <code>Extension</code>. + * + * @param required Description of the required optional package + * @return the enum indicating the compatibility (or lack thereof) + * of specified extension + */ + public Compatibility getCompatibilityWith(final Extension required) { + // Extension Name must match + if (!extensionName.equals(required.getExtensionName())) { + return INCOMPATIBLE; + } + + // Available specification version must be >= required + final DeweyDecimal requiredSpecificationVersion + = required.getSpecificationVersion(); + if (null != requiredSpecificationVersion) { + if (null == specificationVersion + || !isCompatible(specificationVersion, requiredSpecificationVersion)) { + return REQUIRE_SPECIFICATION_UPGRADE; + } + } + + // Implementation Vendor ID must match + final String requiredImplementationVendorID + = required.getImplementationVendorID(); + if (null != requiredImplementationVendorID) { + if (null == implementationVendorID + || !implementationVendorID.equals(requiredImplementationVendorID)) { + return REQUIRE_VENDOR_SWITCH; + } + } + + // Implementation version must be >= required + final DeweyDecimal requiredImplementationVersion + = required.getImplementationVersion(); + if (null != requiredImplementationVersion) { + if (null == implementationVersion + || !isCompatible(implementationVersion, requiredImplementationVersion)) { + return REQUIRE_IMPLEMENTATION_UPGRADE; + } + } + + // This available optional package satisfies the requirements + return COMPATIBLE; + } + + /** + * Return <code>true</code> if the specified <code>Extension</code> + * (which represents an optional package required by an application) + * is satisfied by this <code>Extension</code> (which represents an + * optional package that is already installed. Otherwise, return + * <code>false</code>. + * + * @param required Description of the required optional package + * @return true if the specified extension is compatible with this extension + */ + public boolean isCompatibleWith(final Extension required) { + return (COMPATIBLE == getCompatibilityWith(required)); + } + + /** + * Return a String representation of this object. + * + * @return string representation of object. + */ + public String toString() { + final String brace = ": "; + + final StringBuffer sb = new StringBuffer(EXTENSION_NAME.toString()); + sb.append(brace); + sb.append(extensionName); + sb.append(StringUtils.LINE_SEP); + + if (null != specificationVersion) { + sb.append(SPECIFICATION_VERSION); + sb.append(brace); + sb.append(specificationVersion); + sb.append(StringUtils.LINE_SEP); + } + + if (null != specificationVendor) { + sb.append(SPECIFICATION_VENDOR); + sb.append(brace); + sb.append(specificationVendor); + sb.append(StringUtils.LINE_SEP); + } + + if (null != implementationVersion) { + sb.append(IMPLEMENTATION_VERSION); + sb.append(brace); + sb.append(implementationVersion); + sb.append(StringUtils.LINE_SEP); + } + + if (null != implementationVendorID) { + sb.append(IMPLEMENTATION_VENDOR_ID); + sb.append(brace); + sb.append(implementationVendorID); + sb.append(StringUtils.LINE_SEP); + } + + if (null != implementationVendor) { + sb.append(IMPLEMENTATION_VENDOR); + sb.append(brace); + sb.append(implementationVendor); + sb.append(StringUtils.LINE_SEP); + } + + if (null != implementationURL) { + sb.append(IMPLEMENTATION_URL); + sb.append(brace); + sb.append(implementationURL); + sb.append(StringUtils.LINE_SEP); + } + + return sb.toString(); + } + + /** + * Return <code>true</code> if the first version number is greater than + * or equal to the second; otherwise return <code>false</code>. + * + * @param first First version number (dotted decimal) + * @param second Second version number (dotted decimal) + */ + private boolean isCompatible(final DeweyDecimal first, + final DeweyDecimal second) { + return first.isGreaterThanOrEqual(second); + } + + /** + * Retrieve all the extensions listed under a particular key + * (Usually EXTENSION_LIST or OPTIONAL_EXTENSION_LIST). + * + * @param manifest the manifest to extract extensions from + * @param listKey the key used to get list (Usually + * EXTENSION_LIST or OPTIONAL_EXTENSION_LIST) + * @return the list of listed extensions + */ + private static Extension[] getListed(final Manifest manifest, + final Attributes.Name listKey) { + final ArrayList results = new ArrayList(); + final Attributes mainAttributes = manifest.getMainAttributes(); + + if (null != mainAttributes) { + getExtension(mainAttributes, results, listKey); + } + + final Map entries = manifest.getEntries(); + final Iterator keys = entries.keySet().iterator(); + while (keys.hasNext()) { + final String key = (String) keys.next(); + final Attributes attributes = (Attributes) entries.get(key); + getExtension(attributes, results, listKey); + } + + return (Extension[]) results.toArray(new Extension[results.size()]); + } + + /** + * Add required optional packages defined in the specified + * attributes entry, if any. + * + * @param attributes Attributes to be parsed + * @param required list to add required optional packages to + * @param listKey the key to use to lookup list, usually EXTENSION_LIST + * or OPTIONAL_EXTENSION_LIST + */ + private static void getExtension(final Attributes attributes, + final ArrayList required, + final Attributes.Name listKey) { + final String names = attributes.getValue(listKey); + if (null == names) { + return; + } + + final String[] extensions = split(names, " "); + for (int i = 0; i < extensions.length; i++) { + final String prefix = extensions[ i ] + "-"; + final Extension extension = getExtension(prefix, attributes); + + if (null != extension) { + required.add(extension); + } + } + } + + /** + * Splits the string on every token into an array of strings. + * + * @param string the string + * @param onToken the token + * @return the resultant array + */ + private static String[] split(final String string, + final String onToken) { + final StringTokenizer tokenizer = new StringTokenizer(string, onToken); + final String[] result = new String[ tokenizer.countTokens() ]; + + for (int i = 0; i < result.length; i++) { + result[ i ] = tokenizer.nextToken(); + } + + return result; + } + + /** + * Extract an Extension from Attributes. + * Prefix indicates the prefix checked for each string. + * Usually the prefix is <em>"<extension>-"</em> if looking for a + * <b>Required</b> extension. If you are looking for an + * <b>Available</b> extension + * then the prefix is <em>""</em>. + * + * @param prefix the prefix for each attribute name + * @param attributes Attributes to searched + * @return the new Extension object, or null + */ + private static Extension getExtension(final String prefix, + final Attributes attributes) { + //WARNING: We trim the values of all the attributes because + //Some extension declarations are badly defined (ie have spaces + //after version or vendorID) + final String nameKey = prefix + EXTENSION_NAME; + final String name = getTrimmedString(attributes.getValue(nameKey)); + if (null == name) { + return null; + } + + final String specVendorKey = prefix + SPECIFICATION_VENDOR; + final String specVendor + = getTrimmedString(attributes.getValue(specVendorKey)); + final String specVersionKey = prefix + SPECIFICATION_VERSION; + final String specVersion + = getTrimmedString(attributes.getValue(specVersionKey)); + + final String impVersionKey = prefix + IMPLEMENTATION_VERSION; + final String impVersion + = getTrimmedString(attributes.getValue(impVersionKey)); + final String impVendorKey = prefix + IMPLEMENTATION_VENDOR; + final String impVendor + = getTrimmedString(attributes.getValue(impVendorKey)); + final String impVendorIDKey = prefix + IMPLEMENTATION_VENDOR_ID; + final String impVendorId + = getTrimmedString(attributes.getValue(impVendorIDKey)); + final String impURLKey = prefix + IMPLEMENTATION_URL; + final String impURL = getTrimmedString(attributes.getValue(impURLKey)); + + return new Extension(name, specVersion, specVendor, impVersion, + impVendor, impVendorId, impURL); + } + + /** + * Trim the supplied string if the string is non-null + * + * @param value the string to trim or null + * @return the trimmed string or null + */ + private static String getTrimmedString(final String value) { + return null == value ? null : value.trim(); + } +} |