summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2002-11-29 14:04:19 +0000
committerMark Wielaard <mark@klomp.org>2002-11-29 14:04:19 +0000
commit206bdb02165b314d8e5addf878b34c20f8604a78 (patch)
tree121f5928a5527212f3ae5c29513ea72469e71ee9
parentdb3dd1d85935b4d543854525cf9704794a10e16f (diff)
downloadclasspath-206bdb02165b314d8e5addf878b34c20f8604a78.tar.gz
* java/util/jar/JarFile.java (manifest): Not final.
(manifestRead): New field. (JarFile): Don't read Manifest in constructor. (getManifest): New method. (JarEnumeration.nextElement): Use new method. (getEntry): Likewise. * java/util/zip/ZipFile.java (name): Final. (raf): Likewsie. (entries): Change type to Hashtable. (closed): New field. (ZipFile): Don't read enties in constructor. (readEntries): Use Hashtable. (close): Set new close flag and set entries to null inside synchronized block. (entries): Contruct enumeration using new getEntries() method and entries Hashtable. (getEntryIndex): Removed. (getEntries): New method. (getEntry): Use new getEntries() method and entries Hastable. (getInputStream): Likewise. (size): Return getEntries().size(). (ZipEntryEnumeration): Wrap entries Hashtable elements. * java/util/zip/ZipEntry.java (cal): Don't initialize. (time): Removed (dostime): New field. (zipFileIndex): Removed. (ZipEntry(ZipEntry)): Copy dostime. (setDOSTime): Now final and doesn't convert dos time. (getDOSTime): Likewise. (setTime): Convert dos time. (getTime): Likewise. (getCalendar): New method. (setExtra): Use setTime(). * java/util/zip/ZipInputStream.java (getNextEntry): Format error msg.
-rw-r--r--ChangeLog37
-rw-r--r--java/util/jar/JarFile.java68
-rw-r--r--java/util/zip/ZipEntry.java99
-rw-r--r--java/util/zip/ZipFile.java137
-rw-r--r--java/util/zip/ZipInputStream.java2
5 files changed, 216 insertions, 127 deletions
diff --git a/ChangeLog b/ChangeLog
index 0585b6326..44689fee3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2002-11-25 Mark Wielaard <mark@klomp.org>
+
+ * java/util/jar/JarFile.java (manifest): Not final.
+ (manifestRead): New field.
+ (JarFile): Don't read Manifest in constructor.
+ (getManifest): New method.
+ (JarEnumeration.nextElement): Use new method.
+ (getEntry): Likewise.
+ * java/util/zip/ZipFile.java (name): Final.
+ (raf): Likewsie.
+ (entries): Change type to Hashtable.
+ (closed): New field.
+ (ZipFile): Don't read enties in constructor.
+ (readEntries): Use Hashtable.
+ (close): Set new close flag and set entries to null inside
+ synchronized block.
+ (entries): Contruct enumeration using new getEntries() method and
+ entries Hashtable.
+ (getEntryIndex): Removed.
+ (getEntries): New method.
+ (getEntry): Use new getEntries() method and entries Hastable.
+ (getInputStream): Likewise.
+ (size): Return getEntries().size().
+ (ZipEntryEnumeration): Wrap entries Hashtable elements.
+ * java/util/zip/ZipEntry.java (cal): Don't initialize.
+ (time): Removed
+ (dostime): New field.
+ (zipFileIndex): Removed.
+ (ZipEntry(ZipEntry)): Copy dostime.
+ (setDOSTime): Now final and doesn't convert dos time.
+ (getDOSTime): Likewise.
+ (setTime): Convert dos time.
+ (getTime): Likewise.
+ (getCalendar): New method.
+ (setExtra): Use setTime().
+ * java/util/zip/ZipInputStream.java (getNextEntry): Format error msg.
+
2002-11-27 Julian Dolby <dolby@us.ibm.com>
* java/util/Locale.java (toString): Improve efficiency if country
diff --git a/java/util/jar/JarFile.java b/java/util/jar/JarFile.java
index dd980f8c0..d6fd9846b 100644
--- a/java/util/jar/JarFile.java
+++ b/java/util/jar/JarFile.java
@@ -67,18 +67,22 @@ public class JarFile extends ZipFile
/**
* The manifest of this file, if any, otherwise null.
- * Read by the constructor.
+ * Read when first needed.
*/
- private final Manifest manifest;
+ private Manifest manifest;
- /** Wether to verify the manifest and all entries */
+ /** Wether to verify the manifest and all entries. */
private boolean verify;
+ /** Wether the has already been loaded. */
+ private boolean manifestRead = false;
+
// Constructors
/**
- * Creates a new JarFile, tries to read the manifest and if the manifest
- * exists verifies it.
+ * 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
@@ -90,8 +94,10 @@ public class JarFile extends ZipFile
}
/**
- * Creates a new JarFile, tries to read the manifest and if the manifest
- * exists and verify is true verfies it.
+ * 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
@@ -103,14 +109,12 @@ public class JarFile extends ZipFile
FileNotFoundException, IOException
{
super(fileName);
- manifest = readManifest();
- if (verify)
- verify();
}
/**
- * Creates a new JarFile, tries to read the manifest and if the manifest
- * exists verifies it.
+ * 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
@@ -122,8 +126,10 @@ public class JarFile extends ZipFile
}
/**
- * Creates a new JarFile, tries to read the manifest and if the manifest
- * exists and verify is true verfies it.
+ * 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
@@ -135,13 +141,13 @@ public class JarFile extends ZipFile
IOException
{
super(file);
- manifest = readManifest();
- if (verify)
- verify();
}
/**
- * Creates a new JarFile with the indicated mode, tries to read the
+ * 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
@@ -159,9 +165,6 @@ public class JarFile extends ZipFile
FileNotFoundException, IOException, IllegalArgumentException
{
super(file, mode);
- manifest = readManifest();
- if (verify)
- verify();
}
// Methods
@@ -241,6 +244,16 @@ public class JarFile extends ZipFile
{
ZipEntry zip = (ZipEntry) entries.nextElement();
JarEntry jar = new JarEntry(zip);
+ Manifest manifest;
+ try
+ {
+ manifest = getManifest();
+ }
+ catch (IOException ioe)
+ {
+ manifest = null;
+ }
+
if (manifest != null)
{
jar.attr = manifest.getAttributes(jar.getName());
@@ -261,6 +274,16 @@ public class JarFile extends ZipFile
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);
@@ -303,6 +326,9 @@ public class JarFile extends ZipFile
*/
public Manifest getManifest() throws IOException
{
+ if (!manifestRead)
+ manifest = readManifest();
+
return manifest;
}
}
diff --git a/java/util/zip/ZipEntry.java b/java/util/zip/ZipEntry.java
index 5a43b1f5a..c9f1b1d7d 100644
--- a/java/util/zip/ZipEntry.java
+++ b/java/util/zip/ZipEntry.java
@@ -55,19 +55,18 @@ public class ZipEntry implements ZipConstants, Cloneable
private static int KNOWN_CRC = 4;
private static int KNOWN_TIME = 8;
- private static Calendar cal = Calendar.getInstance();
+ private static Calendar cal;
private String name;
private int size;
private int compressedSize;
private int crc;
- private int time;
+ private int dostime;
private short known = 0;
private short method = -1;
private byte[] extra = null;
private String comment = null;
- int zipFileIndex = -1; /* used by ZipFile */
int flags; /* used by ZipOutputStream */
int offset; /* used by ZipFile and ZipOutputStream */
@@ -104,53 +103,24 @@ public class ZipEntry implements ZipConstants, Cloneable
size = e.size;
compressedSize = e.compressedSize;
crc = e.crc;
- time = e.time;
+ dostime = e.dostime;
method = e.method;
extra = e.extra;
comment = e.comment;
}
- void setDOSTime(int dostime)
+ final void setDOSTime(int dostime)
{
- int sec = 2 * (dostime & 0x1f);
- int min = (dostime >> 5) & 0x3f;
- int hrs = (dostime >> 11) & 0x1f;
- int day = (dostime >> 16) & 0x1f;
- int mon = ((dostime >> 21) & 0xf) - 1;
- int year = ((dostime >> 25) & 0x7f) + 1980; /* since 1900 */
-
- // Guard against invalid or missing date causing
- // IndexOutOfBoundsException.
- try
- {
- synchronized (cal)
- {
- cal.set(year, mon, day, hrs, min, sec);
- time = (int) (cal.getTime().getTime() / 1000L);
- }
- known |= KNOWN_TIME;
- }
- catch (RuntimeException ex)
- {
- /* Ignore illegal time stamp */
- known &= ~KNOWN_TIME;
- }
+ this.dostime = dostime;
+ known |= KNOWN_TIME;
}
- int getDOSTime()
+ final int getDOSTime()
{
if ((known & KNOWN_TIME) == 0)
return 0;
- synchronized (cal)
- {
- cal.setTime(new Date(time*1000L));
- return (cal.get(cal.YEAR) - 1980 & 0x7f) << 25
- | (cal.get(cal.MONTH) + 1) << 21
- | (cal.get(cal.DAY_OF_MONTH)) << 16
- | (cal.get(cal.HOUR_OF_DAY)) << 11
- | (cal.get(cal.MINUTE)) << 5
- | (cal.get(cal.SECOND)) >> 1;
- }
+ else
+ return dostime;
}
/**
@@ -190,7 +160,18 @@ public class ZipEntry implements ZipConstants, Cloneable
*/
public void setTime(long time)
{
- this.time = (int) (time / 1000L);
+ Calendar cal = getCalendar();
+ synchronized (cal)
+ {
+ cal.setTime(new Date(time*1000L));
+ dostime = (cal.get(cal.YEAR) - 1980 & 0x7f) << 25
+ | (cal.get(cal.MONTH) + 1) << 21
+ | (cal.get(cal.DAY_OF_MONTH)) << 16
+ | (cal.get(cal.HOUR_OF_DAY)) << 11
+ | (cal.get(cal.MINUTE)) << 5
+ | (cal.get(cal.SECOND)) >> 1;
+ }
+ dostime = (int) (dostime / 1000L);
this.known |= KNOWN_TIME;
}
@@ -200,7 +181,39 @@ public class ZipEntry implements ZipConstants, Cloneable
*/
public long getTime()
{
- return (known & KNOWN_TIME) != 0 ? time * 1000L : -1;
+ if ((known & KNOWN_TIME) == 0)
+ return -1;
+
+ int sec = 2 * (dostime & 0x1f);
+ int min = (dostime >> 5) & 0x3f;
+ int hrs = (dostime >> 11) & 0x1f;
+ int day = (dostime >> 16) & 0x1f;
+ int mon = ((dostime >> 21) & 0xf) - 1;
+ int year = ((dostime >> 25) & 0x7f) + 1980; /* since 1900 */
+
+ try
+ {
+ cal = getCalendar();
+ synchronized (cal)
+ {
+ cal.set(year, mon, day, hrs, min, sec);
+ return cal.getTime().getTime();
+ }
+ }
+ catch (RuntimeException ex)
+ {
+ /* Ignore illegal time stamp */
+ known &= ~KNOWN_TIME;
+ return -1;
+ }
+ }
+
+ private static synchronized Calendar getCalendar()
+ {
+ if (cal == null)
+ cal = Calendar.getInstance();
+
+ return cal;
}
/**
@@ -320,11 +333,11 @@ public class ZipEntry implements ZipConstants, Cloneable
int flags = extra[pos];
if ((flags & 1) != 0)
{
- time = ((extra[pos+1] & 0xff)
+ long time = ((extra[pos+1] & 0xff)
| (extra[pos+2] & 0xff) << 8
| (extra[pos+3] & 0xff) << 16
| (extra[pos+4] & 0xff) << 24);
- known |= KNOWN_TIME;
+ setTime(time);
}
}
pos += len;
diff --git a/java/util/zip/ZipFile.java b/java/util/zip/ZipFile.java
index 2eb1156d2..eb79d03e5 100644
--- a/java/util/zip/ZipFile.java
+++ b/java/util/zip/ZipFile.java
@@ -46,6 +46,7 @@ import java.io.IOException;
import java.io.EOFException;
import java.io.RandomAccessFile;
import java.util.Enumeration;
+import java.util.Hashtable;
import java.util.NoSuchElementException;
/**
@@ -61,21 +62,26 @@ import java.util.NoSuchElementException;
public class ZipFile implements ZipConstants
{
- /** Mode flag to open a zip file for reading
- *
+ /**
+ * Mode flag to open a zip file for reading.
*/
-
public static final int OPEN_READ = 0x1;
- /** Mode flag to delete a zip file after reading
- *
+ /**
+ * Mode flag to delete a zip file after reading.
*/
-
public static final int OPEN_DELETE = 0x4;
- private String name;
- RandomAccessFile raf;
- ZipEntry[] entries;
+ // Name of this zip file.
+ private final String name;
+
+ // File from which zip entries are read.
+ private final RandomAccessFile raf;
+
+ // The entries of this zip file when initialized and not yet closed.
+ private Hashtable entries;
+
+ private boolean closed = false;
/**
* Opens a Zip file with the given name for reading.
@@ -87,7 +93,6 @@ public class ZipFile implements ZipConstants
{
this.raf = new RandomAccessFile(name, "r");
this.name = name;
- readEntries();
}
/**
@@ -100,7 +105,6 @@ public class ZipFile implements ZipConstants
{
this.raf = new RandomAccessFile(file, "r");
this.name = file.getName();
- readEntries();
}
/**
@@ -130,7 +134,6 @@ public class ZipFile implements ZipConstants
}
this.raf = new RandomAccessFile(file, "r");
this.name = file.getName();
- readEntries();
}
/**
@@ -160,7 +163,7 @@ public class ZipFile implements ZipConstants
/**
* Read the central directory of a zip file and fill the entries
- * array. This is called exactly once by the constructors.
+ * array. This is called exactly once when first needed.
* @exception IOException if a i/o error occured.
* @exception ZipException if the central directory is malformed
*/
@@ -187,7 +190,7 @@ public class ZipFile implements ZipConstants
throw new EOFException(name);
int centralOffset = readLeInt(raf);
- entries = new ZipEntry[count];
+ entries = new Hashtable(count);
raf.seek(centralOffset);
byte[] ebs = new byte[24];
ByteArrayInputStream ebais = new ByteArrayInputStream(ebs);
@@ -236,9 +239,8 @@ public class ZipFile implements ZipConstants
raf.readFully(buffer, 0, commentLen);
entry.setComment(new String(buffer, 0, commentLen));
}
- entry.zipFileIndex = i;
entry.offset = offset;
- entries[i] = entry;
+ entries.put(name, entry);
}
}
@@ -250,9 +252,10 @@ public class ZipFile implements ZipConstants
*/
public void close() throws IOException
{
- entries = null;
synchronized (raf)
{
+ closed = true;
+ entries = null;
raf.close();
}
}
@@ -262,17 +265,34 @@ public class ZipFile implements ZipConstants
*/
public Enumeration entries()
{
- if (entries == null)
- throw new IllegalStateException("ZipFile has closed: " + name);
- return new ZipEntryEnumeration(entries);
+ try
+ {
+ return new ZipEntryEnumeration(getEntries().elements());
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
}
- private int getEntryIndex(String name)
+ /**
+ * Checks that the ZipFile is still open and reads entries when necessary.
+ *
+ * @exception IllegalStateException when the ZipFile has already been closed.
+ * @exception IOEexception when the entries could not be read.
+ */
+ private Hashtable getEntries() throws IOException
{
- for (int i = 0; i < entries.length; i++)
- if (name.equals(entries[i].getName()))
- return i;
- return -1;
+ synchronized(raf)
+ {
+ if (closed)
+ throw new IllegalStateException("ZipFile has closed: " + name);
+
+ if (entries == null)
+ readEntries();
+
+ return entries;
+ }
}
/**
@@ -283,10 +303,16 @@ public class ZipFile implements ZipConstants
* @see #entries */
public ZipEntry getEntry(String name)
{
- if (entries == null)
- throw new IllegalStateException("ZipFile has closed: " + name);
- int index = getEntryIndex(name);
- return index >= 0 ? (ZipEntry) entries[index].clone() : null;
+ try
+ {
+ Hashtable entries = getEntries();
+ ZipEntry entry = (ZipEntry) entries.get(name);
+ return entry != null ? (ZipEntry) entry.clone() : null;
+ }
+ catch (IOException ioe)
+ {
+ return null;
+ }
}
/**
@@ -334,21 +360,16 @@ public class ZipFile implements ZipConstants
*/
public InputStream getInputStream(ZipEntry entry) throws IOException
{
- if (entries == null)
- throw new IllegalStateException("ZipFile has closed");
- int index = entry.zipFileIndex;
- if (index < 0 || index >= entries.length
- || entries[index].getName() != entry.getName())
- {
- index = getEntryIndex(entry.getName());
- if (index < 0)
- throw new NoSuchElementException();
- }
-
- long start = checkLocalHeader(entries[index]);
- int method = entries[index].getMethod();
+ Hashtable entries = getEntries();
+ String name = entry.getName();
+ ZipEntry zipEntry = (ZipEntry) entries.get(name);
+ if (zipEntry == null)
+ throw new NoSuchElementException(name);
+
+ long start = checkLocalHeader(zipEntry);
+ int method = zipEntry.getMethod();
InputStream is = new PartialInputStream
- (raf, start, entries[index].getCompressedSize());
+ (raf, start, zipEntry.getCompressedSize());
switch (method)
{
case ZipOutputStream.STORED:
@@ -375,42 +396,34 @@ public class ZipFile implements ZipConstants
{
try
{
- return entries.length;
+ return getEntries().size();
}
- catch (NullPointerException ex)
+ catch (IOException ioe)
{
- throw new IllegalStateException("ZipFile has closed");
+ return 0;
}
}
private static class ZipEntryEnumeration implements Enumeration
{
- ZipEntry[] array;
- int ptr = 0;
+ private final Enumeration elements;
- public ZipEntryEnumeration(ZipEntry[] arr)
+ public ZipEntryEnumeration(Enumeration elements)
{
- array = arr;
+ this.elements = elements;
}
public boolean hasMoreElements()
{
- return ptr < array.length;
+ return elements.hasMoreElements();
}
public Object nextElement()
{
- try
- {
- /* We return a clone, just to be safe that the user doesn't
- * change the entry.
- */
- return array[ptr++].clone();
- }
- catch (ArrayIndexOutOfBoundsException ex)
- {
- throw new NoSuchElementException();
- }
+ /* We return a clone, just to be safe that the user doesn't
+ * change the entry.
+ */
+ return ((ZipEntry)elements.nextElement()).clone();
}
}
diff --git a/java/util/zip/ZipInputStream.java b/java/util/zip/ZipInputStream.java
index c9a6c0159..c4905978d 100644
--- a/java/util/zip/ZipInputStream.java
+++ b/java/util/zip/ZipInputStream.java
@@ -151,7 +151,7 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants
return null;
}
if (header != LOCSIG)
- throw new ZipException("Wrong Local header signature"
+ throw new ZipException("Wrong Local header signature: "
+ Integer.toHexString(header));
/* skip version */
readLeShort();