JarFile.java (manifest): Not final.

* 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.

From-SVN: r59785
This commit is contained in:
Mark Wielaard 2002-12-03 22:06:31 +00:00 committed by Mark Wielaard
parent 6e1be6b19c
commit 9c1180ea42
5 changed files with 216 additions and 127 deletions

View file

@ -1,3 +1,40 @@
2002-12-03 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-12-03 Tom Tromey <tromey@redhat.com> 2002-12-03 Tom Tromey <tromey@redhat.com>
* java/lang/Character.java (forDigit): Formatting fix. * java/lang/Character.java (forDigit): Formatting fix.

View file

@ -67,18 +67,22 @@ public class JarFile extends ZipFile
/** /**
* The manifest of this file, if any, otherwise null. * 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; private boolean verify;
/** Wether the has already been loaded. */
private boolean manifestRead = false;
// Constructors // Constructors
/** /**
* Creates a new JarFile, tries to read the manifest and if the manifest * Creates a new JarFile. All jar entries are verified (when a Manifest file
* exists verifies it. * 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 fileName the name of the file to open
* @exception FileNotFoundException if the fileName cannot be found * @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 * Creates a new JarFile. If verify is true then all jar entries are
* exists and verify is true verfies it. * 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 fileName the name of the file to open
* @param verify checks manifest and entries when true and a manifest * @param verify checks manifest and entries when true and a manifest
@ -103,14 +109,12 @@ public class JarFile extends ZipFile
FileNotFoundException, IOException FileNotFoundException, IOException
{ {
super(fileName); super(fileName);
manifest = readManifest();
if (verify)
verify();
} }
/** /**
* Creates a new JarFile, tries to read the manifest and if the manifest * Creates a new JarFile. All jar entries are verified (when a Manifest file
* exists verifies it. * 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 * @param file the file to open as a jar file
* @exception FileNotFoundException if the file does not exits * @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 * Creates a new JarFile. If verify is true then all jar entries are
* exists and verify is true verfies it. * 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 file the file to open to open as a jar file
* @param verify checks manifest and entries when true and a manifest * @param verify checks manifest and entries when true and a manifest
@ -135,13 +141,13 @@ public class JarFile extends ZipFile
IOException IOException
{ {
super(file); 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. * 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 file the file to open to open as a jar file
@ -159,9 +165,6 @@ public class JarFile extends ZipFile
FileNotFoundException, IOException, IllegalArgumentException FileNotFoundException, IOException, IllegalArgumentException
{ {
super(file, mode); super(file, mode);
manifest = readManifest();
if (verify)
verify();
} }
// Methods // Methods
@ -241,6 +244,16 @@ public class JarFile extends ZipFile
{ {
ZipEntry zip = (ZipEntry) entries.nextElement(); ZipEntry zip = (ZipEntry) entries.nextElement();
JarEntry jar = new JarEntry(zip); JarEntry jar = new JarEntry(zip);
Manifest manifest;
try
{
manifest = getManifest();
}
catch (IOException ioe)
{
manifest = null;
}
if (manifest != null) if (manifest != null)
{ {
jar.attr = manifest.getAttributes(jar.getName()); jar.attr = manifest.getAttributes(jar.getName());
@ -261,6 +274,16 @@ public class JarFile extends ZipFile
if (entry != null) if (entry != null)
{ {
JarEntry jarEntry = new JarEntry(entry); JarEntry jarEntry = new JarEntry(entry);
Manifest manifest;
try
{
manifest = getManifest();
}
catch (IOException ioe)
{
manifest = null;
}
if (manifest != null) if (manifest != null)
{ {
jarEntry.attr = manifest.getAttributes(name); jarEntry.attr = manifest.getAttributes(name);
@ -301,8 +324,11 @@ public class JarFile extends ZipFile
* Returns the manifest for this JarFile or null when the JarFile does not * Returns the manifest for this JarFile or null when the JarFile does not
* contain a manifest file. * contain a manifest file.
*/ */
public Manifest getManifest() public Manifest getManifest() throws IOException
{ {
if (!manifestRead)
manifest = readManifest();
return manifest; return manifest;
} }
} }

View file

