JarFile.java (manifest): Not final.
authorMark Wielaard <mark@klomp.org>
Tue, 3 Dec 2002 22:06:31 +0000 (22:06 +0000)
committerMark Wielaard <mark@gcc.gnu.org>
Tue, 3 Dec 2002 22:06:31 +0000 (22:06 +0000)
        * 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

libjava/ChangeLog
libjava/java/util/jar/JarFile.java
libjava/java/util/zip/ZipEntry.java
libjava/java/util/zip/ZipFile.java
libjava/java/util/zip/ZipInputStream.java

index 0082f65b6b0103e8e05411fabdf06b5aefb073d0..0fb8c6ab920443ec97b91c0a004e6c40bc880b4b 100644 (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>
 
        * java/lang/Character.java (forDigit): Formatting fix.
index 25179d2558c058465ea4b820bad22c71cd57ee5c..d6fd9846b6ee9ba969bdcf65872d752460886c2c 100644 (file)
@@ -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);
@@ -301,8 +324,11 @@ public class JarFile extends ZipFile
    * Returns the manifest for this JarFile or null when the JarFile does not
    * contain a manifest file.
    */
-  public Manifest getManifest()
+  public Manifest getManifest() throws IOException
   {
+    if (!manifestRead)
+      manifest = readManifest();
+
     return manifest;
   }
 }
index 5a43b1f5a2e599b3fb1aceb51984b9aeac367113..c9f1b1d7d44374d32ebce863f0d2757fbc088c3e 100644 (file)
@@ -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;
index 2eb1156d2bc9a80ddf64f0ef3529f2f9982c1b09..eb79d03e5941b47f7b5ea98552b25a48ba9bdbba 100644 (file)
@@ -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();
     }
   }
 
index c9a6c0159e7c85a1d65e1e68d9a8c9715b2b6164..c4905978d748fbf03c477df87e3246555fd9356c 100644 (file)
@@ -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();