[jboss-svn-commits] JBoss Common SVN: r3248 - jzipfile/trunk/src/main/java/org/jboss/jzipfile.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Jun 12 21:19:08 EDT 2009


Author: david.lloyd at jboss.com
Date: 2009-06-12 21:19:08 -0400 (Fri, 12 Jun 2009)
New Revision: 3248

Modified:
   jzipfile/trunk/src/main/java/org/jboss/jzipfile/Zip.java
   jzipfile/trunk/src/main/java/org/jboss/jzipfile/ZipCatalogBuilder.java
Log:
Minor fixes and javadoc updates

Modified: jzipfile/trunk/src/main/java/org/jboss/jzipfile/Zip.java
===================================================================
--- jzipfile/trunk/src/main/java/org/jboss/jzipfile/Zip.java	2009-06-13 00:59:21 UTC (rev 3247)
+++ jzipfile/trunk/src/main/java/org/jboss/jzipfile/Zip.java	2009-06-13 01:19:08 UTC (rev 3248)
@@ -54,7 +54,7 @@
     }
 
     /**
-     * Fid the zip catalog for the given file.  The returned input stream is positioned at the start of the zip
+     * Find the zip catalog for the given file.  The returned input stream is positioned at the start of the zip
      * directory structure.
      *
      * @param file the file to examine
@@ -62,44 +62,49 @@
      * @throws IOException if an I/O error occurs
      */
     public static InputStream findCatalog(File file) throws IOException {
+        boolean ok = false;
         final RandomAccessFile raf = new RandomAccessFile(file, "r");
-        final long len = raf.length();
-        if (len < 22L) {
-            throw new ZipException("The provided file is too short to hold even one end-of-central-directory record");
-        }
-        // First, check at len-22 in the (common) case that there is no zip file comment.
-        raf.seek(len - 22);
-        if (! catScan(raf, 0)) {
-            // OK, let's back off incrementally, starting from 64 bytes out and going up by a factor of 4 each time
-            int spos = 64;
-            int lim = 64 - 22;
-            raf.seek(len - 64);
-            while (! catScan(raf, lim)) {
-                int newSpos = spos << 2;
-                lim = newSpos - spos;
-                spos = newSpos;
-                if (spos >= 65536) try {
-                    throw new ZipException("No directory found");
-                } finally {
-                    safeClose(raf);
+        try {
+            final long len = raf.length();
+            if (len < 22L) {
+                throw new ZipException("The provided file is too short to hold even one end-of-central-directory record");
+            }
+            // First, check at len-22 in the (common) case that there is no zip file comment.
+            raf.seek(len - 22);
+            if (! catScan(raf, 0)) {
+                // OK, let's back off incrementally, starting from 64 bytes out and going up by a factor of 4 each time
+                int spos = 64;
+                int lim = 64 - 22;
+                raf.seek(len - 64);
+                while (! catScan(raf, lim)) {
+                    int newSpos = spos << 2;
+                    lim = newSpos - spos;
+                    spos = newSpos;
+                    if (spos >= 65536) {
+                        throw new ZipException("No directory found");
+                    }
+                    raf.seek(len - spos);
                 }
-                raf.seek(len - spos);
             }
+            // OK, the EOD was located.  Now read it to find the start of the directory
+            final int diskNo = Short.reverseBytes(raf.readShort()) & 0xffff; // disk #
+            final int cddNo = Short.reverseBytes(raf.readShort()) & 0xffff; // central dir disk #
+            final int diskEC = Short.reverseBytes(raf.readShort()) & 0xffff; // entry count in central dir # on this disk
+            final int totalEC = Short.reverseBytes(raf.readShort()) & 0xffff; // entry count in central dir #
+            if (diskNo != cddNo || cddNo != 0) {
+                throw new ZipException("Multi-disk zips not supported");
+            }
+            if (diskEC != totalEC) {
+                throw new ZipException("Entry count inconsistency in end-of-directory record");
+            }
+            raf.readInt(); // size of central dir
+            raf.seek(Integer.reverseBytes(raf.readInt())); // offset of central dir
+            final RandomAccessInputStream is = new RandomAccessInputStream(raf);
+            ok = true;
+            return is;
+        } finally {
+            if (! ok) safeClose(raf);
         }
-        // OK, the EOD was located.  Now read it to find the start of the directory
-        final int diskNo = Short.reverseBytes(raf.readShort()) & 0xffff; // disk #
-        final int cddNo = Short.reverseBytes(raf.readShort()) & 0xffff; // central dir disk #
-        final int diskEC = Short.reverseBytes(raf.readShort()) & 0xffff; // entry count in central dir # on this disk
-        final int totalEC = Short.reverseBytes(raf.readShort()) & 0xffff; // entry count in central dir #
-        if (diskNo != cddNo || cddNo != 0) {
-            throw new ZipException("Multi-disk zips not supported");
-        }
-        if (diskEC != totalEC) {
-            throw new ZipException("Entry count inconsistency in end-of-directory record");
-        }
-        raf.readInt(); // size of central dir
-        raf.seek(Integer.reverseBytes(raf.readInt())); // offset of central dir
-        return new RandomAccessInputStream(raf);
     }
 
     private static boolean catScan(DataInput input, int limit) throws IOException {
@@ -117,8 +122,8 @@
     }
 
     /**
-     * Read the zip catalog referred to by the given input stream.  The input stream should be pointed to the
-     * start of the catalog.  <b>Note:</b> the passed in
+     * Read the zip catalog referred to by the given input stream, which is pointed at the
+     * start of the catalog (also known as the "central directory").  <b>Note:</b> the passed in
      * {@code InputStream} will be used and closed by this method.
      *
      * @param inputStream the input stream from which to build a catalog
@@ -127,7 +132,7 @@
      */
     public static ZipCatalog readCatalog(InputStream inputStream) throws IOException {
         final ZipCatalogBuilder builder = new ZipCatalogBuilder();
-        builder.read(inputStream);
+        builder.readDirectory(inputStream);
         return builder.getZipCatalog();
     }
 
@@ -143,7 +148,9 @@
     }
 
     /**
-     * Open a zip entry.
+     * Open a zip entry, returning an input stream which may be used to read the contents of the
+     * entry.  Depending on how the entry is stored, the returned stream may or may not support
+     * {@code mark/reset}.
      *
      * @param zipFile the zip file to access
      * @param zipEntry the zip entry from that file
@@ -227,6 +234,9 @@
      * @throws IOException if an I/O error occurs
      */
     public static void extract(File zipFile, File destDir) throws IOException {
+        if (! destDir.isDirectory()) {
+            throw new IOException("Destination is not a directory");
+        }
         final byte[] buf = new byte[16384];
         final ZipCatalog catalog = readCatalog(zipFile);
         for (ZipEntry zipEntry : catalog.allEntries()) {
@@ -266,7 +276,7 @@
         }
     }
 
-    private static void safeClose(final Closeable closeable) {
+    static void safeClose(final Closeable closeable) {
         try {
             if (closeable != null) closeable.close();
         } catch (IOException e) {

Modified: jzipfile/trunk/src/main/java/org/jboss/jzipfile/ZipCatalogBuilder.java
===================================================================
--- jzipfile/trunk/src/main/java/org/jboss/jzipfile/ZipCatalogBuilder.java	2009-06-13 00:59:21 UTC (rev 3247)
+++ jzipfile/trunk/src/main/java/org/jboss/jzipfile/ZipCatalogBuilder.java	2009-06-13 01:19:08 UTC (rev 3248)
@@ -29,8 +29,6 @@
 import java.util.Collections;
 import java.util.Collection;
 import java.util.zip.ZipException;
-import java.util.zip.Inflater;
-import java.util.zip.InflaterInputStream;
 import java.io.InputStream;
 import java.io.IOException;
 
@@ -41,101 +39,105 @@
     ZipCatalogBuilder() {
     }
 
-    void read(InputStream is) throws IOException {
+    void readDirectory(InputStream is) throws IOException {
         readDirectory(is instanceof ZipDataInputStream ? (ZipDataInputStream) is : new ZipDataInputStream(is));
     }
 
     void readDirectory(ZipDataInputStream is) throws IOException {
-        // Format:
-        // central directory
-        // [zip64 end of central directory rec]
-        // [zip64 end of central directory locator]
-        // end of central directory record
-        int sig = is.readInt();
-        while (sig == 0x02014b50) {
-            // central directory file header (0..n)
-            int madeBy = is.readUnsignedShort();
-            int needed = is.readUnsignedShort();
-            if (needed > 20) {
-                throw new ZipException("Need a later version to extract");
+        try {
+            // Format:
+            // central directory
+            // [zip64 end of central directory rec]
+            // [zip64 end of central directory locator]
+            // end of central directory record
+            int sig = is.readInt();
+            while (sig == 0x02014b50) {
+                // central directory file header (0..n)
+                is.readUnsignedShort(); // madeBy
+                int needed = is.readUnsignedShort();
+                if (needed > 20) {
+                    throw new ZipException("Need a later version to extract");
+                }
+                is.readUnsignedShort(); // gpbits
+                final ZipCompressionMethod method = ZipCompressionMethod.getMethod(is.readUnsignedShort());
+                int modTimeBytes = is.readUnsignedShort();
+                int modDateBytes = is.readUnsignedShort();
+                int crc32 = is.readInt();
+                int compSize = is.readInt();
+                int uncompSize = is.readInt();
+                int fnameLen = is.readUnsignedShort();
+                int extraLen = is.readUnsignedShort();
+                int commentLen = is.readUnsignedShort();
+                int diskNumStart = is.readUnsignedShort();
+                if (diskNumStart != 0) {
+                    throw new ZipException("Multi-disk archives not supported");
+                }
+                is.readUnsignedShort(); // internal attr
+                is.readInt(); // external attr
+                int localHeaderOffs = is.readInt();
+                final byte[] fileNameBytes = new byte[fnameLen];
+                is.readFully(fileNameBytes);
+                final byte[] extraBytes = new byte[extraLen];
+                is.readFully(extraBytes);
+                final byte[] commentBytes = new byte[commentLen];
+                is.readFully(commentBytes);
+                final String name = new String(fileNameBytes, "US-ASCII");
+                // interpret type
+                final ZipEntryType type;
+                if (name.indexOf('/') == 0) {
+                    throw new ZipException("Leading slash not allowed in file name \"" + name + "\"");
+                }
+                if (uncompSize == 0 && name.lastIndexOf('/') == name.length() - 1) {
+                    type = ZipEntryType.DIRECTORY;
+                } else {
+                    type = ZipEntryType.FILE;
+                }
+                final String comment = new String(commentBytes, "US-ASCII");
+                final ZipEntryImpl entry = new ZipEntryImpl(name, comment, localHeaderOffs, uncompSize & 0xffffffffL, compSize & 0xffffffffL, crc32, type, 0L, method, extraBytes);
+                allEntries.add(entry);
+                entryMap.put(name, entry);
+                // next sig
+                sig = is.readInt();
             }
-            int gpbits = is.readUnsignedShort();
-            final ZipCompressionMethod method = ZipCompressionMethod.getMethod(is.readUnsignedShort());
-            int modTimeBytes = is.readUnsignedShort();
-            int modDateBytes = is.readUnsignedShort();
-            int crc32 = is.readInt();
-            int compSize = is.readInt();
-            int uncompSize = is.readInt();
-            int fnameLen = is.readUnsignedShort();
-            int extraLen = is.readUnsignedShort();
-            int commentLen = is.readUnsignedShort();
-            int diskNumStart = is.readUnsignedShort();
-            if (diskNumStart != 0) {
-                throw new ZipException("Multi-disk archives not supported");
+            if (sig == 0x05054b50) {
+                // central directory signature (0..1)
+                final int size = is.readUnsignedShort();
+                is.skipFully(size & 0xffffffffL);
+
+                // next sig
+                sig = is.readInt();
             }
-            int internalAttr = is.readUnsignedShort();
-            int externalAttr = is.readInt();
-            int localHeaderOffs = is.readInt();
-            final byte[] fileNameBytes = new byte[fnameLen];
-            is.readFully(fileNameBytes);
-            final byte[] extraBytes = new byte[extraLen];
-            is.readFully(extraBytes);
-            final byte[] commentBytes = new byte[commentLen];
-            is.readFully(commentBytes);
-            final String name = new String(fileNameBytes, "US-ASCII");
-            // interpret type
-            final ZipEntryType type;
-            if (name.indexOf('/') == 0) {
-                throw new ZipException("Leading slash not allowed in file name \"" + name + "\"");
+            if (sig == 0x06064b50) {
+                if (true) throw new ZipException("64-bit zip records unsupported");
+                // zip64 EOD record (0..1)
+                is.readLong();
+                is.readUnsignedShort();
+                is.readUnsignedShort();
+                is.readInt();
+                is.readInt();
+                is.readLong();
+                is.readLong();
+                is.readLong();
+                is.readLong();
+                // next sig
+                sig = is.readInt();
             }
-            if (uncompSize == 0 && name.lastIndexOf('/') == name.length() - 1) {
-                type = ZipEntryType.DIRECTORY;
-            } else {
-                type = ZipEntryType.FILE;
+            if (sig == 0x07064b50) {
+                if (true) throw new ZipException("64-bit zip records unsupported");
+                // zip64 EOD locator (0..1)
+
+                // next sig
+                sig = is.readInt();
             }
-            final String comment = new String(commentBytes, "US-ASCII");
-            final ZipEntryImpl entry = new ZipEntryImpl(name, comment, localHeaderOffs, uncompSize & 0xffffffffL, compSize & 0xffffffffL, crc32, type, 0L, method, extraBytes);
-            allEntries.add(entry);
-            entryMap.put(name, entry);
-            // next sig
-            sig = is.readInt();
+            if (sig == 0x06054b50) {
+                // EOD (exactly 1)
+                is.close();
+                return;
+            }
+            throw new ZipException(String.format("Unexpected signature byte 0x%08x", Integer.valueOf(sig)));
+        } finally {
+            Zip.safeClose(is);
         }
-        if (sig == 0x05054b50) {
-            // central directory signature (0..1)
-            final int size = is.readUnsignedShort();
-            is.skipFully(size & 0xffffffffL);
-
-            // next sig
-            sig = is.readInt();
-        }
-        if (sig == 0x06064b50) {
-            if (true) throw new ZipException("64-bit zip records unsupported");
-            // zip64 EOD record (0..1)
-            is.readLong();
-            is.readUnsignedShort();
-            is.readUnsignedShort();
-            is.readInt();
-            is.readInt();
-            is.readLong();
-            is.readLong();
-            is.readLong();
-            is.readLong();
-            // next sig
-            sig = is.readInt();
-        }
-        if (sig == 0x07064b50) {
-            if (true) throw new ZipException("64-bit zip records unsupported");
-            // zip64 EOD locator (0..1)
-
-            // next sig
-            sig = is.readInt();
-        }
-        if (sig == 0x06054b50) {
-            // EOD (exactly 1)
-            is.close();
-            return;
-        }
-        throw new ZipException(String.format("Unexpected signature byte 0x%08x", Integer.valueOf(sig)));
     }
 
     public ZipCatalog getZipCatalog() {




More information about the jboss-svn-commits mailing list