diff options
author | mark <mark@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-11-18 02:00:06 +0000 |
---|---|---|
committer | mark <mark@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-11-18 02:00:06 +0000 |
commit | 7087a5050b7f3d24bb5171874de7f666d0da815b (patch) | |
tree | 1cdd2c04005f269ae818823da99af56069055ae4 /libjava | |
parent | f1433f3d14b089f6ca72d9a78e7451cc679bdbcc (diff) | |
download | gcc-7087a5050b7f3d24bb5171874de7f666d0da815b.tar.gz |
Merge with Classpath (changes by Bryce McKinlay)
* java/util/jar/*.java: Reformat all to unofficial standard coding
style. No changes of substance.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37538 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
-rw-r--r-- | libjava/ChangeLog | 6 | ||||
-rw-r--r-- | libjava/java/util/jar/Attributes.java | 955 | ||||
-rw-r--r-- | libjava/java/util/jar/JarEntry.java | 203 | ||||
-rw-r--r-- | libjava/java/util/jar/JarException.java | 42 | ||||
-rw-r--r-- | libjava/java/util/jar/JarFile.java | 428 | ||||
-rw-r--r-- | libjava/java/util/jar/JarInputStream.java | 283 | ||||
-rw-r--r-- | libjava/java/util/jar/JarOutputStream.java | 108 | ||||
-rw-r--r-- | libjava/java/util/jar/Manifest.java | 759 |
8 files changed, 1461 insertions, 1323 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 2b604bd7963..ce80cd0faa7 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,9 @@ +2000-11-17 Mark Wielaar <mark@klomp.org> + + Merge with Classpath (changes by Bryce McKinlay) + * java/util/jar/*.java: Reformat all to unofficial standard coding + style. No changes of substance. + 2000-11-17 Mark Wielaard <mark@klomp.org> * java/util/zip/*.java: Javadoc updates. diff --git a/libjava/java/util/jar/Attributes.java b/libjava/java/util/jar/Attributes.java index 6a01be57a19..b18b5d8ca8a 100644 --- a/libjava/java/util/jar/Attributes.java +++ b/libjava/java/util/jar/Attributes.java @@ -7,7 +7,7 @@ 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 @@ -54,533 +54,560 @@ import java.util.Set; * @see java.util.jar.Attributes.Name * @author Mark Wielaard (mark@klomp.org) */ -public class Attributes implements Cloneable, Map { +public class Attributes implements Cloneable, Map +{ + + // 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: + * <ul> + * <li> Must contain at least one character + * <li> The first character must be alphanumeric (a-z, A-Z, 0-9) + * <li> All other characters must be alphanumeric, a '-' or a '_' + * </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. + * + * @since 1.2 + * @author Mark Wielaard (mark@klomp.org) + */ + public static class Name + { // Fields + // General Main Attributes + /** - * 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. + * General main attribute - + * the version of this Manifest file. */ - protected Map map; - - // Inner class - + public static final Name MANIFEST_VERSION = new Name("Manifest-Version"); /** - * 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: - * <ul> - * <li> Must contain at least one character - * <li> The first character must be alphanumeric (a-z, A-Z, 0-9) - * <li> All other characters must be alphanumeric, a '-' or a '_' - * </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. - * - * @since 1.2 - * @author Mark Wielaard (mark@klomp.org) + * General main attribute - + * tool and version that created this Manifest file. */ - public static class Name { - - // Fields - - // General Main Attributes - - /** - * General main attribute - - * the version of this Manifest file. - */ - public static final Name MANIFEST_VERSION - = new Name("Manifest-Version"); - /** - * General main attribute - - * tool and version that created this Manifest file. - */ - public static final Name CREATED_BY - = new Name("Created-By"); - /** - * General main attribute - - * the version of the jar file signature. - */ - public static final Name SIGNATURE_VERSION - = new Name("Signature-Version"); - /** - * General main attribute - - * (relative) URLs of the libraries/classpaths that the Classes in - * this jar file depend on. - */ - 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> <extension>-Specification-Version: - * minimum specification version - * <li> <extension>-Implementation-Version: - * minimum implementation version - * <li> <extension>-Implementation-Vendor-Id: - * unique id of implementation vendor - * <li> <extension>-Implementation-URL: - * where the latest version of the extension library can be found - * </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"); - - /** - * Bean objects attribute - - * whether the entry is a Java Bean. Value is either "true" or "false". - */ - public static final Name JAVA_BEAN - = new Name("Java-Bean"); - - /** - * Signing attribute - - * application specific signing attribute. Must be understood by - * the manifest parser when present to validate the jar (entry). - */ - public static final Name MAGIC - = new Name("Magic"); - - /** 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++) { - 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 - + public static final Name CREATED_BY = new Name("Created-By"); /** - * Creates an empty Attributes map. + * General main attribute - + * the version of the jar file signature. */ - public Attributes() { - map = new Hashtable(); - } - + public static final Name SIGNATURE_VERSION + = new Name("Signature-Version"); /** - * Creates an empty Attributes map with the given initial size. - * @param size the initial size of the underlying map + * General main attribute - + * (relative) URLs of the libraries/classpaths that the Classes in + * this jar file depend on. */ - public Attributes(int size) { - map = new Hashtable(size); - } + public static final Name CLASS_PATH = new Name("Class-Path"); /** - * Creates an Attributes map with the initial values taken from another - * Attributes map. - * @param attr Attributes map to take the initial values from + * Stand alone application attribute - + * the entry (without the .class ending) that is the main + * class of this jar file. */ - public Attributes(Attributes attr) { - map = new Hashtable(attr.map); - } - - // Methods + public static final Name MAIN_CLASS = new Name("Main-Class"); /** - * 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 + * 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> <extension>-Specification-Version: + * minimum specification version + * <li> <extension>-Implementation-Version: + * minimum implementation version + * <li> <extension>-Implementation-Vendor-Id: + * unique id of implementation vendor + * <li> <extension>-Implementation-URL: + * where the latest version of the extension library can be found + * </ul> */ - public String getValue(String name) { - return (String)get(new Name(name)); - } + public static final Name EXTENSION_LIST = new Name("Extension-List"); /** - * 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 + * Extension identification attribute - + * the name if the extension library contained in the jar. */ - public String getValue(Name name) { - return (String)get(name); - } - + public static final Name EXTENSION_NAME = new Name("Extension-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 + * Extension identification attribute - + * synonym for <code>EXTENSTION_NAME</code>. */ - public String putValue(String name, String value) - { - return putValue(new Name(name), value); - } + public static final Name EXTENSION_INSTALLATION = EXTENSION_NAME; + // Package versioning and sealing attributes /** - * 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. - * <p> - * I don't know why there is no public method with this signature. I think - * there should be one. - * - * @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 + * Package versioning - + * name of extension library contained in this jar. */ - private String putValue(Name name, String value) - { - return (String)put(name, value); - } - - // Methods from Cloneable interface - + public static final Name IMPLEMENTATION_TITLE + = new Name("Implementation-Title"); /** - * Return a clone of this attribute map. + * Package versioning - + * version of the extension library contained in this jar. */ - public Object clone() { - return new Attributes(this); - } - - // Methods from Map interface - + public static final Name IMPLEMENTATION_VERSION + = new Name("Implementation-Version"); /** - * Removes all attributes. + * Package versioning - + * name of extension library creator contained in this jar. */ - public void clear() { - map.clear(); - } - + public static final Name IMPLEMENTATION_VENDOR + = new Name("Implementation-Vendor"); /** - * 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 + * Package versioning - + * unique id of extension library creator. */ - public boolean containsKey(Object attrName) { - return map.containsKey(attrName); - } - + public static final Name IMPLEMENTATION_VENDOR_ID + = new Name("Implementation-Vendor-Id"); /** - * 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 + * Package versioning - + * location where this implementation can be downloaded. */ - public boolean containsValue(Object attrValue) { - return map.containsValue(attrValue); - } - + public static final Name IMPLEMENTATION_URL + = new Name("Implementation-URL"); /** - * 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 + * Package versioning - + * title of the specification contained in this jar. */ - public Set entrySet() { - return map.entrySet(); - } - + public static final Name SPECIFICATION_TITLE + = new Name("Specification-Title"); /** - * 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 + * Package versioning - + * version of the specification contained in this jar. */ - 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; - } - } - + public static final Name SPECIFICATION_VERSION + = new Name("Specification-Version"); /** - * 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 + * Package versioning - + * organisation that maintains the specification contains in this + * jar. */ - public Object get(Object attrName) { - return map.get(attrName); - } - + public static final Name SPECIFICATION_VENDOR + = new Name("Specification-Vendor"); /** - * Returns the hashcode of the attribute name/value map. + * Package sealing - + * whether (all) package(s) is(/are) sealed. Value is either "true" + * or "false". */ - public int hashCode() { - return map.hashCode(); - } + public static final Name SEALED = new Name("Sealed"); /** - * Returns true if there are no attributes set, false otherwise. + * File contents attribute - + * Mime type and subtype for the jar entry. */ - public boolean isEmpty() { - return map.isEmpty(); - } + public static final Name CONTENT_TYPE = new Name("Content-Type"); /** - * Gives a Set of all the values of defined attribute names. + * Bean objects attribute - + * whether the entry is a Java Bean. Value is either "true" or "false". */ - public Set keySet() { - return map.keySet(); - } + public static final Name JAVA_BEAN = new Name("Java-Bean"); /** - * 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 + * Signing attribute - + * application specific signing attribute. Must be understood by + * the manifest parser when present to validate the jar (entry). */ - public Object put(Object name, Object value) { - return map.put(name, value); - } + public static final Name MAGIC = new Name("Magic"); + + /** The (lowercase) String representation of this Name */ + private final String name; + /** The original String given to the constructor */ + private final String origName; + + // Constructor /** - * 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 + * 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 void putAll(Map attr) { - if (!(attr instanceof Attributes)) { - throw new ClassCastException( - "Supplied Map is not an instance of Attributes"); - } - map.putAll(attr); + 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++) + { + 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(); } /** - * 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 + * Returns the hash code of the (lowercase) String representation of + * this Name. */ - public Object remove(Object name) { - return map.remove(name); + public int hashCode() + { + return name.hashCode(); } /** - * Returns the number of defined attribute name/value pairs. + * 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 int size() { - return map.size(); + 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 all the values of the defined attribute name/value pairs as a - * Collection. + * Returns the string representation of this Name as given to the + * constructor (not neccesarily the lower case representation). */ - public Collection values() { - return map.values(); + 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. + * <p> + * I don't know why there is no public method with this signature. I think + * there should be one. + * + * @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(); + } } diff --git a/libjava/java/util/jar/JarEntry.java b/libjava/java/util/jar/JarEntry.java index e15f1a4f336..7238d5b5164 100644 --- a/libjava/java/util/jar/JarEntry.java +++ b/libjava/java/util/jar/JarEntry.java @@ -7,7 +7,7 @@ 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 @@ -43,97 +43,112 @@ import java.util.zip.ZipEntry; * @since 1.2 * @author Mark Wielaard (mark@klomp.org) */ - -public class JarEntry extends ZipEntry { - - // (Packge local) fields - - Attributes attr; - Certificate certs[]; - - // Constructors - - /** - * Creates a new JarEntry with the specified name and no attributes or - * or certificates. Calls <code>super(name)</code> so all other (zip)entry - * fields are null or -1. - * - * @param name the name of the new jar entry - * @exception NullPointerException when the supplied name is null - * @exception IllegalArgumentException when the supplied name is longer - * than 65535 bytes - */ - public JarEntry(String name) throws NullPointerException, - IllegalArgumentException { - super(name); - attr = null; - certs = null; - } - - /** - * Creates a new JarEntry with the specified ZipEntry as template for - * all properties of the entry. Both attributes and certificates will be - * null. - * - * @param entry the ZipEntry whose fields should be copied - */ - public JarEntry(ZipEntry entry) { - super(entry); - attr = null; - certs = null; - } - - /** - * Creates a new JarEntry with the specified JarEntry as template for - * all properties of the entry. - * - * @param entry the jarEntry whose fields should be copied - */ - public JarEntry(JarEntry entry) { - super(entry); - try { - attr = entry.getAttributes(); - } catch(IOException _) {} - certs = entry.getCertificates(); - } - - // Methods - - /** - * Returns a copy of the Attributes set for this entry. - * When no Attributes are set in the manifest null is returned. - * - * @return a copy of the Attributes set for this entry - * @exception IOException This will never be thrown. It is here for - * binary compatibility. - */ - public Attributes getAttributes() throws IOException { - if (attr != null) { - return (Attributes) attr.clone(); - } else { - return null; - } - } - - /** - * Returns a copy of the certificates set for this entry. - * When no certificates are set or when not all data of this entry has - * been read null is returned. - * <p> - * To make sure that this call returns a valid value you must read all - * data from the JarInputStream for this entry. - * When you don't need the data for an entry but want to know the - * certificates that are set for the entry then you can skip all data by - * calling <code>skip(entry.getSize())</code> on the JarInputStream for - * the entry. - * - * @return a copy of the certificates set for this entry - */ - public Certificate[] getCertificates() { - if (certs != null) { - return (Certificate []) certs.clone(); - } else { - return null; - } - } + +public class JarEntry extends ZipEntry +{ + // (Packge local) fields + + Attributes attr; + Certificate certs[]; + + // Constructors + + /** + * Creates a new JarEntry with the specified name and no attributes or + * or certificates. Calls <code>super(name)</code> so all other (zip)entry + * fields are null or -1. + * + * @param name the name of the new jar entry + * @exception NullPointerException when the supplied name is null + * @exception IllegalArgumentException when the supplied name is longer + * than 65535 bytes + */ + public JarEntry(String name) throws NullPointerException, + IllegalArgumentException + { + super(name); + attr = null; + certs = null; + } + + /** + * Creates a new JarEntry with the specified ZipEntry as template for + * all properties of the entry. Both attributes and certificates will be + * null. + * + * @param entry the ZipEntry whose fields should be copied + */ + public JarEntry(ZipEntry entry) + { + super(entry); + attr = null; + certs = null; + } + + /** + * Creates a new JarEntry with the specified JarEntry as template for + * all properties of the entry. + * + * @param entry the jarEntry whose fields should be copied + */ + public JarEntry(JarEntry entry) + { + super(entry); + try + { + attr = entry.getAttributes(); + } + catch (IOException _) + { + } + certs = entry.getCertificates(); + } + + // Methods + + /** + * Returns a copy of the Attributes set for this entry. + * When no Attributes are set in the manifest null is returned. + * + * @return a copy of the Attributes set for this entry + * @exception IOException This will never be thrown. It is here for + * binary compatibility. + */ + public Attributes getAttributes() throws IOException + { + if (attr != null) + { + return (Attributes) attr.clone(); + } + else + { + return null; + } + } + + /** + * Returns a copy of the certificates set for this entry. + * When no certificates are set or when not all data of this entry has + * been read null is returned. + * <p> + * To make sure that this call returns a valid value you must read all + * data from the JarInputStream for this entry. + * When you don't need the data for an entry but want to know the + * certificates that are set for the entry then you can skip all data by + * calling <code>skip(entry.getSize())</code> on the JarInputStream for + * the entry. + * + * @return a copy of the certificates set for this entry + */ + public Certificate[] getCertificates() + { + if (certs != null) + { + return (Certificate[])certs.clone(); + } + else + { + return null; + } + } } diff --git a/libjava/java/util/jar/JarException.java b/libjava/java/util/jar/JarException.java index 827f9e2a904..2b73c054628 100644 --- a/libjava/java/util/jar/JarException.java +++ b/libjava/java/util/jar/JarException.java @@ -39,27 +39,29 @@ import java.util.zip.ZipException; * @since 1.2 * @author Mark Wielaard (mark@klomp.org) */ - -public class JarException extends ZipException { - // Constructors +public class JarException extends ZipException +{ + // Constructors - /** - * Create a new JarException without a descriptive error message. - */ - public JarException() { - super(); - } + /** + * Create a new JarException without a descriptive error message. + */ + public JarException() + { + super(); + } - /** - * Create a new JarException with a descriptive error message indicating - * what went wrong. This message can later be retrieved by calling the - * <code>getMessage()</code> method. - * @see java.lang.Throwable@getMessage() - * - * @param message The descriptive error message - */ - public JarException(String message) { - super(message); - } + /** + * Create a new JarException with a descriptive error message indicating + * what went wrong. This message can later be retrieved by calling the + * <code>getMessage()</code> method. + * @see java.lang.Throwable@getMessage() + * + * @param message The descriptive error message + */ + public JarException(String message) + { + super(message); + } } diff --git a/libjava/java/util/jar/JarFile.java b/libjava/java/util/jar/JarFile.java index 5e0f73b6c3b..588f1f85765 100644 --- a/libjava/java/util/jar/JarFile.java +++ b/libjava/java/util/jar/JarFile.java @@ -7,7 +7,7 @@ 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 @@ -47,231 +47,251 @@ import java.util.Enumeration; * @since 1.2 * @author Mark Wielaard (mark@klomp.org) */ -public class JarFile extends ZipFile { - - // Fields - - /** The name of the manifest entry: META-INF/MANIFEST.MF */ - public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; - - /** - * The manifest of this file, if any, otherwise null. - * Read by the constructor. - */ - private final Manifest manifest; +public class JarFile extends ZipFile +{ + // Fields - /** Wether to verify the manifest and all entries */ - private boolean verify; + /** The name of the manifest entry: META-INF/MANIFEST.MF */ + public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; - // Constructors + /** + * The manifest of this file, if any, otherwise null. + * Read by the constructor. + */ + private final Manifest manifest; - /** - * Creates a new JarFile, tries to read the manifest and if the manifest - * exists verifies it. - * - * @param fileName the name of the file to open - * @exception FileNotFoundException if the fileName cannot be found - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(String fileName) throws FileNotFoundException, - IOException { - this (fileName, true); - } + /** Wether to verify the manifest and all entries */ + private boolean verify; - /** - * Creates a new JarFile, tries to read the manifest and if the manifest - * exists and verify is true verfies it. - * - * @param fileName the name of the file to open - * @param verify checks manifest and entries when true and a manifest - * exists, when false no checks are made - * @exception FileNotFoundException if the fileName cannot be found - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(String fileName, boolean verify) throws - FileNotFoundException, - IOException { - super(fileName); - manifest = readManifest(); - if (verify) - verify(); - } + // Constructors - /** - * Creates a new JarFile, tries to read the manifest and if the manifest - * exists verifies it. - * - * @param file the file to open as a jar file - * @exception FileNotFoundException if the file does not exits - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(File file) throws FileNotFoundException, - IOException { - this (file, true); - } + /** + * Creates a new JarFile, tries to read the manifest and if the manifest + * exists verifies it. + * + * @param fileName the name of the file to open + * @exception FileNotFoundException if the fileName cannot be found + * @exception IOException if another IO exception occurs while reading + */ + public JarFile(String fileName) throws FileNotFoundException, IOException + { + this(fileName, true); + } - /** - * Creates a new JarFile, tries to read the manifest and if the manifest - * exists and verify is true verfies it. - * - * @param file the file to open to open as a jar file - * @param verify checks manifest and entries when true and a manifest - * exists, when false no checks are made - * @exception FileNotFoundException if file does not exist - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(File file, boolean verify) throws FileNotFoundException, - IOException { - super(file); - manifest = readManifest(); - if (verify) - verify(); - } + /** + * Creates a new JarFile, tries to read the manifest and if the manifest + * exists and verify is true verfies it. + * + * @param fileName the name of the file to open + * @param verify checks manifest and entries when true and a manifest + * exists, when false no checks are made + * @exception FileNotFoundException if the fileName cannot be found + * @exception IOException if another IO exception occurs while reading + */ + public JarFile(String fileName, boolean verify) throws + FileNotFoundException, IOException + { + super(fileName); + manifest = readManifest(); + if (verify) + verify(); + } - /** - * Creates a new JarFile with the indicated mode, tries to read the - * manifest and if the manifest exists and verify is true verfies it. - * - * @param file the file to open to open as a jar file - * @param verify checks manifest and entries when true and a manifest - * exists, when false no checks are made - * @param mode either ZipFile.OPEN_READ or - * (ZipFile.OPEN_READ | ZipFile.OPEN_DELETE) - * @exception FileNotFoundException if the file does not exist - * @exception IOException if another IO exception occurs while reading - * @exception IllegalArgumentException when given an illegal mode - * - * @since 1.3 - */ - public JarFile(File file, boolean verify, int mode) throws - FileNotFoundException, - IOException, - IllegalArgumentException { - super(file, mode); - manifest = readManifest(); - if (verify) - verify(); - } + /** + * Creates a new JarFile, tries to read the manifest and if the manifest + * exists verifies it. + * + * @param file the file to open as a jar file + * @exception FileNotFoundException if the file does not exits + * @exception IOException if another IO exception occurs while reading + */ + public JarFile(File file) throws FileNotFoundException, IOException + { + this(file, true); + } - // Methods + /** + * Creates a new JarFile, tries to read the manifest and if the manifest + * exists and verify is true verfies it. + * + * @param file the file to open to open as a jar file + * @param verify checks manifest and entries when true and a manifest + * exists, when false no checks are made + * @exception FileNotFoundException if file does not exist + * @exception IOException if another IO exception occurs while reading + */ + public JarFile(File file, boolean verify) throws FileNotFoundException, + IOException + { + super(file); + manifest = readManifest(); + if (verify) + verify(); + } - /** - * XXX - should verify the manifest file - */ - private void verify() { - // only check if manifest is not null - if (manifest == null) { - verify = false; - return; - } + /** + * Creates a new JarFile with the indicated mode, tries to read the + * manifest and if the manifest exists and verify is true verfies it. + * + * @param file the file to open to open as a jar file + * @param verify checks manifest and entries when true and a manifest + * exists, when false no checks are made + * @param mode either ZipFile.OPEN_READ or + * (ZipFile.OPEN_READ | ZipFile.OPEN_DELETE) + * @exception FileNotFoundException if the file does not exist + * @exception IOException if another IO exception occurs while reading + * @exception IllegalArgumentException when given an illegal mode + * + * @since 1.3 + */ + public JarFile(File file, boolean verify, int mode) throws + FileNotFoundException, IOException, IllegalArgumentException + { + super(file, mode); + manifest = readManifest(); + if (verify) + verify(); + } - verify = true; - // XXX - verify manifest - } + // Methods - /** - * Parses and returns the manifest if it exists, otherwise returns null. - */ - private Manifest readManifest() { - try { - ZipEntry manEntry = super.getEntry(MANIFEST_NAME); - if (manEntry != null) { - InputStream in = super.getInputStream(manEntry); - return new Manifest(in); - } else { - return null; - } - } catch (IOException ioe) { - return null; - } - } + /** + * XXX - should verify the manifest file + */ + private void verify() + { + // only check if manifest is not null + if (manifest == null) + { + verify = false; + return; + } - /** - * Returns a enumeration of all the entries in the JarFile. - * Note that also the Jar META-INF entries are returned. - * - * @exception IllegalStateException when the JarFile is already closed - */ - public Enumeration entries() throws IllegalStateException { - return new JarEnumeration(super.entries()); - } + verify = true; + // XXX - verify manifest + } - /** - * Wraps a given Zip Entries Enumeration. For every zip entry a - * JarEntry is created and the corresponding Attributes are looked up. - * XXX - Should also look up the certificates. - */ - private class JarEnumeration implements Enumeration { + /** + * Parses and returns the manifest if it exists, otherwise returns null. + */ + private Manifest readManifest() + { + try + { + ZipEntry manEntry = super.getEntry(MANIFEST_NAME); + if (manEntry != null) + { + InputStream in = super.getInputStream(manEntry); + return new Manifest(in); + } + else + { + return null; + } + } + catch (IOException ioe) + { + return null; + } + } - private final Enumeration entries; + /** + * Returns a enumeration of all the entries in the JarFile. + * Note that also the Jar META-INF entries are returned. + * + * @exception IllegalStateException when the JarFile is already closed + */ + public Enumeration entries() throws IllegalStateException + { + return new JarEnumeration(super.entries()); + } - JarEnumeration(Enumeration e) { - entries = e; - } + /** + * Wraps a given Zip Entries Enumeration. For every zip entry a + * JarEntry is created and the corresponding Attributes are looked up. + * XXX - Should also look up the certificates. + */ + private class JarEnumeration implements Enumeration + { - public boolean hasMoreElements() { - return entries.hasMoreElements(); - } + private final Enumeration entries; - public Object nextElement() { - ZipEntry zip = (ZipEntry) entries.nextElement(); - JarEntry jar = new JarEntry(zip); - if (manifest != null) { - jar.attr = manifest.getAttributes(jar.getName()); - } - // XXX jar.certs - return jar; - } + JarEnumeration(Enumeration e) + { + entries = e; } - /** - * XXX - * It actually returns a JarEntry not a zipEntry - * @param name XXX - */ - public ZipEntry getEntry(String name) { - ZipEntry entry = super.getEntry(name); - if (entry != null) { - JarEntry jarEntry = new JarEntry(entry); - if (manifest != null) { - jarEntry.attr = manifest.getAttributes(name); - // XXX jarEntry.certs - } - return jarEntry; - } - return null; + public boolean hasMoreElements() + { + return entries.hasMoreElements(); } - /** - * XXX should verify the inputstream - * @param entry XXX - * @exception ZipException XXX - * @exception IOException XXX - */ - public synchronized InputStream getInputStream(ZipEntry entry) throws - ZipException, - IOException { - return super.getInputStream(entry); // XXX verify + public Object nextElement() + { + ZipEntry zip = (ZipEntry) entries.nextElement(); + JarEntry jar = new JarEntry(zip); + if (manifest != null) + { + jar.attr = manifest.getAttributes(jar.getName()); + } + // XXX jar.certs + return jar; } + } - /** - * Returns the JarEntry that belongs to the name if such an entry - * exists in the JarFile. Returns null otherwise - * Convenience method that just casts the result from <code>getEntry</code> - * to a JarEntry. - * - * @param name the jar entry name to look up - * @return the JarEntry if it exists, null otherwise - */ - public JarEntry getJarEntry(String name) { - return (JarEntry)getEntry(name); - } + /** + * XXX + * It actually returns a JarEntry not a zipEntry + * @param name XXX + */ + public ZipEntry getEntry(String name) + { + ZipEntry entry = super.getEntry(name); + if (entry != null) + { + JarEntry jarEntry = new JarEntry(entry); + if (manifest != null) + { + jarEntry.attr = manifest.getAttributes(name); + // XXX jarEntry.certs + } + return jarEntry; + } + return null; + } - /** - * Returns the manifest for this JarFile or null when the JarFile does not - * contain a manifest file. - */ - public Manifest getManifest() { - return manifest; - } + /** + * XXX should verify the inputstream + * @param entry XXX + * @exception ZipException XXX + * @exception IOException XXX + */ + public synchronized InputStream getInputStream(ZipEntry entry) throws + ZipException, IOException + { + return super.getInputStream(entry); // XXX verify + } + + /** + * Returns the JarEntry that belongs to the name if such an entry + * exists in the JarFile. Returns null otherwise + * Convenience method that just casts the result from <code>getEntry</code> + * to a JarEntry. + * + * @param name the jar entry name to look up + * @return the JarEntry if it exists, null otherwise + */ + public JarEntry getJarEntry(String name) + { + return (JarEntry) getEntry(name); + } + + /** + * Returns the manifest for this JarFile or null when the JarFile does not + * contain a manifest file. + */ + public Manifest getManifest() + { + return manifest; + } } diff --git a/libjava/java/util/jar/JarInputStream.java b/libjava/java/util/jar/JarInputStream.java index c8f5340637b..c63758e4daf 100644 --- a/libjava/java/util/jar/JarInputStream.java +++ b/libjava/java/util/jar/JarInputStream.java @@ -7,7 +7,7 @@ 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 @@ -39,137 +39,152 @@ import java.util.zip.ZipInputStream; * @since 1.2 * @author Mark Wielaard (mark@klomp.org) */ - -public class JarInputStream extends ZipInputStream { - - // Fields - - /** The manifest for this file or null when there was no manifest. */ - private Manifest manifest; - - /** The first real JarEntry for this file. Used by readManifest() to store - an entry that isn't the manifest but that should be returned by - getNextEntry next time it is called. Null when no firstEntry was read - while searching for the manifest entry, or when it has already been - returned by getNextEntry(). */ - private JarEntry firstEntry; - - // Constructors - - /** - * Creates a new JarInputStream and tries to read the manifest. - * If such a manifest is present the JarInputStream tries to verify all - * the entry signatures while reading. - * - * @param in InputStream to read the jar from - * @exception IOException when an error occurs when opening or reading - */ - public JarInputStream(InputStream in) throws IOException { - this(in, true); - } - - /** - * Creates a new JarInputStream and tries to read the manifest. - * If such a manifest is present and verify is true, the JarInputStream - * tries to verify all the entry signatures while reading. - * - * @param in InputStream to read the jar from - * @param verify wheter or not to verify the manifest entries - * @exception IOException when an error occurs when opening or reading - */ - public JarInputStream(InputStream in, boolean verify) throws IOException { - super(in); - readManifest(verify); - } - - // Methods - - /** - * Set the manifest if found. Skips all entries that start with "META-INF/" - * - * @param verify when true (and a Manifest is found) checks the Manifest, - * when false no check is performed - * @exception IOException if an error occurs while reading - */ - private void readManifest(boolean verify) throws IOException { - firstEntry = (JarEntry) super.getNextEntry(); - while ((firstEntry != null) && - firstEntry.getName().startsWith("META-INF/")) { - if(firstEntry.getName().equals(JarFile.MANIFEST_NAME)) { - manifest = new Manifest(this); - } - firstEntry = (JarEntry) super.getNextEntry(); - } - closeEntry(); - - if (verify) { - // XXX - } - } - - /** - * Creates a JarEntry for a particular name and consults the manifest - * for the Attributes of the entry. - * Used by <code>ZipEntry.getNextEntry()</code> - * - * @param name the name of the new entry - */ - protected ZipEntry createZipEntry(String name) { - ZipEntry zipEntry = super.createZipEntry(name); - JarEntry jarEntry = new JarEntry(zipEntry); - if (manifest != null) { - jarEntry.attr = manifest.getAttributes(name); - } - return jarEntry; - } - - /** - * Returns the Manifest for the jar file or null if there was no Manifest. - */ - public Manifest getManifest() { - return manifest; - } - - /** - * Returns the next entry or null when there are no more entries. - * Does actually return a JarEntry, if you don't want to cast it yourself - * use <code>getNextJarEntry()</code>. Does not return any entries found - * at the beginning of the ZipFile that are special - * (those that start with "META-INF/"). - * - * @exception IOException if an IO error occurs when reading the entry - */ - public ZipEntry getNextEntry() throws IOException { - ZipEntry entry; - if (firstEntry != null) { - entry = firstEntry; - firstEntry = null; - } else { - entry = super.getNextEntry(); - } - return entry; - } - - /** - * Returns the next jar entry or null when there are no more entries. - * - * @exception IOException if an IO error occurs when reading the entry - */ - public JarEntry getNextJarEntry() throws IOException { - return (JarEntry)getNextEntry(); - } - - /** - * XXX - * - * @param buf XXX - * @param off XXX - * @param len XXX - * @return XXX - * @exception IOException XXX - */ - public int read(byte[] buf, int off, int len) throws IOException { - // XXX if (verify) {} - return super.read(buf, off, len); - } + +public class JarInputStream extends ZipInputStream +{ + // Fields + + /** The manifest for this file or null when there was no manifest. */ + private Manifest manifest; + + /** The first real JarEntry for this file. Used by readManifest() to store + an entry that isn't the manifest but that should be returned by + getNextEntry next time it is called. Null when no firstEntry was read + while searching for the manifest entry, or when it has already been + returned by getNextEntry(). */ + private JarEntry firstEntry; + + // Constructors + + /** + * Creates a new JarInputStream and tries to read the manifest. + * If such a manifest is present the JarInputStream tries to verify all + * the entry signatures while reading. + * + * @param in InputStream to read the jar from + * @exception IOException when an error occurs when opening or reading + */ + public JarInputStream(InputStream in) throws IOException + { + this(in, true); + } + + /** + * Creates a new JarInputStream and tries to read the manifest. + * If such a manifest is present and verify is true, the JarInputStream + * tries to verify all the entry signatures while reading. + * + * @param in InputStream to read the jar from + * @param verify wheter or not to verify the manifest entries + * @exception IOException when an error occurs when opening or reading + */ + public JarInputStream(InputStream in, boolean verify) throws IOException + { + super(in); + readManifest(verify); + } + + // Methods + + /** + * Set the manifest if found. Skips all entries that start with "META-INF/" + * + * @param verify when true (and a Manifest is found) checks the Manifest, + * when false no check is performed + * @exception IOException if an error occurs while reading + */ + private void readManifest(boolean verify) throws IOException + { + firstEntry = (JarEntry) super.getNextEntry(); + while ((firstEntry != null) && + firstEntry.getName().startsWith("META-INF/")) + { + if (firstEntry.getName().equals(JarFile.MANIFEST_NAME)) + { + manifest = new Manifest(this); + } + firstEntry = (JarEntry) super.getNextEntry(); + } + closeEntry(); + + if (verify) + { + // XXX + } + } + + /** + * Creates a JarEntry for a particular name and consults the manifest + * for the Attributes of the entry. + * Used by <code>ZipEntry.getNextEntry()</code> + * + * @param name the name of the new entry + */ + protected ZipEntry createZipEntry(String name) + { + ZipEntry zipEntry = super.createZipEntry(name); + JarEntry jarEntry = new JarEntry(zipEntry); + if (manifest != null) + { + jarEntry.attr = manifest.getAttributes(name); + } + return jarEntry; + } + + /** + * Returns the Manifest for the jar file or null if there was no Manifest. + */ + public Manifest getManifest() + { + return manifest; + } + + /** + * Returns the next entry or null when there are no more entries. + * Does actually return a JarEntry, if you don't want to cast it yourself + * use <code>getNextJarEntry()</code>. Does not return any entries found + * at the beginning of the ZipFile that are special + * (those that start with "META-INF/"). + * + * @exception IOException if an IO error occurs when reading the entry + */ + public ZipEntry getNextEntry() throws IOException + { + ZipEntry entry; + if (firstEntry != null) + { + entry = firstEntry; + firstEntry = null; + } + else + { + entry = super.getNextEntry(); + } + return entry; + } + + /** + * Returns the next jar entry or null when there are no more entries. + * + * @exception IOException if an IO error occurs when reading the entry + */ + public JarEntry getNextJarEntry() throws IOException + { + return (JarEntry) getNextEntry(); + } + + /** + * XXX + * + * @param buf XXX + * @param off XXX + * @param len XXX + * @return XXX + * @exception IOException XXX + */ + public int read(byte[]buf, int off, int len) throws IOException + { + // XXX if (verify) {} + return super.read(buf, off, len); + } } diff --git a/libjava/java/util/jar/JarOutputStream.java b/libjava/java/util/jar/JarOutputStream.java index 78bb35979ea..ca7729df02e 100644 --- a/libjava/java/util/jar/JarOutputStream.java +++ b/libjava/java/util/jar/JarOutputStream.java @@ -7,7 +7,7 @@ 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 @@ -38,61 +38,65 @@ import java.util.zip.ZipOutputStream; * * @author Mark Wielaard (mark@klomp.org) */ - -public class JarOutputStream extends ZipOutputStream { - // Constructors +public class JarOutputStream extends ZipOutputStream +{ + // Constructors - /** - * Creates a new JarOutputStream without a manifest entry. - * - * @param out the stream to create the new jar on - * @exception IOException if something unexpected happend - */ - public JarOutputStream(OutputStream out) throws IOException { - this(out, null); - } + /** + * Creates a new JarOutputStream without a manifest entry. + * + * @param out the stream to create the new jar on + * @exception IOException if something unexpected happend + */ + public JarOutputStream(OutputStream out) throws IOException + { + this(out, null); + } - /** - * Creates a new JarOutputStream with a manifest entry. - * The manifest will be the first entry in the jar. - * - * @param out the stream to create the new jar on - * @param man the manifest that should be put in the jar file or null - * for no manifest entry - * @exception IOException if something unexpected happend - */ - public JarOutputStream(OutputStream out, Manifest man) throws IOException { - super(out); - if (man != null) - writeManifest(man); - } + /** + * Creates a new JarOutputStream with a manifest entry. + * The manifest will be the first entry in the jar. + * + * @param out the stream to create the new jar on + * @param man the manifest that should be put in the jar file or null + * for no manifest entry + * @exception IOException if something unexpected happend + */ + public JarOutputStream(OutputStream out, Manifest man) throws IOException + { + super(out); + if (man != null) + writeManifest(man); + } - // Methods + // Methods - /** - * Writes the manifest to a new JarEntry in this JarOutputStream with as - * name JarFile.MANIFEST_NAME. - * - * @param manifest the non null manifest to be written - * @exception IOException if something unexpected happend - */ - private void writeManifest(Manifest manifest) throws IOException { - // Create a new Jar Entry for the Manifest - JarEntry entry = new JarEntry(JarFile.MANIFEST_NAME); - putNextEntry(entry); - manifest.write(this); - closeEntry(); - } + /** + * Writes the manifest to a new JarEntry in this JarOutputStream with as + * name JarFile.MANIFEST_NAME. + * + * @param manifest the non null manifest to be written + * @exception IOException if something unexpected happend + */ + private void writeManifest(Manifest manifest) throws IOException + { + // Create a new Jar Entry for the Manifest + JarEntry entry = new JarEntry(JarFile.MANIFEST_NAME); + putNextEntry(entry); + manifest.write(this); + closeEntry(); + } - /** - * Prepares the JarOutputStream for writing the next entry. - * This implementation just calls <code>super.putNextEntre()</code>. - * - * @param entry The information for the next entry - * @exception IOException when some unexpected I/O exception occured - */ - public void putNextEntry(ZipEntry entry) throws IOException { - super.putNextEntry(entry); // XXX - } + /** + * Prepares the JarOutputStream for writing the next entry. + * This implementation just calls <code>super.putNextEntre()</code>. + * + * @param entry The information for the next entry + * @exception IOException when some unexpected I/O exception occured + */ + public void putNextEntry(ZipEntry entry) throws IOException + { + super.putNextEntry(entry); // XXX + } } diff --git a/libjava/java/util/jar/Manifest.java b/libjava/java/util/jar/Manifest.java index a4034e2c65c..833ac26540d 100644 --- a/libjava/java/util/jar/Manifest.java +++ b/libjava/java/util/jar/Manifest.java @@ -7,7 +7,7 @@ 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 @@ -48,359 +48,408 @@ import java.util.Set; * @since 1.2 * @author Mark Wielaard (mark@klomp.org) */ -public class Manifest implements Cloneable { - - // Fields - - /** The main attributes of the manifest (jar file). */ - private final Attributes mainAttr; - - /** A map of atrributes for all entries described in this Manifest. */ - private final Map entries; - - // Constructors - - /** - * Creates a new empty Manifest. - */ - public Manifest() { - mainAttr = new Attributes(); - entries = new Hashtable(); - } - - /** - * Creates a Manifest from the supplied input stream. - * - * @see read(Inputstream) - * @see write(OutputStream) - * - * @param InputStream the input stream to read the manifest from - * @exception IOException when an i/o exception occurs or the input stream - * does not describe a valid manifest - */ - public Manifest(InputStream in) throws IOException { - this(); - read(in); - } - - /** - * Creates a Manifest from another Manifest. - * Makes a deep copy of the main attributes, but a shallow copy of - * the other entries. This means that you can freely add, change or remove - * the main attributes or the entries of the new manifest without effecting - * the original manifest, but adding, changing or removing attributes from - * a particular entry also changes the attributes of that entry in the - * original manifest. - * - * @see clone() - * @param man the Manifest to copy from - */ - public Manifest (Manifest man) { - mainAttr = new Attributes(man.getMainAttributes()); - entries = new Hashtable(man.getEntries()); - } - - // Methods - - /** - * Gets the main attributes of this Manifest. - */ - public Attributes getMainAttributes() { - return mainAttr; - } - - /** - * Gets a map of entry Strings to Attributes for all the entries described - * in this manifest. Adding, changing or removing from this entries map - * changes the entries of this manifest. - */ - public Map getEntries() { - return entries; - } - - /** - * Returns the Attributes associated with the Entry. - * <p> - * Implemented as: - * <code>return (Attributes)getEntries().get(entryName)</code> - * - * @param entryName the name of the entry to look up - * @return the attributes associated with the entry or null when none - */ - public Attributes getAttributes(String entryName) { - return (Attributes)getEntries().get(entryName); - } - - /** - * Clears the main attributes and removes all the entries from the - * manifest. - */ - public void clear() { - mainAttr.clear(); - entries.clear(); - } - - /** - * XXX - */ - public void read(InputStream in) throws IOException { - BufferedReader br = new BufferedReader( - new InputStreamReader(in, "8859_1")); - read_main_section(getMainAttributes(), br); - read_individual_sections(getEntries(), br); - } - - // Private Static methods for reading the Manifest file from BufferedReader - - private static void read_main_section(Attributes attr, - BufferedReader br) throws - IOException { - read_version_info(attr, br); - read_attributes(attr, br); - } - - private static void read_version_info(Attributes attr, - BufferedReader br) throws - IOException { - String version_header = Attributes.Name.MANIFEST_VERSION.toString(); - try { - String value = expect_header(version_header, br); - attr.putValue(version_header, value); - } catch (IOException ioe) { - throw new JarException( - "Manifest should start with a " + version_header - + ": " + ioe.getMessage()); - } - } - - private static String expect_header(String header, BufferedReader br) - throws IOException { - - String s = br.readLine(); - if (s == null) { - throw new JarException("unexpected end of file"); - } - return expect_header(header, br, s); - } - - private static String expect_header(String header, BufferedReader br, - String s) throws IOException { - try { - String name = s.substring(0, header.length() + 1); - if (name.equalsIgnoreCase(header + ":")) { - String value_start = s.substring(header.length() + 2); - return read_header_value(value_start, br); - } - } catch (IndexOutOfBoundsException iobe) {} - // If we arrive here, something went wrong - throw new JarException("unexpected '" + s + "'"); - } - - private static String read_header_value(String s, BufferedReader br) - throws IOException { - boolean try_next = true; - while (try_next) { - // Lets see if there is something on the next line - br.mark(1); - if (br.read() == ' ') { - s += br.readLine(); - } else { - br.reset(); - try_next = false; - } - } - return s; - } - - private static void read_attributes(Attributes attr, - BufferedReader br) throws - IOException { - String s = br.readLine(); - while (s != null && (!s.equals(""))) { - read_attribute(attr, s, br); - s = br.readLine(); - } - } - - private static void read_attribute(Attributes attr, String s, - BufferedReader br) throws IOException { - try { - int colon = s.indexOf(": "); - String name = s.substring(0, colon); - String value_start = s.substring(colon+2); - String value = read_header_value(value_start, br); - attr.putValue(name, value); - } catch (IndexOutOfBoundsException iobe) { - throw new JarException( - "Manifest contains a bad header: " + s); - } - } - - private static void read_individual_sections(Map entries, - BufferedReader br) throws - IOException { - String s = br.readLine(); - while (s != null && (!s.equals(""))) { - Attributes attr = read_section_name(s, br, entries); - read_attributes(attr, br); - s = br.readLine(); - } - } - - private static Attributes read_section_name(String s, BufferedReader br, - Map entries) throws - JarException { - try { - String name = expect_header("Name", br, s); - Attributes attr = new Attributes(); - entries.put(name, attr); - return attr; - } catch(IOException ioe) { - throw new JarException - ("Section should start with a Name header: " - + ioe.getMessage()); - } - } - - /** - * XXX - */ - public void write(OutputStream out) throws IOException { - PrintWriter pw = new PrintWriter( - new BufferedWriter( - new OutputStreamWriter(out, "8859_1"))); - write_main_section(getMainAttributes(), pw); - pw.println(); - write_individual_sections(getEntries(), pw); - if (pw.checkError()) { - throw new JarException("Error while writing manifest"); - } - } - - // Private Static functions for writing the Manifest file to a PrintWriter - - private static void write_main_section(Attributes attr, - PrintWriter pw) - throws JarException { - - write_version_info(attr, pw); - write_main_attributes(attr, pw); - } - - private static void write_version_info(Attributes attr, PrintWriter pw) { - // First check if there is already a version attribute set - String version = attr.getValue(Attributes.Name.MANIFEST_VERSION); - if (version == null) { - version = "1.0"; - } - write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, pw); - } - - private static void write_header(String name, String value, - PrintWriter pw) { - pw.print(name + ": "); - - int last = 68 - name.length(); - if (last > value.length()) { - pw.println(value); - } else { - pw.println(value.substring(0, last)); - } - while (last < value.length()) { - pw.print(" "); - int end = (last + 69); - if (end > value.length()) { - pw.println(value.substring(last)); - } else { - pw.println(value.substring(last, end)); - } - last = end; - } - } - - private static void write_main_attributes(Attributes attr, - PrintWriter pw) throws - JarException { - Iterator it = attr.entrySet().iterator(); - while(it.hasNext()) { - Map.Entry entry = (Map.Entry)it.next(); - // Don't print the manifest version again - if (!Attributes.Name.MANIFEST_VERSION.equals(entry.getKey())) { - write_attribute_entry(entry, pw); - } - } - } - - private static void write_attribute_entry(Map.Entry entry, - PrintWriter pw) throws - JarException { - String name = entry.getKey().toString(); - String value = entry.getValue().toString(); - - if (name.equalsIgnoreCase("Name")) { - throw new JarException("Attributes cannot be called 'Name'"); - } - if (name.startsWith("From")) { - throw new JarException( - "Header cannot start with the four letters 'From'" - + name); - } - write_header(name, value, pw); - } - - private static void write_individual_sections(Map entries, - PrintWriter pw) - throws JarException { - - Iterator it = entries.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry)it.next(); - write_header("Name", entry.getKey().toString(), pw); - write_entry_attributes((Attributes)entry.getValue(), pw); - pw.println(); - } - } - - private static void write_entry_attributes(Attributes attr, - PrintWriter pw) throws - JarException { - Iterator it = attr.entrySet().iterator(); - while(it.hasNext()) { - Map.Entry entry = (Map.Entry)it.next(); - write_attribute_entry(entry, pw); - } - } - - /** - * Makes a deep copy of the main attributes, but a shallow copy of - * the other entries. This means that you can freely add, change or remove - * the main attributes or the entries of the new manifest without effecting - * the original manifest, but adding, changing or removing attributes from - * a particular entry also changes the attributes of that entry in the - * original manifest. Calls <CODE>new Manifest(this)</CODE>. - */ - public Object clone() { - return new Manifest(this); - } - - /** - * Checks if another object is equal to this Manifest object. - * Another Object is equal to this Manifest object if it is an instance of - * Manifest and the main attributes and the entries of the other manifest - * are equal to this one. - */ - public boolean equals(Object o) { - return (o instanceof Manifest) && - (mainAttr.equals(((Manifest)o).mainAttr)) && - (entries.equals(((Manifest)o).entries)); - } - - /** - * Calculates the hash code of the manifest. Implemented by a xor of the - * hash code of the main attributes with the hash code of the entries map. - */ - public int hashCode() { - return mainAttr.hashCode() ^ entries.hashCode(); - } +public class Manifest implements Cloneable +{ + // Fields + + /** The main attributes of the manifest (jar file). */ + private final Attributes mainAttr; + + /** A map of atrributes for all entries described in this Manifest. */ + private final Map entries; + + // Constructors + + /** + * Creates a new empty Manifest. + */ + public Manifest() + { + mainAttr = new Attributes(); + entries = new Hashtable(); + } + + /** + * Creates a Manifest from the supplied input stream. + * + * @see read(Inputstream) + * @see write(OutputStream) + * + * @param InputStream the input stream to read the manifest from + * @exception IOException when an i/o exception occurs or the input stream + * does not describe a valid manifest + */ + public Manifest(InputStream in) throws IOException + { + this(); + read(in); + } + + /** + * Creates a Manifest from another Manifest. + * Makes a deep copy of the main attributes, but a shallow copy of + * the other entries. This means that you can freely add, change or remove + * the main attributes or the entries of the new manifest without effecting + * the original manifest, but adding, changing or removing attributes from + * a particular entry also changes the attributes of that entry in the + * original manifest. + * + * @see clone() + * @param man the Manifest to copy from + */ + public Manifest(Manifest man) + { + mainAttr = new Attributes(man.getMainAttributes()); + entries = new Hashtable(man.getEntries()); + } + + // Methods + + /** + * Gets the main attributes of this Manifest. + */ + public Attributes getMainAttributes() + { + return mainAttr; + } + + /** + * Gets a map of entry Strings to Attributes for all the entries described + * in this manifest. Adding, changing or removing from this entries map + * changes the entries of this manifest. + */ + public Map getEntries() + { + return entries; + } + + /** + * Returns the Attributes associated with the Entry. + * <p> + * Implemented as: + * <code>return (Attributes)getEntries().get(entryName)</code> + * + * @param entryName the name of the entry to look up + * @return the attributes associated with the entry or null when none + */ + public Attributes getAttributes(String entryName) + { + return (Attributes) getEntries().get(entryName); + } + + /** + * Clears the main attributes and removes all the entries from the + * manifest. + */ + public void clear() + { + mainAttr.clear(); + entries.clear(); + } + + /** + * XXX + */ + public void read(InputStream in) throws IOException + { + BufferedReader br = + new BufferedReader(new InputStreamReader(in, "8859_1")); + read_main_section(getMainAttributes(), br); + read_individual_sections(getEntries(), br); + } + + // Private Static methods for reading the Manifest file from BufferedReader + + private static void read_main_section(Attributes attr, + BufferedReader br) throws IOException + { + read_version_info(attr, br); + read_attributes(attr, br); + } + + private static void read_version_info(Attributes attr, + BufferedReader br) throws IOException + { + String version_header = Attributes.Name.MANIFEST_VERSION.toString(); + try + { + String value = expect_header(version_header, br); + attr.putValue(version_header, value); + } + catch (IOException ioe) + { + throw new JarException("Manifest should start with a " + + version_header + ": " + ioe.getMessage()); + } + } + + private static String expect_header(String header, BufferedReader br) + throws IOException + { + String s = br.readLine(); + if (s == null) + { + throw new JarException("unexpected end of file"); + } + return expect_header(header, br, s); + } + + private static String expect_header(String header, BufferedReader br, + String s) throws IOException + { + try + { + String name = s.substring(0, header.length() + 1); + if (name.equalsIgnoreCase(header + ":")) + { + String value_start = s.substring(header.length() + 2); + return read_header_value(value_start, br); + } + } + catch (IndexOutOfBoundsException iobe) + { + } + // If we arrive here, something went wrong + throw new JarException("unexpected '" + s + "'"); + } + + private static String read_header_value(String s, BufferedReader br) + throws IOException + { + boolean try_next = true; + while (try_next) + { + // Lets see if there is something on the next line + br.mark(1); + if (br.read() == ' ') + { + s += br.readLine(); + } + else + { + br.reset(); + try_next = false; + } + } + return s; + } + + private static void read_attributes(Attributes attr, + BufferedReader br) throws IOException + { + String s = br.readLine(); + while (s != null && (!s.equals(""))) + { + read_attribute(attr, s, br); + s = br.readLine(); + } + } + + private static void read_attribute(Attributes attr, String s, + BufferedReader br) throws IOException + { + try + { + int colon = s.indexOf(": "); + String name = s.substring(0, colon); + String value_start = s.substring(colon + 2); + String value = read_header_value(value_start, br); + attr.putValue(name, value); + } + catch (IndexOutOfBoundsException iobe) + { + throw new JarException("Manifest contains a bad header: " + s); + } + } + + private static void read_individual_sections(Map entries, + BufferedReader br) throws + IOException + { + String s = br.readLine(); + while (s != null && (!s.equals(""))) + { + Attributes attr = read_section_name(s, br, entries); + read_attributes(attr, br); + s = br.readLine(); + } + } + + private static Attributes read_section_name(String s, BufferedReader br, + Map entries) throws JarException + { + try + { + String name = expect_header("Name", br, s); + Attributes attr = new Attributes(); + entries.put(name, attr); + return attr; + } + catch (IOException ioe) + { + throw new JarException + ("Section should start with a Name header: " + ioe.getMessage()); + } + } + + /** + * XXX + */ + public void write(OutputStream out) throws IOException + { + PrintWriter pw = + new PrintWriter(new + BufferedWriter(new OutputStreamWriter(out, "8859_1"))); + write_main_section(getMainAttributes(), pw); + pw.println(); + write_individual_sections(getEntries(), pw); + if (pw.checkError()) + { + throw new JarException("Error while writing manifest"); + } + } + + // Private Static functions for writing the Manifest file to a PrintWriter + + private static void write_main_section(Attributes attr, + PrintWriter pw) throws JarException + { + write_version_info(attr, pw); + write_main_attributes(attr, pw); + } + + private static void write_version_info(Attributes attr, PrintWriter pw) + { + // First check if there is already a version attribute set + String version = attr.getValue(Attributes.Name.MANIFEST_VERSION); + if (version == null) + { + version = "1.0"; + } + write_header(Attributes.Name.MANIFEST_VERSION.toString(), version, pw); + } + + private static void write_header(String name, String value, PrintWriter pw) + { + pw.print(name + ": "); + + int last = 68 - name.length(); + if (last > value.length()) + { + pw.println(value); + } + else + { + pw.println(value.substring(0, last)); + } + while (last < value.length()) + { + pw.print(" "); + int end = (last + 69); + if (end > value.length()) + { + pw.println(value.substring(last)); + } + else + { + pw.println(value.substring(last, end)); + } + last = end; + } + } + + private static void write_main_attributes(Attributes attr, PrintWriter pw) + throws JarException + { + Iterator it = attr.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry entry = (Map.Entry) it.next(); + // Don't print the manifest version again + if (!Attributes.Name.MANIFEST_VERSION.equals(entry.getKey())) + { + write_attribute_entry(entry, pw); + } + } + } + + private static void write_attribute_entry(Map.Entry entry, PrintWriter pw) + throws JarException + { + String name = entry.getKey().toString(); + String value = entry.getValue().toString(); + + if (name.equalsIgnoreCase("Name")) + { + throw new JarException("Attributes cannot be called 'Name'"); + } + if (name.startsWith("From")) + { + throw new + JarException("Header cannot start with the four letters 'From'" + + name); + } + write_header(name, value, pw); + } + + private static void write_individual_sections(Map entries, PrintWriter pw) + throws JarException + { + + Iterator it = entries.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry entry = (Map.Entry) it.next(); + write_header("Name", entry.getKey().toString(), pw); + write_entry_attributes((Attributes) entry.getValue(), pw); + pw.println(); + } + } + + private static void write_entry_attributes(Attributes attr, PrintWriter pw) + throws JarException + { + Iterator it = attr.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry entry = (Map.Entry) it.next(); + write_attribute_entry(entry, pw); + } + } + + /** + * Makes a deep copy of the main attributes, but a shallow copy of + * the other entries. This means that you can freely add, change or remove + * the main attributes or the entries of the new manifest without effecting + * the original manifest, but adding, changing or removing attributes from + * a particular entry also changes the attributes of that entry in the + * original manifest. Calls <CODE>new Manifest(this)</CODE>. + */ + public Object clone() + { + return new Manifest(this); + } + + /** + * Checks if another object is equal to this Manifest object. + * Another Object is equal to this Manifest object if it is an instance of + * Manifest and the main attributes and the entries of the other manifest + * are equal to this one. + */ + public boolean equals(Object o) + { + return (o instanceof Manifest) && + (mainAttr.equals(((Manifest) o).mainAttr)) && + (entries.equals(((Manifest) o).entries)); + } + + /** + * Calculates the hash code of the manifest. Implemented by a xor of the + * hash code of the main attributes with the hash code of the entries map. + */ + public int hashCode() + { + return mainAttr.hashCode() ^ entries.hashCode(); + } } |