| /* Attributes.java -- Represents attribute name/value pairs from a Manifest |
| Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| package java.util.jar; |
| |
| import gnu.java.util.jar.JarUtils; |
| |
| import java.util.Collection; |
| import java.util.Hashtable; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * Represents attribute name/value pairs from a Manifest as a Map. |
| * The names of an attribute are represented by the |
| * <code>Attributes.Name</code> class and should confirm to the restrictions |
| * described in that class. Note that the Map interface that Attributes |
| * implements allows you to put names and values into the attribute that don't |
| * follow these restriction (and are not really Atrribute.Names, but if you do |
| * that it might cause undefined behaviour later). |
| * <p> |
| * If you use the constants defined in the inner class Name then you can be |
| * sure that you always access the right attribute names. This makes |
| * manipulating the Attributes more or less type safe. |
| * <p> |
| * Most of the methods are wrappers to implement the Map interface. The really |
| * useful and often used methods are <code>getValue(Name)</code> and |
| * <code>getValue(String)</code>. If you actually want to set attributes you |
| * may want to use the <code>putValue(String, String)</code> method |
| * (sorry there is no public type safe <code>putValue(Name, String)</code> |
| * method). |
| * |
| * @see java.util.jar.Attributes.Name |
| * @author Mark Wielaard (mark@klomp.org) |
| */ |
| public class Attributes |
| implements Cloneable, java.util.Map // Fully qualified for jikes 1.22 |
| { |
| |
| // Fields |
| |
| /** |
| * The map that holds all the attribute name/value pairs. In this |
| * implementation it is actually a Hashtable, but that can be different in |
| * other implementations. |
| */ |
| protected Map map; |
| |
| // Inner class |
| |
| /** |
| * Represents a name of a Manifest Attribute. Defines a couple of well |
| * know names for the general main attributes, stand alone application |
| * attributes, applet attributes, extension identification attributes, |
| * package versioning and sealing attributes, file contents attributes, |
| * bean objects attribute and signing attributes. See the |
| * |
| * <p>The characters of a Name must obey the following restrictions:</p> |
| * |
| * <ul> |
| * <li>Must contain at least one character</li> |
| * <li>The first character must be alphanumeric (a-z, A-Z, 0-9)</li> |
| * <li>All other characters must be alphanumeric, a '-' or a '_'</li> |
| * </ul> |
| * |
| * <p>When comparing Names (with <code>equals</code>) all characters are |
| * converted to lowercase. But you can get the original case sensitive |
| * string with the <code>toString()</code> method.</p> |
| * |
| * <p>Most important attributes have a constant defined in this |
| * class. Some other attributes used in Manifest files are: |
| * <ul> |
| * <li> "Created-By" - General main attribute, tool and version |
| * that created this Manifest file.</li> |
| * <li> "Java-Bean" - Bean objects attribute, whether the entry is a Bean. |
| * Value is either "true" or "false".</li> |
| * <li> "Magic" - Signing attribute, application specific signing attribute. |
| * Must be understood by the manifest parser when present to validate the |
| * jar (entry).</li> |
| * </ul> |
| * |
| * @since 1.2 |
| * @author Mark Wielaard (mark@klomp.org) |
| */ |
| public static class Name |
| { |
| // General Main Attributes |
| |
| /** |
| * General main attribute - |
| * the version of this Manifest file. |
| */ |
| public static final Name MANIFEST_VERSION = new Name(JarUtils.MANIFEST_VERSION); |
| |
| /** |
| * General main attribute - |
| * the version of the jar file signature. |
| */ |
| public static final Name SIGNATURE_VERSION = new Name(JarUtils.SIGNATURE_VERSION); |
| |
| /** |
| * General main attribute - |
| * (relative) file paths of the libraries/classpaths that the Classes in |
| * this jar file depend on. Paths are separated by spaces. |
| */ |
| public static final Name CLASS_PATH = new Name("Class-Path"); |
| |
| /** |
| * Stand alone application attribute - |
| * the entry (without the .class ending) that is the main |
| * class of this jar file. |
| */ |
| public static final Name MAIN_CLASS = new Name("Main-Class"); |
| |
| /** |
| * Applet attribute - |
| * a list of extension libraries that the applet in this |
| * jar file depends on. |
| * For every named extension there should be some Attributes in the |
| * Manifest manifest file with the following Names: |
| * <ul> |
| * <li> <extension>-Extension-Name: |
| * unique name of the extension</li> |
| * <li> <extension>-Specification-Version: |
| * minimum specification version</li> |
| * <li> <extension>-Implementation-Version: |
| * minimum implementation version</li> |
| * <li> <extension>-Implementation-Vendor-Id: |
| * unique id of implementation vendor</li> |
| * <li> <extension>-Implementation-URL: |
| * where the latest version of the extension library can be found</li> |
| * </ul> |
| */ |
| public static final Name EXTENSION_LIST = new Name("Extension-List"); |
| |
| /** |
| * Extension identification attribute - |
| * the name if the extension library contained in the jar. |
| */ |
| public static final Name EXTENSION_NAME = new Name("Extension-Name"); |
| |
| /** |
| * Extension identification attribute - |
| * synonym for <code>EXTENSTION_NAME</code>. |
| */ |
| public static final Name EXTENSION_INSTALLATION = EXTENSION_NAME; |
| |
| // Package versioning and sealing attributes |
| |
| /** |
| * Package versioning - |
| * name of extension library contained in this jar. |
| */ |
| public static final Name IMPLEMENTATION_TITLE |
| = new Name("Implementation-Title"); |
| |
| /** |
| * Package versioning - |
| * version of the extension library contained in this jar. |
| */ |
| public static final Name IMPLEMENTATION_VERSION |
| = new Name("Implementation-Version"); |
| |
| /** |
| * Package versioning - |
| * name of extension library creator contained in this jar. |
| */ |
| public static final Name IMPLEMENTATION_VENDOR |
| = new Name("Implementation-Vendor"); |
| |
| /** |
| * Package versioning - |
| * unique id of extension library creator. |
| */ |
| public static final Name IMPLEMENTATION_VENDOR_ID |
| = new Name("Implementation-Vendor-Id"); |
| |
| /** |
| * Package versioning - |
| * location where this implementation can be downloaded. |
| */ |
| public static final Name IMPLEMENTATION_URL |
| = new Name("Implementation-URL"); |
| |
| /** |
| * Package versioning - |
| * title of the specification contained in this jar. |
| */ |
| public static final Name SPECIFICATION_TITLE |
| = new Name("Specification-Title"); |
| |
| /** |
| * Package versioning - |
| * version of the specification contained in this jar. |
| */ |
| public static final Name SPECIFICATION_VERSION |
| = new Name("Specification-Version"); |
| |
| /** |
| * Package versioning - |
| * organisation that maintains the specification contains in this |
| * jar. |
| */ |
| public static final Name SPECIFICATION_VENDOR |
| = new Name("Specification-Vendor"); |
| |
| /** |
| * Package sealing - |
| * whether (all) package(s) is(/are) sealed. Value is either "true" |
| * or "false". |
| */ |
| public static final Name SEALED = new Name("Sealed"); |
| |
| /** |
| * File contents attribute - |
| * Mime type and subtype for the jar entry. |
| */ |
| public static final Name CONTENT_TYPE = new Name("Content-Type"); |
| |
| /** The (lowercase) String representation of this Name */ |
| private final String name; |
| |
| /** The original String given to the constructor */ |
| private final String origName; |
| |
| // Constructor |
| |
| /** |
| * Creates a new Name from the given String. |
| * Throws an IllegalArgumentException if the given String is empty or |
| * contains any illegal Name characters. |
| * |
| * @param name the name of the new Name |
| * @exception IllegalArgumentException if name isn't a valid String |
| * representation of a Name |
| * @exception NullPointerException if name is null |
| */ |
| public Name(String name) throws IllegalArgumentException, |
| NullPointerException |
| { |
| // name must not be null |
| // this will throw a NullPointerException if it is |
| char chars[] = name.toCharArray(); |
| |
| // there must be at least one character |
| if (chars.length == 0) |
| throw new |
| IllegalArgumentException |
| ("There must be at least one character in a name"); |
| |
| // first character must be alphanum |
| char c = chars[0]; |
| if (!((c >= 'a' && c <= 'z') || |
| (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))) |
| throw new |
| IllegalArgumentException("First character must be alphanum"); |
| |
| // all other characters must be alphanums, '-' or '_' |
| for (int i = 1; i < chars.length; i++) |
| { |
| c = chars[i]; |
| if (!((c >= 'a' && c <= 'z') || |
| (c >= 'A' && c <= 'Z') || |
| (c >= '0' && c <= '9') || (c == '-') || (c == '_'))) |
| throw new |
| IllegalArgumentException |
| ("Characters must be alphanums, '-' or '_'"); |
| } |
| |
| // Still here? Then convert to lower case and be done. |
| // Store the original name for toString(); |
| this.origName = name; |
| this.name = name.toLowerCase(); |
| } |
| |
| /** |
| * Returns the hash code of the (lowercase) String representation of |
| * this Name. |
| */ |
| public int hashCode() |
| { |
| return name.hashCode(); |
| } |
| |
| /** |
| * Checks if another object is equal to this Name object. |
| * Another object is equal to this Name object if it is an instance of |
| * Name and the (lowercase) string representation of the name is equal. |
| */ |
| public boolean equals(Object o) |
| { |
| // Quick and dirty check |
| if (name == o) |
| return true; |
| |
| try |
| { |
| // Note that the constructor already converts the strings to |
| // lowercase. |
| String otherName = ((Name) o).name; |
| return name.equals(otherName); |
| } |
| catch (ClassCastException cce) |
| { |
| return false; |
| } |
| catch (NullPointerException npe) |
| { |
| return false; |
| } |
| } |
| |
| /** |
| * Returns the string representation of this Name as given to the |
| * constructor (not neccesarily the lower case representation). |
| */ |
| public String toString() |
| { |
| return origName; |
| } |
| } |
| |
| // Constructors |
| |
| /** |
| * Creates an empty Attributes map. |
| */ |
| public Attributes() |
| { |
| map = new Hashtable(); |
| } |
| |
| /** |
| * Creates an empty Attributes map with the given initial size. |
| * @param size the initial size of the underlying map |
| */ |
| public Attributes(int size) |
| { |
| map = new Hashtable(size); |
| } |
| |
| /** |
| * Creates an Attributes map with the initial values taken from another |
| * Attributes map. |
| * @param attr Attributes map to take the initial values from |
| */ |
| public Attributes(Attributes attr) |
| { |
| map = new Hashtable(attr.map); |
| } |
| |
| // Methods |
| |
| /** |
| * Gets the value of an attribute name given as a String. |
| * |
| * @param name a String describing the Name to look for |
| * @return the value gotten from the map of null when not found |
| */ |
| public String getValue(String name) |
| { |
| return (String) get(new Name(name)); |
| } |
| |
| /** |
| * Gets the value of the given attribute name. |
| * |
| * @param name the Name to look for |
| * @return the value gotten from the map of null when not found |
| */ |
| public String getValue(Name name) |
| { |
| return (String) get(name); |
| } |
| |
| /** |
| * Stores an attribute name (represented by a String) and value in this |
| * Attributes map. |
| * When the (case insensitive string) name already exists the value is |
| * replaced and the old value is returned. |
| * |
| * @param name a (case insensitive) String representation of the attribite |
| * name to add/replace |
| * @param value the (new) value of the attribute name |
| * @returns the old value of the attribute name or null if it didn't exist |
| * yet |
| */ |
| public String putValue(String name, String value) |
| { |
| return putValue(new Name(name), value); |
| } |
| |
| /** |
| * Stores an attribute name (represented by a String) and value in this |
| * Attributes map. |
| * When the name already exists the value is replaced and the old value |
| * is returned. |
| * |
| * @param name the attribite name to add/replace |
| * @param value the (new) value of the attribute name |
| * @returns the old value of the attribute name or null if it didn't exist |
| * yet |
| */ |
| private String putValue(Name name, String value) |
| { |
| return (String) put(name, value); |
| } |
| |
| // Methods from Cloneable interface |
| |
| /** |
| * Return a clone of this attribute map. |
| */ |
| public Object clone() |
| { |
| return new Attributes(this); |
| } |
| |
| // Methods from Map interface |
| |
| /** |
| * Removes all attributes. |
| */ |
| public void clear() |
| { |
| map.clear(); |
| } |
| |
| /** |
| * Checks to see if there is an attribute with the specified name. |
| * XXX - what if the object is a String? |
| * |
| * @param attrName the name of the attribute to check |
| * @return true if there is an attribute with the specified name, false |
| * otherwise |
| */ |
| public boolean containsKey(Object attrName) |
| { |
| return map.containsKey(attrName); |
| } |
| |
| /** |
| * Checks to see if there is an attribute name with the specified value. |
| * |
| * @param attrValue the value of a attribute to check |
| * @return true if there is an attribute name with the specified value, |
| * false otherwise |
| */ |
| public boolean containsValue(Object attrValue) |
| { |
| return map.containsValue(attrValue); |
| } |
| |
| /** |
| * Gives a Set of attribute name and values pairs as MapEntries. |
| * @see java.util.Map.Entry |
| * @see java.util.Map#entrySet() |
| * |
| * @return a set of attribute name value pairs |
| */ |
| public Set entrySet() |
| { |
| return map.entrySet(); |
| } |
| |
| /** |
| * Checks to see if two Attributes are equal. The supplied object must be |
| * a real instance of Attributes and contain the same attribute name/value |
| * pairs. |
| * |
| * @param o another Attribute object which should be checked for equality |
| * @return true if the object is an instance of Attributes and contains the |
| * same name/value pairs, false otherwise |
| */ |
| public boolean equals(Object o) |
| { |
| // quick and dirty check |
| if (this == o) |
| return true; |
| |
| try |
| { |
| return map.equals(((Attributes) o).map); |
| } |
| catch (ClassCastException cce) |
| { |
| return false; |
| } |
| catch (NullPointerException npe) |
| { |
| return false; |
| } |
| } |
| |
| /** |
| * Gets the value of a specified attribute name. |
| * XXX - what if the object is a String? |
| * |
| * @param attrName the name of the attribute we want the value of |
| * @return the value of the specified attribute name or null when there is |
| * no such attribute name |
| */ |
| public Object get(Object attrName) |
| { |
| return map.get(attrName); |
| } |
| |
| /** |
| * Returns the hashcode of the attribute name/value map. |
| */ |
| public int hashCode() |
| { |
| return map.hashCode(); |
| } |
| |
| /** |
| * Returns true if there are no attributes set, false otherwise. |
| */ |
| public boolean isEmpty() |
| { |
| return map.isEmpty(); |
| } |
| |
| /** |
| * Gives a Set of all the values of defined attribute names. |
| */ |
| public Set keySet() |
| { |
| return map.keySet(); |
| } |
| |
| /** |
| * Adds or replaces a attribute name/value pair. |
| * XXX - What if the name is a string? What if the name is neither a Name |
| * nor a String? What if the value is not a string? |
| * |
| * @param name the name of the attribute |
| * @param value the (new) value of the attribute |
| * @return the old value of the attribute or null when there was no old |
| * attribute with this name |
| */ |
| public Object put(Object name, Object value) |
| { |
| return map.put(name, value); |
| } |
| |
| /** |
| * Adds or replaces all attribute name/value pairs from another |
| * Attributes object to this one. The supplied Map must be an instance of |
| * Attributes. |
| * |
| * @param attr the Attributes object to merge with this one |
| * @exception ClassCastException if the supplied map is not an instance of |
| * Attributes |
| */ |
| public void putAll(Map attr) |
| { |
| if (!(attr instanceof Attributes)) |
| { |
| throw new |
| ClassCastException("Supplied Map is not an instance of Attributes"); |
| } |
| map.putAll(attr); |
| } |
| |
| /** |
| * Remove a attribute name/value pair. |
| * XXX - What if the name is a String? |
| * |
| * @param name the name of the attribute name/value pair to remove |
| * @return the old value of the attribute or null if the attribute didn't |
| * exist |
| */ |
| public Object remove(Object name) |
| { |
| return map.remove(name); |
| } |
| |
| /** |
| * Returns the number of defined attribute name/value pairs. |
| */ |
| public int size() |
| { |
| return map.size(); |
| } |
| |
| /** |
| * Returns all the values of the defined attribute name/value pairs as a |
| * Collection. |
| */ |
| public Collection values() |
| { |
| return map.values(); |
| } |
| } |