@ -55,19 +55,18 @@ public class ZipEntry implements ZipConstants, Cloneable
private static int KNOWN_CRC = 4; private static int KNOWN_CRC = 4;
private static int KNOWN_TIME = 8; private static int KNOWN_TIME = 8;
private static Calendar cal = Calendar.getInstance(); private static Calendar cal;
private String name; private String name;
private int size; private int size;
private int compressedSize; private int compressedSize;
private int crc; private int crc;
private int time; private int dostime;
private short known = 0; private short known = 0;
private short method = -1; private short method = -1;
private byte[] extra = null; private byte[] extra = null;
private String comment = null; private String comment = null;
int zipFileIndex = -1; /* used by ZipFile */
int flags; /* used by ZipOutputStream */ int flags; /* used by ZipOutputStream */
int offset; /* used by ZipFile and ZipOutputStream */ int offset; /* used by ZipFile and ZipOutputStream */
@ -104,53 +103,24 @@ public class ZipEntry implements ZipConstants, Cloneable
size = e.size; size = e.size;
compressedSize = e.compressedSize; compressedSize = e.compressedSize;
crc = e.crc; crc = e.crc;
time = e.time; dostime = e.dostime;
method = e.method; method = e.method;
extra = e.extra; extra = e.extra;
comment = e.comment; comment = e.comment;
} }
void setDOSTime(int dostime) final void setDOSTime(int dostime)
{ {
int sec = 2 * (dostime & 0x1f); this.dostime = dostime;
int min = (dostime >> 5) & 0x3f; known |= KNOWN_TIME;
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;
}
} }
int getDOSTime() final int getDOSTime()
{ {
if ((known & KNOWN_TIME) == 0) if ((known & KNOWN_TIME) == 0)
return 0; return 0;
synchronized (cal) else
{ return dostime;
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;
}
} }
/** /**
@ -190,7 +160,18 @@ public class ZipEntry implements ZipConstants, Cloneable
*/ */
public void setTime(long time) 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; this.known |= KNOWN_TIME;
} }
@ -200,7 +181,39 @@ public class ZipEntry implements ZipConstants, Cloneable
*/ */
public long getTime() 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]; int flags = extra[pos];
if ((flags & 1) != 0) if ((flags & 1) != 0)
{ {
time = ((extra[pos+1] & 0xff) long time = ((extra[pos+1] & 0xff)
| (extra[pos+2] & 0xff) << 8 | (extra[pos+2] & 0xff) << 8
| (extra[pos+3] & 0xff) << 16 | (extra[pos+3] & 0xff) << 16
| (extra[pos+4] & 0xff) << 24); | (extra[pos+4] & 0xff) << 24);
known |= KNOWN_TIME; setTime(time);
} }
} }
pos += len; pos += len;

View file

