diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-16 01:27:14 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-16 01:27:14 +0000 |
commit | a63c2657c94913d72b3cd388730d61edcb09fc69 (patch) | |
tree | 8762d1f992e2f725a6bde1ff966ed6f1e5f4f823 /libjava/java/util/jar | |
parent | 6484dceb0094998183c2f8d3c8c27c6f4e53b8a9 (diff) | |
download | gcc-a63c2657c94913d72b3cd388730d61edcb09fc69.tar.gz |
Major merge with Classpath.
Removed many duplicate files.
* HACKING: Updated.x
* classpath: Imported new directory.
* standard.omit: New file.
* Makefile.in, aclocal.m4, configure: Rebuilt.
* sources.am: New file.
* configure.ac: Run Classpath configure script. Moved code around
to support. Disable xlib AWT peers (temporarily).
* Makefile.am (SUBDIRS): Added 'classpath'
(JAVAC): Removed.
(AM_CPPFLAGS): Added more -I options.
(BOOTCLASSPATH): Simplified.
Completely redid how sources are built.
Include sources.am.
* include/Makefile.am (tool_include__HEADERS): Removed jni.h.
* include/jni.h: Removed (in Classpath).
* scripts/classes.pl: Updated to look at built classes.
* scripts/makemake.tcl: New file.
* testsuite/libjava.jni/jni.exp (gcj_jni_compile_c_to_so): Added
-I options.
(gcj_jni_invocation_compile_c_to_binary): Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102082 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/java/util/jar')
-rw-r--r-- | libjava/java/util/jar/Attributes.java | 630 | ||||
-rw-r--r-- | libjava/java/util/jar/JarEntry.java | 165 | ||||
-rw-r--r-- | libjava/java/util/jar/JarException.java | 77 | ||||
-rw-r--r-- | libjava/java/util/jar/JarFile.java | 1058 | ||||
-rw-r--r-- | libjava/java/util/jar/JarInputStream.java | 200 | ||||
-rw-r--r-- | libjava/java/util/jar/JarOutputStream.java | 113 | ||||
-rw-r--r-- | libjava/java/util/jar/Manifest.java | 472 |
7 files changed, 0 insertions, 2715 deletions
diff --git a/libjava/java/util/jar/Attributes.java b/libjava/java/util/jar/Attributes.java deleted file mode 100644 index 4db2c72e75b..00000000000 --- a/libjava/java/util/jar/Attributes.java +++ /dev/null @@ -1,630 +0,0 @@ -/* 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 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, 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:</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("Manifest-Version"); - - /** - * General main attribute - - * the version of the jar file signature. - */ - public static final Name SIGNATURE_VERSION - = new Name("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. - * <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 - */ - 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 deleted file mode 100644 index 722a283bba3..00000000000 --- a/libjava/java/util/jar/JarEntry.java +++ /dev/null @@ -1,165 +0,0 @@ -/* JarEntry.java - Represents an entry in a jar file - Copyright (C) 2000 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 java.io.IOException; -import java.security.cert.Certificate; -import java.util.zip.ZipEntry; - -/** - * Extension to a ZipEntry that contains manifest attributes and certificates. - * Both the Atrributes and the Certificates can be null when not set. - * Note that the <code>getCertificates()</code> method only returns a - * valid value after all of the data of the entry has been read. - * <p> - * There are no public methods to set the attributes or certificate of an - * Entru. Only JarEntries created by the classes in <code>java.util.jar</code> - * will have these properties set. - * - * @since 1.2 - * @author Mark Wielaard (mark@klomp.org) - */ - -public class JarEntry extends ZipEntry -{ - // (Package 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 deleted file mode 100644 index d6f0634fe71..00000000000 --- a/libjava/java/util/jar/JarException.java +++ /dev/null @@ -1,77 +0,0 @@ -/* JarException.java -- thrown to indicate an problem with a jar file - Copyright (C) 2000, 2002 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 java.util.zip.ZipException; - -/** - * This exception is thrown to indicate an problem with a jar file. - * Note that none of the methods in the java.util.jar package actually declare - * to throw this exception, most just declare that they throw an IOException - * which is super class of JarException. - * - * @author Mark Wielaard (mark@klomp.org) - * @since 1.2 - */ -public class JarException extends ZipException -{ - /** - * Compatible with JDK 1.2+. - */ - private static final long serialVersionUID = 7159778400963954473L; - - /** - * Create a new JarException without a descriptive error message. - */ - public JarException() - { - } - - /** - * 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. - * - * @param message The descriptive error message - * @see #getMessage() - */ - public JarException(String message) - { - super(message); - } -} diff --git a/libjava/java/util/jar/JarFile.java b/libjava/java/util/jar/JarFile.java deleted file mode 100644 index 3550ad8e0fb..00000000000 --- a/libjava/java/util/jar/JarFile.java +++ /dev/null @@ -1,1058 +0,0 @@ -/* JarFile.java - Representation of a jar file - Copyright (C) 2000, 2003, 2004 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.io.Base64InputStream; -import gnu.java.security.OID; -import gnu.java.security.pkcs.PKCS7SignedData; -import gnu.java.security.pkcs.SignerInfo; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Signature; -import java.security.SignatureException; -import java.security.cert.CRLException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; - -/** - * Representation of a jar file. - * <p> - * Note that this class is not a subclass of java.io.File but a subclass of - * java.util.zip.ZipFile and you can only read JarFiles with it (although - * there are constructors that take a File object). - * - * @since 1.2 - * @author Mark Wielaard (mark@klomp.org) - * @author Casey Marshall (csm@gnu.org) wrote the certificate and entry - * verification code. - */ -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 META-INF directory entry. */ - private static final String META_INF = "META-INF/"; - - /** The suffix for PKCS7 DSA signature entries. */ - private static final String PKCS7_DSA_SUFFIX = ".DSA"; - - /** The suffix for PKCS7 RSA signature entries. */ - private static final String PKCS7_RSA_SUFFIX = ".RSA"; - - /** The suffix for digest attributes. */ - private static final String DIGEST_KEY_SUFFIX = "-Digest"; - - /** The suffix for signature files. */ - private static final String SF_SUFFIX = ".SF"; - - // Signature OIDs. - private static final OID MD2_OID = new OID("1.2.840.113549.2.2"); - private static final OID MD4_OID = new OID("1.2.840.113549.2.4"); - private static final OID MD5_OID = new OID("1.2.840.113549.2.5"); - private static final OID SHA1_OID = new OID("1.3.14.3.2.26"); - private static final OID DSA_ENCRYPTION_OID = new OID("1.2.840.10040.4.1"); - private static final OID RSA_ENCRYPTION_OID = new OID("1.2.840.113549.1.1.1"); - - /** - * The manifest of this file, if any, otherwise null. - * Read when first needed. - */ - private Manifest manifest; - - /** Whether to verify the manifest and all entries. */ - boolean verify; - - /** Whether the has already been loaded. */ - private boolean manifestRead = false; - - /** Whether the signature files have been loaded. */ - boolean signaturesRead = false; - - /** - * A map between entry names and booleans, signaling whether or - * not that entry has been verified. - * Only be accessed with lock on this JarFile*/ - HashMap verified = new HashMap(); - - /** - * A mapping from entry name to certificates, if any. - * Only accessed with lock on this JarFile. - */ - HashMap entryCerts; - - static boolean DEBUG = false; - static void debug(Object msg) - { - System.err.print(JarFile.class.getName()); - System.err.print(" >>> "); - System.err.println(msg); - } - - // Constructors - - /** - * Creates a new JarFile. All jar entries are verified (when a Manifest file - * for this JarFile exists). You need to actually open and read the complete - * jar entry (with <code>getInputStream()</code>) to check its signature. - * - * @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. If verify is true then all jar entries are - * verified (when a Manifest file for this JarFile exists). You need to - * actually open and read the complete jar entry - * (with <code>getInputStream()</code>) to check its signature. - * - * @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); - if (verify) - { - manifest = readManifest(); - verify(); - } - } - - /** - * Creates a new JarFile. All jar entries are verified (when a Manifest file - * for this JarFile exists). You need to actually open and read the complete - * jar entry (with <code>getInputStream()</code>) to check its signature. - * - * @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. If verify is true then all jar entries are - * verified (when a Manifest file for this JarFile exists). You need to - * actually open and read the complete jar entry - * (with <code>getInputStream()</code>) to check its signature. - * - * @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); - if (verify) - { - manifest = readManifest(); - verify(); - } - } - - /** - * Creates a new JarFile with the indicated mode. If verify is true then - * all jar entries are verified (when a Manifest file for this JarFile - * exists). You need to actually open and read the complete jar entry - * (with <code>getInputStream()</code>) to check its signature. - * 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); - if (verify) - { - manifest = readManifest(); - verify(); - } - } - - // Methods - - /** - * XXX - should verify the manifest file - */ - private void verify() - { - // only check if manifest is not null - if (manifest == null) - { - verify = false; - return; - } - - verify = true; - // XXX - verify manifest - } - - /** - * 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); - manifestRead = true; - return new Manifest(in); - } - else - { - manifestRead = true; - return null; - } - } - catch (IOException ioe) - { - manifestRead = true; - return null; - } - } - - /** - * 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(), this); - } - - /** - * Wraps a given Zip Entries Enumeration. For every zip entry a - * JarEntry is created and the corresponding Attributes are looked up. - */ - private static class JarEnumeration implements Enumeration - { - - private final Enumeration entries; - private final JarFile jarfile; - - JarEnumeration(Enumeration e, JarFile f) - { - entries = e; - jarfile = f; - } - - public boolean hasMoreElements() - { - return entries.hasMoreElements(); - } - - public Object nextElement() - { - ZipEntry zip = (ZipEntry) entries.nextElement(); - JarEntry jar = new JarEntry(zip); - Manifest manifest; - try - { - manifest = jarfile.getManifest(); - } - catch (IOException ioe) - { - manifest = null; - } - - if (manifest != null) - { - jar.attr = manifest.getAttributes(jar.getName()); - } - - synchronized(jarfile) - { - if (!jarfile.signaturesRead) - try - { - jarfile.readSignatures(); - } - catch (IOException ioe) - { - if (JarFile.DEBUG) - { - JarFile.debug(ioe); - ioe.printStackTrace(); - } - jarfile.signaturesRead = true; // fudge it. - } - - // Include the certificates only if we have asserted that the - // signatures are valid. This means the certificates will not be - // available if the entry hasn't been read yet. - if (jarfile.entryCerts != null - && jarfile.verified.get(zip.getName()) == Boolean.TRUE) - { - Set certs = (Set) jarfile.entryCerts.get(jar.getName()); - if (certs != null) - jar.certs = (Certificate[]) - certs.toArray(new Certificate[certs.size()]); - } - } - return jar; - } - } - - /** - * XXX - * It actually returns a JarEntry not a zipEntry - * @param name XXX - */ - public synchronized ZipEntry getEntry(String name) - { - ZipEntry entry = super.getEntry(name); - if (entry != null) - { - JarEntry jarEntry = new JarEntry(entry); - Manifest manifest; - try - { - manifest = getManifest(); - } - catch (IOException ioe) - { - manifest = null; - } - - if (manifest != null) - { - jarEntry.attr = manifest.getAttributes(name); - } - - if (!signaturesRead) - try - { - readSignatures(); - } - catch (IOException ioe) - { - if (DEBUG) - { - debug(ioe); - ioe.printStackTrace(); - } - signaturesRead = true; - } - // See the comments in the JarEnumeration for why we do this - // check. - if (DEBUG) - debug("entryCerts=" + entryCerts + " verified " + name - + " ? " + verified.get(name)); - if (entryCerts != null && verified.get(name) == Boolean.TRUE) - { - Set certs = (Set) entryCerts.get(name); - if (certs != null) - jarEntry.certs = (Certificate[]) - certs.toArray(new Certificate[certs.size()]); - } - return jarEntry; - } - return null; - } - - /** - * Returns an input stream for the given entry. If configured to - * verify entries, the input stream returned will verify them while - * the stream is read, but only on the first time. - * - * @param entry The entry to get the input stream for. - * @exception ZipException XXX - * @exception IOException XXX - */ - public synchronized InputStream getInputStream(ZipEntry entry) throws - ZipException, IOException - { - // If we haven't verified the hash, do it now. - if (!verified.containsKey(entry.getName()) && verify) - { - if (DEBUG) - debug("reading and verifying " + entry); - return new EntryInputStream(entry, super.getInputStream(entry), this); - } - else - { - if (DEBUG) - debug("reading already verified entry " + entry); - if (verify && verified.get(entry.getName()) == Boolean.FALSE) - throw new ZipException("digest for " + entry + " is invalid"); - return super.getInputStream(entry); - } - } - - /** - * 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 synchronized Manifest getManifest() throws IOException - { - if (!manifestRead) - manifest = readManifest(); - - return manifest; - } - - // Only called with lock on this JarFile. - private void readSignatures() throws IOException - { - Map pkcs7Dsa = new HashMap(); - Map pkcs7Rsa = new HashMap(); - Map sigFiles = new HashMap(); - - // Phase 1: Read all signature files. These contain the user - // certificates as well as the signatures themselves. - for (Enumeration e = super.entries(); e.hasMoreElements(); ) - { - ZipEntry ze = (ZipEntry) e.nextElement(); - String name = ze.getName(); - if (name.startsWith(META_INF)) - { - String alias = name.substring(META_INF.length()); - if (alias.lastIndexOf('.') >= 0) - alias = alias.substring(0, alias.lastIndexOf('.')); - - if (name.endsWith(PKCS7_DSA_SUFFIX) || name.endsWith(PKCS7_RSA_SUFFIX)) - { - if (DEBUG) - debug("reading PKCS7 info from " + name + ", alias=" + alias); - PKCS7SignedData sig = null; - try - { - sig = new PKCS7SignedData(super.getInputStream(ze)); - } - catch (CertificateException ce) - { - IOException ioe = new IOException("certificate parsing error"); - ioe.initCause(ce); - throw ioe; - } - catch (CRLException crle) - { - IOException ioe = new IOException("CRL parsing error"); - ioe.initCause(crle); - throw ioe; - } - if (name.endsWith(PKCS7_DSA_SUFFIX)) - pkcs7Dsa.put(alias, sig); - else if (name.endsWith(PKCS7_RSA_SUFFIX)) - pkcs7Rsa.put(alias, sig); - } - else if (name.endsWith(SF_SUFFIX)) - { - if (DEBUG) - debug("reading signature file for " + alias + ": " + name); - Manifest sf = new Manifest(super.getInputStream(ze)); - sigFiles.put(alias, sf); - if (DEBUG) - debug("result: " + sf); - } - } - } - - // Phase 2: verify the signatures on any signature files. - Set validCerts = new HashSet(); - Map entryCerts = new HashMap(); - for (Iterator it = sigFiles.entrySet().iterator(); it.hasNext(); ) - { - int valid = 0; - Map.Entry e = (Map.Entry) it.next(); - String alias = (String) e.getKey(); - - PKCS7SignedData sig = (PKCS7SignedData) pkcs7Dsa.get(alias); - if (sig != null) - { - Certificate[] certs = sig.getCertificates(); - Set signerInfos = sig.getSignerInfos(); - for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); ) - verify(certs, (SignerInfo) it2.next(), alias, validCerts); - } - - sig = (PKCS7SignedData) pkcs7Rsa.get(alias); - if (sig != null) - { - Certificate[] certs = sig.getCertificates(); - Set signerInfos = sig.getSignerInfos(); - for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); ) - verify(certs, (SignerInfo) it2.next(), alias, validCerts); - } - - // It isn't a signature for anything. Punt it. - if (validCerts.isEmpty()) - { - it.remove(); - continue; - } - - entryCerts.put(e.getValue(), new HashSet(validCerts)); - validCerts.clear(); - } - - // Phase 3: verify the signature file signatures against the manifest, - // mapping the entry name to the target certificates. - this.entryCerts = new HashMap(); - for (Iterator it = entryCerts.entrySet().iterator(); it.hasNext(); ) - { - Map.Entry e = (Map.Entry) it.next(); - Manifest sigfile = (Manifest) e.getKey(); - Map entries = sigfile.getEntries(); - Set certificates = (Set) e.getValue(); - - for (Iterator it2 = entries.entrySet().iterator(); it2.hasNext(); ) - { - Map.Entry e2 = (Map.Entry) it2.next(); - String entryname = String.valueOf(e2.getKey()); - Attributes attr = (Attributes) e2.getValue(); - if (verifyHashes(entryname, attr)) - { - if (DEBUG) - debug("entry " + entryname + " has certificates " + certificates); - Set s = (Set) this.entryCerts.get(entryname); - if (s != null) - s.addAll(certificates); - else - this.entryCerts.put(entryname, new HashSet(certificates)); - } - } - } - - signaturesRead = true; - } - - /** - * Tell if the given signer info is over the given alias's signature file, - * given one of the certificates specified. - */ - private void verify(Certificate[] certs, SignerInfo signerInfo, - String alias, Set validCerts) - { - Signature sig = null; - try - { - OID alg = signerInfo.getDigestEncryptionAlgorithmId(); - if (alg.equals(DSA_ENCRYPTION_OID)) - { - if (!signerInfo.getDigestAlgorithmId().equals(SHA1_OID)) - return; - sig = Signature.getInstance("SHA1withDSA"); - } - else if (alg.equals(RSA_ENCRYPTION_OID)) - { - OID hash = signerInfo.getDigestAlgorithmId(); - if (hash.equals(MD2_OID)) - sig = Signature.getInstance("md2WithRsaEncryption"); - else if (hash.equals(MD4_OID)) - sig = Signature.getInstance("md4WithRsaEncryption"); - else if (hash.equals(MD5_OID)) - sig = Signature.getInstance("md5WithRsaEncryption"); - else if (hash.equals(SHA1_OID)) - sig = Signature.getInstance("sha1WithRsaEncryption"); - else - return; - } - else - { - if (DEBUG) - debug("unsupported signature algorithm: " + alg); - return; - } - } - catch (NoSuchAlgorithmException nsae) - { - if (DEBUG) - { - debug(nsae); - nsae.printStackTrace(); - } - return; - } - ZipEntry sigFileEntry = super.getEntry(META_INF + alias + SF_SUFFIX); - if (sigFileEntry == null) - return; - for (int i = 0; i < certs.length; i++) - { - if (!(certs[i] instanceof X509Certificate)) - continue; - X509Certificate cert = (X509Certificate) certs[i]; - if (!cert.getIssuerX500Principal().equals(signerInfo.getIssuer()) || - !cert.getSerialNumber().equals(signerInfo.getSerialNumber())) - continue; - try - { - sig.initVerify(cert.getPublicKey()); - InputStream in = super.getInputStream(sigFileEntry); - if (in == null) - continue; - byte[] buf = new byte[1024]; - int len = 0; - while ((len = in.read(buf)) != -1) - sig.update(buf, 0, len); - if (sig.verify(signerInfo.getEncryptedDigest())) - { - if (DEBUG) - debug("signature for " + cert.getSubjectDN() + " is good"); - validCerts.add(cert); - } - } - catch (IOException ioe) - { - continue; - } - catch (InvalidKeyException ike) - { - continue; - } - catch (SignatureException se) - { - continue; - } - } - } - - /** - * Verifies that the digest(s) in a signature file were, in fact, made - * over the manifest entry for ENTRY. - * - * @param entry The entry name. - * @param attr The attributes from the signature file to verify. - */ - private boolean verifyHashes(String entry, Attributes attr) - { - int verified = 0; - - // The bytes for ENTRY's manifest entry, which are signed in the - // signature file. - byte[] entryBytes = null; - try - { - ZipEntry e = super.getEntry(entry); - if (e == null) - { - if (DEBUG) - debug("verifyHashes: no entry '" + entry + "'"); - return false; - } - entryBytes = readManifestEntry(e); - } - catch (IOException ioe) - { - if (DEBUG) - { - debug(ioe); - ioe.printStackTrace(); - } - return false; - } - - for (Iterator it = attr.entrySet().iterator(); it.hasNext(); ) - { - Map.Entry e = (Map.Entry) it.next(); - String key = String.valueOf(e.getKey()); - if (!key.endsWith(DIGEST_KEY_SUFFIX)) - continue; - String alg = key.substring(0, key.length() - DIGEST_KEY_SUFFIX.length()); - try - { - byte[] hash = Base64InputStream.decode((String) e.getValue()); - MessageDigest md = MessageDigest.getInstance(alg); - md.update(entryBytes); - byte[] hash2 = md.digest(); - if (DEBUG) - debug("verifying SF entry " + entry + " alg: " + md.getAlgorithm() - + " expect=" + new java.math.BigInteger(hash).toString(16) - + " comp=" + new java.math.BigInteger(hash2).toString(16)); - if (!Arrays.equals(hash, hash2)) - return false; - verified++; - } - catch (IOException ioe) - { - if (DEBUG) - { - debug(ioe); - ioe.printStackTrace(); - } - return false; - } - catch (NoSuchAlgorithmException nsae) - { - if (DEBUG) - { - debug(nsae); - nsae.printStackTrace(); - } - return false; - } - } - - // We have to find at least one valid digest. - return verified > 0; - } - - /** - * Read the raw bytes that comprise a manifest entry. We can't use the - * Manifest object itself, because that loses information (such as line - * endings, and order of entries). - */ - private byte[] readManifestEntry(ZipEntry entry) throws IOException - { - InputStream in = super.getInputStream(super.getEntry(MANIFEST_NAME)); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] target = ("Name: " + entry.getName()).getBytes(); - int t = 0, c, prev = -1, state = 0, l = -1; - - while ((c = in.read()) != -1) - { -// if (DEBUG) -// debug("read " -// + (c == '\n' ? "\\n" : (c == '\r' ? "\\r" : String.valueOf((char) c))) -// + " state=" + state + " prev=" -// + (prev == '\n' ? "\\n" : (prev == '\r' ? "\\r" : String.valueOf((char) prev))) -// + " t=" + t + (t < target.length ? (" target[t]=" + (char) target[t]) : "") -// + " l=" + l); - switch (state) - { - - // Step 1: read until we find the "target" bytes: the start - // of the entry we need to read. - case 0: - if (((byte) c) != target[t]) - t = 0; - else - { - t++; - if (t == target.length) - { - out.write(target); - state = 1; - } - } - break; - - // Step 2: assert that there is a newline character after - // the "target" bytes. - case 1: - if (c != '\n' && c != '\r') - { - out.reset(); - t = 0; - state = 0; - } - else - { - out.write(c); - state = 2; - } - break; - - // Step 3: read this whole entry, until we reach an empty - // line. - case 2: - if (c == '\n') - { - out.write(c); - // NL always terminates a line. - if (l == 0 || (l == 1 && prev == '\r')) - return out.toByteArray(); - l = 0; - } - else - { - // Here we see a blank line terminated by a CR, - // followed by the next entry. Technically, `c' should - // always be 'N' at this point. - if (l == 1 && prev == '\r') - return out.toByteArray(); - out.write(c); - l++; - } - prev = c; - break; - - default: - throw new RuntimeException("this statement should be unreachable"); - } - } - - // The last entry, with a single CR terminating the line. - if (state == 2 && prev == '\r' && l == 0) - return out.toByteArray(); - - // We should not reach this point, we didn't find the entry (or, possibly, - // it is the last entry and is malformed). - throw new IOException("could not find " + entry + " in manifest"); - } - - /** - * A utility class that verifies jar entries as they are read. - */ - private static class EntryInputStream extends FilterInputStream - { - private final JarFile jarfile; - private final long length; - private long pos; - private final ZipEntry entry; - private final byte[][] hashes; - private final MessageDigest[] md; - private boolean checked; - - EntryInputStream(final ZipEntry entry, - final InputStream in, - final JarFile jar) - throws IOException - { - super(in); - this.entry = entry; - this.jarfile = jar; - - length = entry.getSize(); - pos = 0; - checked = false; - - Attributes attr; - Manifest manifest = jarfile.getManifest(); - if (manifest != null) - attr = manifest.getAttributes(entry.getName()); - else - attr = null; - if (DEBUG) - debug("verifying entry " + entry + " attr=" + attr); - if (attr == null) - { - hashes = new byte[0][]; - md = new MessageDigest[0]; - } - else - { - List hashes = new LinkedList(); - List md = new LinkedList(); - for (Iterator it = attr.entrySet().iterator(); it.hasNext(); ) - { - Map.Entry e = (Map.Entry) it.next(); - String key = String.valueOf(e.getKey()); - if (key == null) - continue; - if (!key.endsWith(DIGEST_KEY_SUFFIX)) - continue; - hashes.add(Base64InputStream.decode((String) e.getValue())); - try - { - md.add(MessageDigest.getInstance - (key.substring(0, key.length() - DIGEST_KEY_SUFFIX.length()))); - } - catch (NoSuchAlgorithmException nsae) - { - IOException ioe = new IOException("no such message digest: " + key); - ioe.initCause(nsae); - throw ioe; - } - } - if (DEBUG) - debug("digests=" + md); - this.hashes = (byte[][]) hashes.toArray(new byte[hashes.size()][]); - this.md = (MessageDigest[]) md.toArray(new MessageDigest[md.size()]); - } - } - - public boolean markSupported() - { - return false; - } - - public void mark(int readLimit) - { - } - - public void reset() - { - } - - public int read() throws IOException - { - int b = super.read(); - if (b == -1) - { - eof(); - return -1; - } - for (int i = 0; i < md.length; i++) - md[i].update((byte) b); - pos++; - if (length > 0 && pos >= length) - eof(); - return b; - } - - public int read(byte[] buf, int off, int len) throws IOException - { - int count = super.read(buf, off, (int) Math.min(len, (length != 0 - ? length - pos - : Integer.MAX_VALUE))); - if (count == -1 || (length > 0 && pos >= length)) - { - eof(); - return -1; - } - for (int i = 0; i < md.length; i++) - md[i].update(buf, off, count); - pos += count; - if (length != 0 && pos >= length) - eof(); - return count; - } - - public int read(byte[] buf) throws IOException - { - return read(buf, 0, buf.length); - } - - public long skip(long bytes) throws IOException - { - byte[] b = new byte[1024]; - long amount = 0; - while (amount < bytes) - { - int l = read(b, 0, (int) Math.min(b.length, bytes - amount)); - if (l == -1) - break; - amount += l; - } - return amount; - } - - private void eof() throws IOException - { - if (checked) - return; - checked = true; - for (int i = 0; i < md.length; i++) - { - byte[] hash = md[i].digest(); - if (DEBUG) - debug("verifying " + md[i].getAlgorithm() + " expect=" - + new java.math.BigInteger(hashes[i]).toString(16) - + " comp=" + new java.math.BigInteger(hash).toString(16)); - if (!Arrays.equals(hash, hashes[i])) - { - synchronized(jarfile) - { - if (DEBUG) - debug(entry + " could NOT be verified"); - jarfile.verified.put(entry.getName(), Boolean.FALSE); - } - return; - // XXX ??? what do we do here? - // throw new ZipException("message digest mismatch"); - } - } - - synchronized(jarfile) - { - if (DEBUG) - debug(entry + " has been VERIFIED"); - jarfile.verified.put(entry.getName(), Boolean.TRUE); - } - } - } -} diff --git a/libjava/java/util/jar/JarInputStream.java b/libjava/java/util/jar/JarInputStream.java deleted file mode 100644 index 1788af6add5..00000000000 --- a/libjava/java/util/jar/JarInputStream.java +++ /dev/null @@ -1,200 +0,0 @@ -/* JarInputStream.java - InputStream for reading jar files - Copyright (C) 2000, 2004 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 java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * InputStream for reading jar files. - * XXX - verification of the signatures in the Manifest file is not yet - * implemented. - * - * @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 whether 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(); - } - - 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 deleted file mode 100644 index 2c8c2f08d8f..00000000000 --- a/libjava/java/util/jar/JarOutputStream.java +++ /dev/null @@ -1,113 +0,0 @@ -/* JarOutputStream.java - OutputStream for writing jar files - Copyright (C) 2000, 2004 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 java.io.IOException; -import java.io.OutputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * OutputStream for writing jar files. - * A special ZipOutputStream that can take JarEntries and can have a optional - * Manifest as first entry. - * - * @author Mark Wielaard (mark@klomp.org) - */ - -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 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 - - /** - * 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 occurred - */ - 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 deleted file mode 100644 index fdc76ff97ee..00000000000 --- a/libjava/java/util/jar/Manifest.java +++ /dev/null @@ -1,472 +0,0 @@ -/* Manifest.java -- Reads, writes and manipulaties jar manifest files - Copyright (C) 2000, 2004 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 java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; - -/** - * Reads, writes and manipulaties jar manifest files. - * XXX - * - * @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 - { - // According to the spec we should actually call read_version_info() here. - read_attributes(attr, br); - // Explicitly set Manifest-Version attribute if not set in Main - // attributes of Manifest. - if (attr.getValue(Attributes.Name.MANIFEST_VERSION) == null) - attr.putValue(Attributes.Name.MANIFEST_VERSION, "0.0"); - } - - /** - * Pedantic method that requires the next attribute in the Manifest to be - * the "Manifest-Version". This follows the Manifest spec closely but - * reject some jar Manifest files out in the wild. - */ - 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(Attributes.Name.MANIFEST_VERSION, 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(); - } - -} |