@ -46,6 +46,7 @@ import java.io.IOException;
import java.io.EOFException; import java.io.EOFException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Hashtable;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
/** /**
@ -61,21 +62,26 @@ import java.util.NoSuchElementException;
public class ZipFile implements ZipConstants 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; 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; public static final int OPEN_DELETE = 0x4;
private String name; // Name of this zip file.
RandomAccessFile raf; private final String name;
ZipEntry[] entries;
// 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. * 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.raf = new RandomAccessFile(name, "r");
this.name = name; this.name = name;
readEntries();
} }
/** /**
@ -100,7 +105,6 @@ public class ZipFile implements ZipConstants
{ {
this.raf = new RandomAccessFile(file, "r"); this.raf = new RandomAccessFile(file, "r");
this.name = file.getName(); this.name = file.getName();
readEntries();
} }
/** /**
@ -130,7 +134,6 @@ public class ZipFile implements ZipConstants
} }
this.raf = new RandomAccessFile(file, "r"); this.raf = new RandomAccessFile(file, "r");
this.name = file.getName(); 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 * 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 IOException if a i/o error occured.
* @exception ZipException if the central directory is malformed * @exception ZipException if the central directory is malformed
*/ */
@ -187,7 +190,7 @@ public class ZipFile implements ZipConstants
throw new EOFException(name); throw new EOFException(name);
int centralOffset = readLeInt(raf); int centralOffset = readLeInt(raf);
entries = new ZipEntry[count]; entries = new Hashtable(count);
raf.seek(centralOffset); raf.seek(centralOffset);
byte[] ebs = new byte[24]; byte[] ebs = new byte[24];
ByteArrayInputStream ebais = new ByteArrayInputStream(ebs); ByteArrayInputStream ebais = new ByteArrayInputStream(ebs);
@ -236,9 +239,8 @@ public class ZipFile implements ZipConstants
raf.readFully(buffer, 0, commentLen); raf.readFully(buffer, 0, commentLen);
entry.setComment(new String(buffer, 0, commentLen)); entry.setComment(new String(buffer, 0, commentLen));
} }
entry.zipFileIndex = i;
entry.offset = offset; entry.offset = offset;
entries[i] = entry; entries.put(name, entry);
} }
} }
@ -250,9 +252,10 @@ public class ZipFile implements ZipConstants
*/ */
public void close() throws IOException public void close() throws IOException
{ {
entries = null;
synchronized (raf) synchronized (raf)
{ {
closed = true;
entries = null;
raf.close(); raf.close();
} }
} }
@ -262,17 +265,34 @@ public class ZipFile implements ZipConstants
*/ */
public Enumeration entries() public Enumeration entries()
{ {
if (entries == null) try
throw new IllegalStateException("ZipFile has closed: " + name); {
return new ZipEntryEnumeration(entries); 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++) synchronized(raf)
if (name.equals(entries[i].getName())) {
return i; if (closed)
return -1; throw new IllegalStateException("ZipFile has closed: " + name);
if (entries == null)
readEntries();
return entries;
}
} }
/** /**
@ -283,10 +303,16 @@ public class ZipFile implements ZipConstants
* @see #entries */ * @see #entries */
public ZipEntry getEntry(String name) public ZipEntry getEntry(String name)
{ {
if (entries == null) try
throw new IllegalStateException("ZipFile has closed: " + name); {
int index = getEntryIndex(name); Hashtable entries = getEntries();
return index >= 0 ? (ZipEntry) entries[index].clone() : null; 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 public InputStream getInputStream(ZipEntry entry) throws IOException
{ {
if (entries == null) Hashtable entries = getEntries();
throw new IllegalStateException("ZipFile has closed"); String name = entry.getName();
int index = entry.zipFileIndex; ZipEntry zipEntry = (ZipEntry) entries.get(name);
if (index < 0 || index >= entries.length if (zipEntry == null)
|| entries[index].getName() != entry.getName()) throw new NoSuchElementException(name);
{
index = getEntryIndex(entry.getName());
if (index < 0)
throw new NoSuchElementException();
}
long start = checkLocalHeader(entries[index]); long start = checkLocalHeader(zipEntry);
int method = entries[index].getMethod(); int method = zipEntry.getMethod();
InputStream is = new PartialInputStream InputStream is = new PartialInputStream
(raf, start, entries[index].getCompressedSize()); (raf, start, zipEntry.getCompressedSize());
switch (method) switch (method)
{ {
case ZipOutputStream.STORED: case ZipOutputStream.STORED:
@ -375,42 +396,34 @@ public class ZipFile implements ZipConstants
{ {
try 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 private static class ZipEntryEnumeration implements Enumeration
{ {
ZipEntry[] array; private final Enumeration elements;
int ptr = 0;
public ZipEntryEnumeration(ZipEntry[] arr) public ZipEntryEnumeration(Enumeration elements)
{ {
array = arr; this.elements = elements;
} }
public boolean hasMoreElements() public boolean hasMoreElements()
{ {
return ptr < array.length; return elements.hasMoreElements();
} }
public Object nextElement() public Object nextElement()
{ {
try /* We return a clone, just to be safe that the user doesn't
{ * change the entry.
/* We return a clone, just to be safe that the user doesn't */
* change the entry. return ((ZipEntry)elements.nextElement()).clone();
*/
return array[ptr++].clone();
}
catch (ArrayIndexOutOfBoundsException ex)
{
throw new NoSuchElementException();
}
} }
} }

View file

@ -151,7 +151,7 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants
return null; return null;
} }
if (header != LOCSIG) if (header != LOCSIG)
throw new ZipException("Wrong Local header signature" throw new ZipException("Wrong Local header signature: "
+ Integer.toHexString(header)); + Integer.toHexString(header));
/* skip version */ /* skip version */
readLeShort(); readLeShort();