You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2009/10/07 20:54:09 UTC

svn commit: r822846 [1/2] - in /harmony/enhanced/classlib/trunk: modules/archive/src/main/java/java/util/jar/ modules/archive/src/main/java/java/util/zip/ modules/archive/src/main/native/archive/shared/ modules/archive/src/main/native/archive/unix/ mod...

Author: tellison
Date: Wed Oct  7 18:54:08 2009
New Revision: 822846

URL: http://svn.apache.org/viewvc?rev=822846&view=rev
Log:
Apply part of patch from HARMONY-6346 ([classlib] [archive] Several archive bugfixes and optimizations)

Added:
    harmony/enhanced/classlib/trunk/support/src/test/java/tests/resources/EmptyEntries_signed.jar   (with props)
Modified:
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarFile.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarVerifier.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPInputStream.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPOutputStream.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/Inflater.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/InflaterInputStream.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipEntry.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/inflater.c
    harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/zip.c
    harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/unix/exports.txt
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/CheckedInputStreamTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/DeflaterOutputStreamTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterInputStreamTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipEntryTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
    harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipInputStreamTest.java

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarFile.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarFile.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarFile.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarFile.java Wed Oct  7 18:54:08 2009
@@ -17,6 +17,9 @@
 
 package java.util.jar;
 
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+import java.util.ArrayList;
 import java.io.File;
 import java.io.FilterInputStream;
 import java.io.IOException;
@@ -49,6 +52,8 @@
 
     JarVerifier verifier;
 
+    private boolean closed = false;
+
     static final class JarFileInputStream extends FilterInputStream {
         private long count;
 
@@ -56,6 +61,8 @@
 
         private JarVerifier.VerifierEntry entry;
 
+        private boolean done = false;
+
         JarFileInputStream(InputStream is, ZipEntry ze,
                 JarVerifier.VerifierEntry e) {
             super(is);
@@ -66,6 +73,9 @@
 
         @Override
         public int read() throws IOException {
+            if (done) {
+                return -1;
+            }
             if (count > 0) {
                 int r = super.read();
                 if (r != -1) {
@@ -75,16 +85,22 @@
                     count = 0;
                 }
                 if (count == 0) {
+                    done = true;
                     entry.verify();
                 }
                 return r;
             } else {
+                done = true;
+                entry.verify();
                 return -1;
             }
         }
 
         @Override
         public int read(byte[] buf, int off, int nbytes) throws IOException {
+            if (done) {
+                return -1;
+            }
             if (count > 0) {
                 int r = super.read(buf, off, nbytes);
                 if (r != -1) {
@@ -98,15 +114,26 @@
                     count = 0;
                 }
                 if (count == 0) {
+                    done = true;
                     entry.verify();
                 }
                 return r;
             } else {
+                done = true;
+                entry.verify();
                 return -1;
             }
         }
 
         @Override
+        public int available() throws IOException {
+            if (done) {
+                return 0;
+            }
+            return super.available();
+        }
+
+        @Override
         public long skip(long nbytes) throws IOException {
             long cnt = 0, rem = 0;
             byte[] buf = new byte[4096];
@@ -252,6 +279,21 @@
         return (JarEntry) getEntry(name);
     }
 
+    private byte[] getAllBytesFromStreamAndClose(InputStream is) throws IOException {
+        ByteArrayOutputStream bs = new ByteArrayOutputStream();
+        try {
+            byte[] buf = new byte[1024];
+            while (is.available() > 0) {
+                int iRead = is.read(buf, 0, buf.length);
+                if (iRead > 0)
+                    bs.write(buf, 0, iRead);
+            }
+        } finally {
+            is.close();
+        }
+        return bs.toByteArray();
+    }
+
     /**
      * Returns the {@code Manifest} object associated with this {@code JarFile}
      * or {@code null} if no MANIFEST entry exists.
@@ -264,17 +306,17 @@
      * @see Manifest
      */
     public Manifest getManifest() throws IOException {
+        if (closed) {
+            throw new IllegalStateException("JarFile has been closed.");
+        }
         if (manifest != null) {
             return manifest;
         }
         try {
             InputStream is = super.getInputStream(manifestEntry);
             if (verifier != null) {
-                byte[] buf = new byte[is.available()];
-                is.mark(buf.length);
-                is.read(buf, 0, buf.length);
-                is.reset();
-                verifier.addMetaEntry(manifestEntry.getName(), buf);
+                verifier.addMetaEntry(manifestEntry.getName(), getAllBytesFromStreamAndClose(is));
+                is = super.getInputStream(manifestEntry);
             }
             try {
                 manifest = new Manifest(is, verifier != null);
@@ -289,7 +331,7 @@
     }
 
     private void readMetaEntries() throws IOException {
-        ZipEntry[] metaEntries = getMetaEntriesImpl(null);
+        ZipEntry[] metaEntries = getMetaEntriesImpl();
         int dirLength = META_DIR.length();
 
         boolean signed = false;
@@ -316,12 +358,7 @@
                                 entryName.length() - 4, ".RSA", 0, 4))) { //$NON-NLS-1$
                     signed = true;
                     InputStream is = super.getInputStream(entry);
-                    byte[] buf = new byte[is.available()];
-                    try {
-                        is.read(buf, 0, buf.length);
-                    } finally {
-                        is.close();
-                    }
+                    byte[] buf = getAllBytesFromStreamAndClose(is);
                     verifier.addMetaEntry(entryName, buf);
                 }
             }
@@ -394,6 +431,34 @@
         return je;
     }
 
-    private native ZipEntry[] getMetaEntriesImpl(byte[] buf);
+    private ZipEntry[] getMetaEntriesImpl() {
+        List<ZipEntry> list = new ArrayList<ZipEntry>();
+
+        Enumeration<? extends ZipEntry> allEntries = entries();
+        while (allEntries.hasMoreElements()) {
+            ZipEntry ze = allEntries.nextElement();
+            if (ze.getName().startsWith("META-INF/") && ze.getName().length() > 9) {
+                list.add(ze);
+            }
+        }
+        if (list.size() != 0) {
+            ZipEntry[] result = new ZipEntry[list.size()];
+            list.toArray(result);
+            return result;
+        } else {
+            return null;
+        }
+    }
 
+    /**
+     * Closes this {@code JarFile}.
+     *
+     * @throws IOException
+     *             if an error occurs.
+     */
+    @Override
+    public void close() throws IOException {
+        super.close();
+        closed = true;
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarVerifier.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarVerifier.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarVerifier.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/jar/JarVerifier.java Wed Oct  7 18:54:08 2009
@@ -117,7 +117,6 @@
          *             if the digest value stored in the manifest does <i>not</i>
          *             agree with the decrypted digest as recovered from the
          *             <code>.SF</code> file.
-         * @see #initEntry(String)
          */
         void verify() {
             byte[] d = digest.digest();
@@ -375,7 +374,7 @@
      * Associate this verifier with the specified {@link Manifest} object.
      * 
      * @param mf
-     *            a <code>java.util.jar.Manifest</code> object.
+     *            a {@code java.util.jar.Manifest} object.
      */
     void setManifest(Manifest mf) {
         man = mf;
@@ -385,7 +384,7 @@
      * Returns a <code>boolean</code> indication of whether or not the
      * associated jar file is signed.
      * 
-     * @return <code>true</code> if the jar is signed, <code>false</code>
+     * @return {@code true} if the JAR is signed, {@code false}
      *         otherwise.
      */
     boolean isSignedJar() {

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPInputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPInputStream.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPInputStream.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPInputStream.java Wed Oct  7 18:54:08 2009
@@ -161,37 +161,49 @@
         if (closed) {
             throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
         }
-        if (eof) {
+        if (eos) {
             return -1;
         }
         // avoid int overflow, check null buffer
-        if (off <= buffer.length && nbytes >= 0 && off >= 0
-                && buffer.length - off >= nbytes) {
-            int val = super.read(buffer, off, nbytes);
-            if (val != -1) {
-                crc.update(buffer, off, val);
-            } else if (!eos) {
-                eos = true;
-                // Get non-compressed bytes read by fill
-                int size = inf.getRemaining();
-                final int trailerSize = 8; // crc (4 bytes) + total out (4
-                // bytes)
-                byte[] b = new byte[trailerSize];
-                int copySize = (size > trailerSize) ? trailerSize : size;
-
-                System.arraycopy(buf, len - size, b, 0, copySize);
-                readFully(b, copySize, trailerSize - copySize);
-
-                if (getLong(b, 0) != crc.getValue()) {
-                    throw new IOException(Messages.getString("archive.20")); //$NON-NLS-1$
-                }
-                if ((int) getLong(b, 4) != inf.getTotalOut()) {
-                    throw new IOException(Messages.getString("archive.21")); //$NON-NLS-1$
-                }
-            }
-            return val;
+        if (off > buffer.length || nbytes < 0 || off < 0
+                || buffer.length - off < nbytes) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        int bytesRead;
+        try {
+            bytesRead = super.read(buffer, off, nbytes);
+        } finally {
+            eos = eof; // update eos after every read(), even when it throws
+        }
+
+        if (bytesRead != -1) {
+            crc.update(buffer, off, bytesRead);
+        }
+
+        if (eos) {
+            verifyCrc();
+        }
+
+        return bytesRead;
+    }
+
+    private void verifyCrc() throws IOException {
+        // Get non-compressed bytes read by fill
+        int size = inf.getRemaining();
+        final int trailerSize = 8; // crc (4 bytes) + total out (4 bytes)
+        byte[] b = new byte[trailerSize];
+        int copySize = (size > trailerSize) ? trailerSize : size;
+
+        System.arraycopy(buf, len - size, b, 0, copySize);
+        readFully(b, copySize, trailerSize - copySize);
+
+        if (getLong(b, 0) != crc.getValue()) {
+            throw new IOException(Messages.getString("archive.20")); //$NON-NLS-1$
+        }
+        if ((int) getLong(b, 4) != inf.getTotalOut()) {
+            throw new IOException(Messages.getString("archive.21")); //$NON-NLS-1$
         }
-        throw new ArrayIndexOutOfBoundsException();
     }
 
     private void readFully(byte[] buffer, int offset, int length)

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPOutputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPOutputStream.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPOutputStream.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/GZIPOutputStream.java Wed Oct  7 18:54:08 2009
@@ -92,10 +92,11 @@
 
     private long writeLong(long i) throws IOException {
         // Write out the long value as an unsigned int
-        out.write((int) (i & 0xFF));
-        out.write((int) (i >> 8) & 0xFF);
-        out.write((int) (i >> 16) & 0xFF);
-        out.write((int) (i >> 24) & 0xFF);
+        int unsigned = (int) i;
+        out.write(unsigned & 0xFF);
+        out.write((unsigned >> 8) & 0xFF);
+        out.write((unsigned >> 16) & 0xFF);
+        out.write((unsigned >> 24) & 0xFF);
         return i;
     }
 

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/Inflater.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/Inflater.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/Inflater.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/Inflater.java Wed Oct  7 18:54:08 2009
@@ -47,16 +47,12 @@
 
     private boolean finished; // Set by the inflateImpl native
 
-    private boolean gotFirstHeaderByte;
-
     int inLength;
 
     int inRead;
 
     private boolean needsDictionary; // Set by the inflateImpl native
 
-    private boolean pass_magic_number_check = true;
-
     private long streamHandle = -1;
 
     /**
@@ -78,13 +74,12 @@
      */
     public Inflater(boolean noHeader) {
         streamHandle = createStream(noHeader);
-        gotFirstHeaderByte = noHeader;
     }
 
     private native long createStream(boolean noHeader1);
 
     /**
-     * Release any resources associated with this Inflater. Any unused
+     * Release any resources associated with this {@code Inflater}. Any unused
      * input/output is discarded. This is also called by the finalize method.
      */
     public synchronized void end() {
@@ -164,9 +159,9 @@
 
     /**
      * Returns the number of bytes of current input remaining to be read by the
-     * inflater
+     * inflater.
      * 
-     * @return Number of bytes of unread input.
+     * @return the number of bytes of unread input.
      */
     public synchronized int getRemaining() {
         return inLength - inRead;
@@ -238,32 +233,32 @@
     public synchronized int inflate(byte[] buf, int off, int nbytes)
             throws DataFormatException {
         // avoid int overflow, check null buf
-        if (off <= buf.length && nbytes >= 0 && off >= 0
-                && buf.length - off >= nbytes) {
-            if (nbytes == 0)
-                return 0;
+        if (off > buf.length || nbytes < 0 || off < 0
+                || buf.length - off < nbytes) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        if (nbytes == 0) {
+            return 0;
+        }
+
+        if (streamHandle == -1) {
+            throw new IllegalStateException();
+        }
 
-            if (streamHandle == -1) {
-                throw new IllegalStateException();
-            }
-
-            if (!pass_magic_number_check) {
-                throw new DataFormatException();
-            }
-
-            if (needsInput()) {
-                return 0;
-            }
-
-            boolean neededDict = needsDictionary;
-            needsDictionary = false;
-            int result = inflateImpl(buf, off, nbytes, streamHandle);
-            if (needsDictionary && neededDict) {
-                throw new DataFormatException(Messages.getString("archive.27")); //$NON-NLS-1$
-            }
-            return result;
+        if (needsInput()) {
+            return 0;
         }
-        throw new ArrayIndexOutOfBoundsException();
+
+        boolean neededDict = needsDictionary;
+        needsDictionary = false;
+        int result = inflateImpl(buf, off, nbytes, streamHandle);
+        if (needsDictionary && neededDict) {
+            throw new DataFormatException(
+                    Messages.getString("archive.27")); //$NON-NLS-1$
+        }
+
+        return result;
     }
 
     private native synchronized int inflateImpl(byte[] buf, int off,
@@ -395,11 +390,6 @@
         } else {
             throw new ArrayIndexOutOfBoundsException();
         }
-
-        if (!gotFirstHeaderByte && nbytes > 0) {
-            pass_magic_number_check = (buf[off] == MAGIC_NUMBER);
-            gotFirstHeaderByte = true;
-        }
     }
 
     private native synchronized void setInputImpl(byte[] buf, int off,

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/InflaterInputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/InflaterInputStream.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/InflaterInputStream.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/InflaterInputStream.java Wed Oct  7 18:54:08 2009
@@ -53,6 +53,11 @@
 
     boolean closed;
 
+    /**
+     * True if this stream's last byte has been returned to the user. This
+     * could be because the underlying stream has been exhausted, or if errors
+     * were encountered while inflating that stream.
+     */
     boolean eof;
 
     static final int BUF_SIZE = 512;
@@ -155,41 +160,45 @@
             return 0;
         }
 
-        if (inf.finished()) {
-            eof = true;
+        if (eof) {
             return -1;
         }
 
         // avoid int overflow, check null buffer
-        if (off <= buffer.length && nbytes >= 0 && off >= 0
-                && buffer.length - off >= nbytes) {
-            do {
-                if (inf.needsInput()) {
-                    fill();
-                }
-                int result;
-                try {
-                    result = inf.inflate(buffer, off, nbytes);
-                } catch (DataFormatException e) {
-                    if (len == -1) {
-                        throw new EOFException();
-                    }
-                    throw (IOException) (new IOException().initCause(e));
-                }
+        if (off > buffer.length || nbytes < 0 || off < 0
+                || buffer.length - off < nbytes) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        do {
+            if (inf.needsInput()) {
+                fill();
+            }
+            // Invariant: if reading returns -1 or throws, eof must be true.
+            // It may also be true if the next read() should return -1.
+            try {
+                int result = inf.inflate(buffer, off, nbytes);
+                eof = inf.finished();
                 if (result > 0) {
                     return result;
-                } else if (inf.finished()) {
-                    eof = true;
+                } else if (eof) {
                     return -1;
                 } else if (inf.needsDictionary()) {
+                    eof = true;
                     return -1;
                 } else if (len == -1) {
+                    eof = true;
                     throw new EOFException();
                     // If result == 0, fill() and try again
                 }
-            } while (true);
-        }
-        throw new ArrayIndexOutOfBoundsException();
+            } catch (DataFormatException e) {
+                eof = true;
+                if (len == -1) {
+                    throw new EOFException();
+                }
+                throw (IOException) (new IOException().initCause(e));
+            }
+        } while (true);
     }
 
     /**
@@ -219,13 +228,15 @@
     @Override
     public long skip(long nbytes) throws IOException {
         if (nbytes >= 0) {
+            if (buf == null) {
+                buf = new byte[BUF_SIZE];
+            }
             long count = 0, rem = 0;
             while (count < nbytes) {
                 int x = read(buf, 0,
                         (rem = nbytes - count) > buf.length ? buf.length
                                 : (int) rem);
                 if (x == -1) {
-                    eof = true;
                     return count;
                 }
                 count += x;
@@ -236,9 +247,18 @@
     }
 
     /**
-     * Returns whether data can be read from this stream.
-     * 
-     * @return 0 if this stream has been closed, 1 otherwise.
+     * Returns 0 when when this stream has exhausted its input; and 1 otherwise.
+     * A result of 1 does not guarantee that further bytes can be returned,
+     * with or without blocking.
+     *
+     * <p>Although consistent with the RI, this behavior is inconsistent with
+     * {@link InputStream#available()}, and violates the <a
+     * href="http://en.wikipedia.org/wiki/Liskov_substitution_principle">Liskov
+     * Substitution Principle</a>. This method should not be used.
+     *
+     * @return 0 if no further bytes are available. Otherwise returns 1,
+     *         which suggests (but does not guarantee) that additional bytes are
+     *         available.
      * @throws IOException
      *             If an error occurs.
      */

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipEntry.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipEntry.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipEntry.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipEntry.java Wed Oct  7 18:54:08 2009
@@ -17,6 +17,11 @@
 
 package java.util.zip;
 
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.GregorianCalendar;
@@ -28,19 +33,22 @@
  * itself. For example when reading a <i>ZIP-file</i> you will first retrieve
  * all its entries in a collection and then read the data for a specific entry
  * through an input stream.
- * 
+ *
  * @see ZipFile
  * @see ZipOutputStream
  */
 public class ZipEntry implements ZipConstants, Cloneable {
     String name, comment;
 
-    long compressedSize = -1, crc = -1, size = -1, dataOffset = -1;
+    long compressedSize = -1, crc = -1, size = -1;
 
     int compressionMethod = -1, time = -1, modDate = -1;
 
     byte[] extra;
 
+    int nameLen = -1;
+    long mLocalHeaderRelOffset = -1;
+
     /**
      * Zip entry state: Deflated.
      */
@@ -288,21 +296,6 @@
         return name;
     }
 
-    ZipEntry(String name, String comment, byte[] extra, long modTime,
-            long size, long compressedSize, long crc, int compressionMethod,
-            long modDate, long offset) {
-        this.name = name;
-        this.comment = comment;
-        this.extra = extra;
-        time = (int) modTime;
-        this.size = size;
-        this.compressedSize = compressedSize;
-        this.crc = crc;
-        this.compressionMethod = compressionMethod;
-        this.modDate = (int) modDate;
-        dataOffset = offset;
-    }
-
     /**
      * Constructs a new {@code ZipEntry} using the values obtained from {@code
      * ze}.
@@ -320,7 +313,8 @@
         compressionMethod = ze.compressionMethod;
         modDate = ze.modDate;
         extra = ze.extra;
-        dataOffset = ze.dataOffset;
+        nameLen = ze.nameLen;
+        mLocalHeaderRelOffset = ze.mLocalHeaderRelOffset;
     }
 
     /**
@@ -342,4 +336,146 @@
     public int hashCode() {
         return name.hashCode();
     }
+
+    /*
+     * Internal constructor.  Creates a new ZipEntry by reading the
+     * Central Directory Entry from "in", which must be positioned at
+     * the CDE signature.
+     *
+     * On exit, "in" will be positioned at the start of the next entry.
+     */
+    ZipEntry(LittleEndianReader ler, InputStream in) throws IOException {
+
+        /*
+         * We're seeing performance issues when we call readShortLE and
+         * readIntLE, so we're going to read the entire header at once
+         * and then parse the results out without using any function calls.
+         * Uglier, but should be much faster.
+         *
+         * Note that some lines look a bit different, because the corresponding
+         * fields or locals are long and so we need to do & 0xffffffffl to avoid
+         * problems induced by sign extension.
+         */
+
+        byte[] hdrBuf = ler.hdrBuf;
+        myReadFully(in, hdrBuf);
+
+        long sig = (hdrBuf[0] & 0xff) | ((hdrBuf[1] & 0xff) << 8) |
+            ((hdrBuf[2] & 0xff) << 16) | ((hdrBuf[3] << 24) & 0xffffffffL);
+        if (sig != CENSIG) {
+             throw new ZipException("Central Directory Entry not found");
+        }
+
+        compressionMethod = (hdrBuf[10] & 0xff) | ((hdrBuf[11] & 0xff) << 8);
+        time = (hdrBuf[12] & 0xff) | ((hdrBuf[13] & 0xff) << 8);
+        modDate = (hdrBuf[14] & 0xff) | ((hdrBuf[15] & 0xff) << 8);
+        crc = (hdrBuf[16] & 0xff) | ((hdrBuf[17] & 0xff) << 8)
+                | ((hdrBuf[18] & 0xff) << 16)
+                | ((hdrBuf[19] << 24) & 0xffffffffL);
+        compressedSize = (hdrBuf[20] & 0xff) | ((hdrBuf[21] & 0xff) << 8)
+                | ((hdrBuf[22] & 0xff) << 16)
+                | ((hdrBuf[23] << 24) & 0xffffffffL);
+        size = (hdrBuf[24] & 0xff) | ((hdrBuf[25] & 0xff) << 8)
+                | ((hdrBuf[26] & 0xff) << 16)
+                | ((hdrBuf[27] << 24) & 0xffffffffL);
+        nameLen = (hdrBuf[28] & 0xff) | ((hdrBuf[29] & 0xff) << 8);
+        int extraLen = (hdrBuf[30] & 0xff) | ((hdrBuf[31] & 0xff) << 8);
+        int commentLen = (hdrBuf[32] & 0xff) | ((hdrBuf[33] & 0xff) << 8);
+        mLocalHeaderRelOffset = (hdrBuf[42] & 0xff) | ((hdrBuf[43] & 0xff) << 8)
+                | ((hdrBuf[44] & 0xff) << 16)
+                | ((hdrBuf[45] << 24) & 0xffffffffL);
+
+        byte[] nameBytes = new byte[nameLen];
+        myReadFully(in, nameBytes);
+
+        byte[] commentBytes = null;
+        if (commentLen > 0) {
+            commentBytes = new byte[commentLen];
+            myReadFully(in, commentBytes);
+        }
+
+        if (extraLen > 0) {
+            extra = new byte[extraLen];
+            myReadFully(in, extra);
+        }
+
+        try {
+            /*
+             * The actual character set is "IBM Code Page 437".  As of
+             * Sep 2006, the Zip spec (APPNOTE.TXT) supports UTF-8.  When
+             * bit 11 of the GP flags field is set, the file name and
+             * comment fields are UTF-8.
+             *
+             * TODO: add correct UTF-8 support.
+             */
+            name = new String(nameBytes, "ISO-8859-1");
+            if (commentBytes != null) {
+                comment = new String(commentBytes, "ISO-8859-1");
+            } else {
+                comment = null;
+            }
+        } catch (UnsupportedEncodingException uee) {
+            throw new InternalError(uee.getMessage());
+        }
+    }
+
+    private void myReadFully(InputStream in, byte[] b) throws IOException {
+        int len = b.length;
+        int off = 0;
+
+        while (len > 0) {
+            int count = in.read(b, off, len);
+            if (count <= 0) {
+                throw new EOFException();
+            }
+            off += count;
+            len -= count;
+        }
+    }
+
+    /*
+     * Read a four-byte int in little-endian order.
+     */
+    static long readIntLE(RandomAccessFile raf) throws IOException {
+        int b0 = raf.read();
+        int b1 = raf.read();
+        int b2 = raf.read();
+        int b3 = raf.read();
+
+        if (b3 < 0) {
+            throw new EOFException("in ZipEntry.readIntLE(RandomAccessFile)");
+        }
+        return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); // ATTENTION: DOES SIGN EXTENSION: IS THIS WANTED?
+    }
+
+    static class LittleEndianReader {
+        private byte[] b = new byte[4];
+        byte[] hdrBuf = new byte[CENHDR];
+
+        /*
+         * Read a two-byte short in little-endian order.
+         */
+        int readShortLE(InputStream in) throws IOException {
+            if (in.read(b, 0, 2) == 2) {
+                return (b[0] & 0XFF) | ((b[1] & 0XFF) << 8);
+            } else {
+                throw new EOFException("in ZipEntry.readShortLE(InputStream)");
+            }
+        }
+
+        /*
+         * Read a four-byte int in little-endian order.
+         */
+        long readIntLE(InputStream in) throws IOException {
+            if (in.read(b, 0, 4) == 4) {
+                return (   ((b[0] & 0XFF))
+                         | ((b[1] & 0XFF) << 8)
+                         | ((b[2] & 0XFF) << 16)
+                         | ((b[3] & 0XFF) << 24))
+                       & 0XFFFFFFFFL; // Here for sure NO sign extension is wanted.
+            } else {
+                throw new EOFException("in ZipEntry.readIntLE(InputStream)");
+            }
+        }
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipFile.java Wed Oct  7 18:54:08 2009
@@ -17,17 +17,17 @@
 
 package java.util.zip;
 
-import java.io.ByteArrayInputStream;
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.RandomAccessFile;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Collections;
 import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-import org.apache.harmony.archive.internal.nls.Messages;
-import org.apache.harmony.luni.util.Util;
+import java.util.LinkedHashMap;
+import java.util.Iterator;
 
 /**
  * This class provides random read access to a <i>ZIP-archive</i> file.
@@ -45,28 +45,27 @@
  */
 public class ZipFile implements ZipConstants {
 
-    String fileName;
-
-    long descriptor = -1;
-
-    private int size = -1;
-
-    private int mode;
-    static {
-        System.loadLibrary("hyarchive"); //$NON-NLS-1$
-        ntvinit();
-    }
-
     /**
-     * Open zip file for read.
+     * Open ZIP file for read.
      */
     public static final int OPEN_READ = 1;
 
     /**
-     * Delete zip file when closed.
+     * Delete ZIP file when closed.
      */
     public static final int OPEN_DELETE = 4;
 
+    private final String fileName;
+
+    private File fileToDeleteOnClose;
+
+    private RandomAccessFile mRaf;
+
+    private final ZipEntry.LittleEndianReader ler = new ZipEntry.LittleEndianReader();
+
+    private final LinkedHashMap<String, ZipEntry> mEntries
+            = new LinkedHashMap<String, ZipEntry>();
+
     /**
      * Constructs a new {@code ZipFile} with the specified file.
      * 
@@ -78,7 +77,7 @@
      *             if an {@code IOException} occurs.
      */
     public ZipFile(File file) throws ZipException, IOException {
-        this(file.getPath());
+        this(file, OPEN_READ);
     }
 
     /**
@@ -94,20 +93,27 @@
      *             if an {@code IOException} occurs.
      */
     public ZipFile(File file, int mode) throws IOException {
-        if (mode == OPEN_READ || mode == (OPEN_READ | OPEN_DELETE)) {
-            fileName = file.getPath();
-            SecurityManager security = System.getSecurityManager();
+        fileName = file.getPath();
+        if (mode != OPEN_READ && mode != (OPEN_READ | OPEN_DELETE)) {
+            throw new IllegalArgumentException();
+        }
+
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkRead(fileName);
+        }
+        if ((mode & OPEN_DELETE) != 0) {
             if (security != null) {
-                security.checkRead(fileName);
-                if ((mode & OPEN_DELETE) != 0) {
-                    security.checkDelete(fileName);
-                }
+                security.checkDelete(fileName);
             }
-            this.mode = mode;
-            openZip();
+            fileToDeleteOnClose = file; // file.deleteOnExit();
         } else {
-            throw new IllegalArgumentException();
+            fileToDeleteOnClose = null;
         }
+
+        mRaf = new RandomAccessFile(fileName, "r");
+
+        readCentralDir();
     }
 
     /**
@@ -119,29 +125,7 @@
      *             if an IOException occurs.
      */
     public ZipFile(String name) throws IOException {
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) {
-            security.checkRead(name);
-        }
-        fileName = name;
-        openZip();
-    }
-
-    private void openZip() throws IOException {
-        int result = openZipImpl(Util.getUTF8Bytes(fileName));
-
-        if (result != 0) {
-            switch (result) {
-            case 1:
-                throw new ZipException(Messages.getString(
-                        "archive.24", fileName)); //$NON-NLS-1$
-            case 2:
-                throw new ZipException(Messages.getString(
-                        "archive.25", fileName)); //$NON-NLS-1$
-            default:
-                throw new OutOfMemoryError();
-            }
-        }
+        this(new File(name), OPEN_READ);
     }
 
     @Override
@@ -150,34 +134,60 @@
     }
 
     /**
-     * Closes this ZIP file.
+     * Closes this ZIP file. This method is idempotent.
      * 
      * @throws IOException
      *             if an IOException occurs.
      */
-    public synchronized void close() throws IOException {
-        if (descriptor != -1 && fileName != null) {
-            // Only close initialized instances
-            closeZipImpl(descriptor);
-            if ((mode & OPEN_DELETE) != 0) {
+    public void close() throws IOException {
+        RandomAccessFile raf = mRaf;
+
+        if (raf != null) { // Only close initialized instances
+            synchronized(raf) {
+                mRaf = null;
+                raf.close();
+            }
+            if (fileToDeleteOnClose != null) {
                 AccessController.doPrivileged(new PrivilegedAction<Object>() {
                     public Object run() {
                         new File(fileName).delete();
                         return null;
                     }
                 });
+                // fileToDeleteOnClose.delete();
+                fileToDeleteOnClose = null;
             }
         }
     }
 
+    private void checkNotClosed() {
+        if (mRaf == null) {
+            throw new IllegalStateException("Zip File closed.");
+        }
+    }
+
     /**
      * Returns an enumeration of the entries. The entries are listed in the
      * order in which they appear in the ZIP archive.
      * 
      * @return the enumeration of the entries.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public Enumeration<? extends ZipEntry> entries() {
-        return new ZFEnum<ZipEntry>();
+        checkNotClosed();
+        final Iterator<ZipEntry> iterator = mEntries.values().iterator();
+
+        return new Enumeration<ZipEntry>() {
+            public boolean hasMoreElements() {
+                checkNotClosed();
+                return iterator.hasNext();
+            }
+
+            public ZipEntry nextElement() {
+                checkNotClosed();
+                return iterator.next();
+            }
+        };
     }
 
     /**
@@ -187,13 +197,19 @@
      *            the name of the entry in the ZIP file.
      * @return a {@code ZipEntry} or {@code null} if the entry name does not
      *         exist in the ZIP file.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public ZipEntry getEntry(String entryName) {
-        if (entryName != null) {
-            ZipEntry entry = getEntryImpl(descriptor, entryName);
-            return entry;
+        checkNotClosed();
+        if (entryName == null) {
+            throw new NullPointerException();
         }
-        throw new NullPointerException();
+
+        ZipEntry ze = mEntries.get(entryName);
+        if (ze == null) {
+            ze = mEntries.get(entryName + "/");
+        }
+        return ze;
     }
 
     /**
@@ -204,20 +220,39 @@
      * @return an input stream of the data contained in the {@code ZipEntry}.
      * @throws IOException
      *             if an {@code IOException} occurs.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public InputStream getInputStream(ZipEntry entry) throws IOException {
-        if (descriptor == -1) {
-            /*
-             * the descriptor is set to -1 by native code to indicate the zip
-             * was closed
-             */
-            throw new IllegalStateException();
-        }
-        byte[] buf = inflateEntryImpl2(descriptor, entry.getName());
-        if (buf == null) {
+        /*
+         * Make sure this ZipEntry is in this Zip file.  We run it through
+         * the name lookup.
+         */
+        entry = getEntry(entry.getName());
+        if (entry == null) {
             return null;
         }
-        return new ByteArrayInputStream(buf);
+
+        /*
+         * Create a ZipInputStream at the right part of the file.
+         */
+        RandomAccessFile raf = mRaf;
+        synchronized (raf) {
+            // We don't know the entry data's start position. All we have is the
+            // position of the entry's local header. At position 28 we find the
+            // length of the extra data. In some cases this length differs from
+            // the one coming in the central header.
+            RAFStream rafstrm = new RAFStream(raf,
+                    entry.mLocalHeaderRelOffset + 28);
+            int localExtraLenOrWhatever = ler.readShortLE(rafstrm);
+            // Skip the name and this "extra" data or whatever it is:
+            rafstrm.skip(entry.nameLen + localExtraLenOrWhatever);
+            rafstrm.mLength = rafstrm.mOffset + entry.compressedSize;
+            if (entry.compressionMethod == ZipEntry.DEFLATED) {
+                return new InflaterInputStream(rafstrm, new Inflater(true));
+            } else {
+                return rafstrm;
+            }
+        }
     }
 
     /**
@@ -229,69 +264,152 @@
         return fileName;
     }
 
-    private synchronized native int openZipImpl(byte[] fileName1);
-
-    private native void closeZipImpl(long descriptor1) throws IOException;
-
-    private native ZipEntry getEntryImpl(long descriptor1, String entryName);
-
-    private native byte[] inflateEntryImpl2(long descriptor1, String entryName)
-            throws ZipException;
-
     /**
      * Returns the number of {@code ZipEntries} in this {@code ZipFile}.
      * 
      * @return the number of entries in this file.
+     * @throws IllegalStateException if this ZIP file has been closed.
      */
     public int size() {
-        if (size != -1) {
-            return size;
-        }
-
-        size = 0;
-        Enumeration<?> e = entries();
-        while (e.hasMoreElements()) {
-            size++;
-            e.nextElement();
-        }
-        return size;
-
+        checkNotClosed();
+        return mEntries.size();
     }
 
-    private static native void ntvinit();
-
-    class ZFEnum<T extends ZipEntry> implements Enumeration<T> {
-        private final long nextEntryPointer;
-
-        private T current;
+    /**
+     * Find the central directory and read the contents.
+     *
+     * <p>The central directory can be followed by a variable-length comment
+     * field, so we have to scan through it backwards.  The comment is at
+     * most 64K, plus we have 18 bytes for the end-of-central-dir stuff
+     * itself, plus apparently sometimes people throw random junk on the end
+     * just for the fun of it.
+     *  
+     * <p>This is all a little wobbly.  If the wrong value ends up in the EOCD
+     * area, we're hosed. This appears to be the way that everybody handles
+     * it though, so we're in good company if this fails.
+     */
+    private void readCentralDir() throws IOException {
+        /*
+         * Scan back, looking for the End Of Central Directory field.  If
+         * the archive doesn't have a comment, we'll hit it on the first
+         * try.
+         *
+         * No need to synchronize mRaf here -- we only do this when we
+         * first open the Zip file.
+         */
+        long scanOffset = mRaf.length() - ENDHDR;
+        if (scanOffset < 0) {
+            throw new ZipException("too short to be Zip");
+        }
+
+        long stopOffset = scanOffset - 65536;
+        if (stopOffset < 0) {
+            stopOffset = 0;
+        }
+
+        while (true) {
+            mRaf.seek(scanOffset);
+            if (ZipEntry.readIntLE(mRaf) == 101010256L) {
+                break;
+            }
 
-        ZFEnum() {
-            nextEntryPointer = resetZip(descriptor);
-            current = getNextEntry(descriptor, nextEntryPointer);
+            scanOffset--;
+            if (scanOffset < stopOffset) {
+                throw new ZipException("EOCD not found; not a Zip archive?");
+            }
         }
 
-        private native long resetZip(long descriptor1);
-
-        private native T getNextEntry(long descriptor1, long nextEntryPointer1);
+        /*
+         * Found it, read the EOCD.
+         *
+         * For performance we want to use buffered I/O when reading the
+         * file.  We wrap a buffered stream around the random-access file
+         * object.  If we just read from the RandomAccessFile we'll be
+         * doing a read() system call every time.
+         */
+        RAFStream rafs = new RAFStream(mRaf, mRaf.getFilePointer());
+        BufferedInputStream bin = new BufferedInputStream(rafs, ENDHDR);
+
+        int diskNumber = ler.readShortLE(bin);
+        int diskWithCentralDir = ler.readShortLE(bin);
+        int numEntries = ler.readShortLE(bin);
+        int totalNumEntries = ler.readShortLE(bin);
+        /*centralDirSize =*/ ler.readIntLE(bin);
+        long centralDirOffset = ler.readIntLE(bin);
+        /*commentLen =*/ ler.readShortLE(bin);
+
+        if (numEntries != totalNumEntries ||
+            diskNumber != 0 ||
+            diskWithCentralDir != 0) {
+            throw new ZipException("spanned archives not supported");
+        }
+
+        /*
+         * Seek to the first CDE and read all entries.
+         */
+        rafs = new RAFStream(mRaf, centralDirOffset);
+        bin = new BufferedInputStream(rafs, 4096);
+        for (int i = 0; i < numEntries; i++) {
+            ZipEntry newEntry = new ZipEntry(ler, bin);
+            mEntries.put(newEntry.getName(), newEntry);
+        }
+    }
+
+    /**
+     * Wrap a stream around a RandomAccessFile.  The RandomAccessFile is shared
+     * among all streams returned by getInputStream(), so we have to synchronize
+     * access to it.  (We can optimize this by adding buffering here to reduce
+     * collisions.)
+     *
+     * <p>We could support mark/reset, but we don't currently need them.
+     */
+    static class RAFStream extends InputStream {
+
+        RandomAccessFile mSharedRaf;
+        long mOffset;
+        long mLength;
+        private byte[] singleByteBuf = new byte[1];
+
+        public RAFStream(RandomAccessFile raf, long pos) throws IOException {
+            mSharedRaf = raf;
+            mOffset = pos;
+            mLength = raf.length();
+        }
+
+        @Override
+        public int available() throws IOException {
+            return (mOffset < mLength ? 1 : 0);
+        }
+
+        public int read() throws IOException {
+            if (read(singleByteBuf, 0, 1) == 1) {
+                return singleByteBuf[0] & 0XFF;
+            } else {
+                return -1;
+            }
+        }
 
-        public boolean hasMoreElements() {
-            if (descriptor == -1) {
-                /*
-                 * the descriptor is set to -1 by native code to indicate the
-                 * zip was closed
-                 */
-                throw new IllegalStateException();
+        public int read(byte[] b, int off, int len) throws IOException {
+            synchronized (mSharedRaf) {
+                mSharedRaf.seek(mOffset);
+                if (mOffset + len > mLength) len = (int) (mLength - mOffset);
+                int count = mSharedRaf.read(b, off, len);
+                if (count > 0) {
+                    mOffset += count;
+                    return count;
+                } else {
+                    return -1;
+                }
             }
-            return current != null;
         }
 
-        public T nextElement() {
-            if (current == null) {
-                throw new NoSuchElementException();
+        @Override
+        public long skip(long n) throws IOException {
+            if (mOffset + n > mLength) {
+                n = mLength - mOffset;
             }
-            T ze = current;
-            current = getNextEntry(descriptor, nextEntryPointer);
-            return ze;
+            mOffset += n;
+            return n;
         }
     }
 }

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/java/util/zip/ZipInputStream.java Wed Oct  7 18:54:08 2009
@@ -53,8 +53,6 @@
 
     static final int ZIPLocalHeaderVersionNeeded = 20;
 
-    private boolean zipClosed = false;
-
     private boolean entriesEnd = false;
 
     private boolean hasDD = false;
@@ -75,7 +73,7 @@
 
     /**
      * Constructs a new {@code ZipInputStream} from the specified input stream.
-     * 
+     *
      * @param stream
      *            the input stream to representing a ZIP archive.
      */
@@ -94,21 +92,20 @@
      */
     @Override
     public void close() throws IOException {
-        if (zipClosed != true) {
+        if (!closed) {
             closeEntry(); // Close the current entry
-            zipClosed = true;
             super.close();
         }
     }
 
     /**
      * Closes the current ZIP entry and positions to read the next entry.
-     * 
+     *
      * @throws IOException
      *             if an {@code IOException} occurs.
      */
     public void closeEntry() throws IOException {
-        if (zipClosed) {
+        if (closed) {
             throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
         }
         if (currentEntry == null) {
@@ -306,56 +303,58 @@
      */
     @Override
     public int read(byte[] buffer, int start, int length) throws IOException {
-        if (zipClosed) {
+        if (closed) {
             throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
         }
         if (inf.finished() || currentEntry == null) {
             return -1;
         }
         // avoid int overflow, check null buffer
-        if (start <= buffer.length && length >= 0 && start >= 0
-                && buffer.length - start >= length) {
-            if (currentEntry.compressionMethod == STORED) {
-                int csize = (int) currentEntry.size;
-                if (inRead >= csize) {
+        if (start > buffer.length || length < 0 || start < 0
+                || buffer.length - start < length) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        if (currentEntry.compressionMethod == STORED) {
+            int csize = (int) currentEntry.size;
+            if (inRead >= csize) {
+                return -1;
+            }
+            if (lastRead >= len) {
+                lastRead = 0;
+                if ((len = in.read(buf)) == -1) {
+                    eof = true;
                     return -1;
                 }
-                if (lastRead >= len) {
-                    lastRead = 0;
-                    if ((len = in.read(buf)) == -1) {
-                        return -1;
-                    }
-                    entryIn += len;
-                }
-                int toRead = length > len ? len - lastRead : length;
-                if ((csize - inRead) < toRead) {
-                    toRead = csize - inRead;
-                }
-                System.arraycopy(buf, lastRead, buffer, start, toRead);
-                lastRead += toRead;
-                inRead += toRead;
-                crc.update(buffer, start, toRead);
-                return toRead;
-            }
-            if (inf.needsInput()) {
-                fill();
-                if (len > 0) {
-                    entryIn += len;
-                }
+                entryIn += len;
             }
-            int read = 0;
-            try {
-                read = inf.inflate(buffer, start, length);
-            } catch (DataFormatException e) {
-                throw new ZipException(e.getMessage());
+            int toRead = length > (len - lastRead) ? len - lastRead : length;
+            if ((csize - inRead) < toRead) {
+                toRead = csize - inRead;
             }
-            if (read == 0 && inf.finished()) {
-                return -1;
+            System.arraycopy(buf, lastRead, buffer, start, toRead);
+            lastRead += toRead;
+            inRead += toRead;
+            crc.update(buffer, start, toRead);
+            return toRead;
+        }
+        if (inf.needsInput()) {
+            fill();
+            if (len > 0) {
+                entryIn += len;
             }
-            crc.update(buffer, start, read);
-            return read;
         }
-        throw new ArrayIndexOutOfBoundsException();
+        int read;
+        try {
+            read = inf.inflate(buffer, start, length);
+        } catch (DataFormatException e) {
+            throw new ZipException(e.getMessage());
+        }
+        if (read == 0 && inf.finished()) {
+            return -1;
+        }
+        crc.update(buffer, start, read);
+        return read;
     }
 
     /**
@@ -369,20 +368,21 @@
      */
     @Override
     public long skip(long value) throws IOException {
-        if (value >= 0) {
-            long skipped = 0;
-            byte[] b = new byte[1024];
-            while (skipped != value) {
-                long rem = value - skipped;
-                int x = read(b, 0, (int) (b.length > rem ? rem : b.length));
-                if (x == -1) {
-                    return skipped;
-                }
-                skipped += x;
+        if (value < 0) {
+            throw new IllegalArgumentException();
+        }
+
+        long skipped = 0;
+        byte[] b = new byte[1024];
+        while (skipped != value) {
+            long rem = value - skipped;
+            int x = read(b, 0, (int) (b.length > rem ? rem : b.length));
+            if (x == -1) {
+                return skipped;
             }
-            return skipped;
+            skipped += x;
         }
-        throw new IllegalArgumentException();
+        return skipped;
     }
 
     /**
@@ -394,22 +394,10 @@
      */
     @Override
     public int available() throws IOException {
-        if (zipClosed) {
+        if (closed) {
             throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
         }
-        if (currentEntry == null) {
-            return 1;
-        }
-        if (currentEntry.compressionMethod == STORED) {
-            if (inRead >= currentEntry.size) {
-                return 0;
-            }
-        } else {
-            if (inf.finished()) {
-                return 0;
-            }
-        }
-        return 1;
+        return (currentEntry == null || inRead < currentEntry.size) ? 1 : 0;
     }
 
     /**

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/inflater.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/inflater.c?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/inflater.c (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/inflater.c Wed Oct  7 18:54:08 2009
@@ -66,7 +66,10 @@
   jstream->dict = NULL;
   jstream->inaddr = NULL;
 
-  /*Unable to find official doc that this is the way to avoid zlib header use. However doc in zipsup.c claims it is so. */
+  /*
+   * In the range 8..15 for checked, or -8..-15 for unchecked inflate. Unchecked
+   * is appropriate for formats like zip that do their own validity checking.
+   */
   if (noHeader)
     wbits = wbits / -1;
   err = inflateInit2 (stream, wbits);   /*Window bits to use. 15 is fastest but consumes the most memory */

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/zip.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/zip.c?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/zip.c (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/shared/zip.c Wed Oct  7 18:54:08 2009
@@ -68,245 +68,6 @@
   throwNewExceptionByName(env, "java/util/zip/ZipException", message);
 }
 
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_openZipImpl (JNIEnv * env, jobject recv,
-                                        jbyteArray zipName)
-{
-  VMI_ACCESS_FROM_ENV (env);
-  PORT_ACCESS_FROM_ENV (env);
-
-  I_32 retval;
-  JCLZipFile *jclZipFile;
-  JCLZipFileLink *zipfileHandles;
-  jsize length;
-  char pathCopy[HyMaxPath];
-#ifndef HY_ZIP_API
-  HyZipCachePool *zipCachePool;
-#else /* HY_ZIP_API */
-  VMIZipFunctionTable *zipFuncs;
-#endif /* HY_ZIP_API */
-
-  jclZipFile = jclmem_allocate_memory (env, sizeof (*jclZipFile));
-  if (!jclZipFile)
-    return 3;
-
-  length = (*env)->GetArrayLength (env, zipName);
-  length = length < HyMaxPath - 1 ? length : HyMaxPath - 1;
-  ((*env)->GetByteArrayRegion (env, zipName, 0, length, (jbyte*)pathCopy));
-  pathCopy[length++] = '\0';
-  ioh_convertToPlatform (pathCopy);
-
-#ifndef HY_ZIP_API
-  /* Open the zip file (caching will be managed automatically by zipsup) */
-  zipCachePool = (*VMI)->GetZipCachePool (VMI);
-  retval =
-    zip_openZipFile (privatePortLibrary, pathCopy, &(jclZipFile->hyZipFile),
-                     zipCachePool);
-#else /* HY_ZIP_API */
-  /* Open the zip file (caching will be managed automatically) */
-  zipFuncs = (*VMI)->GetZipFunctions(VMI);
-  retval = zipFuncs->zip_openZipFile(VMI, pathCopy, &(jclZipFile->hyZipFile), ZIP_FLAG_OPEN_CACHE);
-#endif /* HY_ZIP_API */
-
-  if (retval)
-    {
-      jclmem_free_memory (env, jclZipFile);     /* free on fail */
-
-      if (retval == ZIP_ERR_FILE_OPEN_ERROR)
-        return 1;
-      else
-        return 2;
-    }
-
-  /* Add the zipFile we just allocated to the list of zip files -- we will
-   * free this on UnLoad if its not already free'd.
-   */
-  zipfileHandles = JCL_CACHE_GET (env, zipfile_handles);
-  MUTEX_ENTER (zipfileHandles->mutex);
-  jclZipFile->last = (JCLZipFile *) zipfileHandles;
-  jclZipFile->next = zipfileHandles->next;
-  if (zipfileHandles->next != NULL)
-    zipfileHandles->next->last = jclZipFile;
-  zipfileHandles->next = jclZipFile;
-  MUTEX_EXIT (zipfileHandles->mutex);
-
-  (*env)->SetLongField (env, recv,
-                        JCL_CACHE_GET (env,
-                                       FID_java_util_zip_ZipFile_descriptor),
-			            ((IDATA) jclZipFile));
-  return 0;
-}
-
-JNIEXPORT jobject JNICALL
-Java_java_util_zip_ZipFile_getEntryImpl (JNIEnv * env, jobject recv,
-                                         jlong zipPointer, jstring entryName)
-{
-#ifdef HY_ZIP_API
-  VMI_ACCESS_FROM_ENV(env);
-#else
-  PORT_ACCESS_FROM_ENV (env);
-#endif /* HY_ZIP_API */
-
-  I_32 retval;
-  I_32 extraval;
-#ifdef HY_ZIP_API
-  VMIZipFile *zipFile;
-  VMIZipEntry zipEntry;
-#else
-  HyZipFile *zipFile;
-  HyZipEntry zipEntry;
-#endif
-  jobject java_ZipEntry, extra;
-  jclass entryClass;
-  jmethodID mid;
-  const char *entryCopy;
-  JCLZipFile *jclZipFile = (JCLZipFile *) (IDATA) zipPointer;
-#ifdef HY_ZIP_API
-  VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI);
-#endif /* HY_ZIP_API */
-
-  if (jclZipFile == (void *) -1)
-    {
-      throwNewIllegalStateException (env, "");
-      return NULL;
-    }
-  zipFile = &(jclZipFile->hyZipFile);
-  entryCopy = (*env)->GetStringUTFChars (env, entryName, NULL);
-  if (entryCopy == NULL)
-    return (jobject) NULL;
-
-#ifndef HY_ZIP_API
-  zip_initZipEntry (PORTLIB, &zipEntry);
-  retval = zip_getZipEntry (PORTLIB, zipFile, &zipEntry, entryCopy, TRUE);
-#else /* HY_ZIP_API */
-  zipFuncs->zip_initZipEntry (VMI, &zipEntry);
-  retval = zipFuncs->zip_getZipEntry (VMI, zipFile, &zipEntry, entryCopy, ZIP_FLAG_FIND_DIRECTORY|ZIP_FLAG_READ_DATA_POINTER);
-#endif /* HY_ZIP_API */
-  (*env)->ReleaseStringUTFChars (env, entryName, entryCopy);
-  if (retval)
-    {
-#ifndef HY_ZIP_API
-      zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-	  zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-      return (jobject) NULL;
-    }
-
-  extra = NULL;
-  if (zipEntry.extraFieldLength > 0)
-    {
-      extraval =
-#ifndef HY_ZIP_API
-        zip_getZipEntryExtraField (PORTLIB, zipFile, &zipEntry, NULL,
-#else /* HY_ZIP_API */
-	    zipFuncs->zip_getZipEntryExtraField (VMI, zipFile, &zipEntry, NULL,
-#endif /* HY_ZIP_API */
-                                 zipEntry.extraFieldLength);
-      if (extraval || zipEntry.extraField == NULL)
-        {
-#ifndef HY_ZIP_API
-          zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-    	  zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-          if (extraval)
-            {
-              char buf[50];
-              sprintf (buf, "Error %d getting extra field of zip entry", extraval);
-              throwNewInternalError (env, buf);
-            }
-          return (jobject) NULL;
-        }
-      extra = ((*env)->NewByteArray (env, zipEntry.extraFieldLength));
-      if (((*env)->ExceptionCheck (env)))
-        {
-#ifndef HY_ZIP_API
-          zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-    	  zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-          return (jobject) NULL;
-        }
-      ((*env)->
-       SetByteArrayRegion (env, extra, 0, zipEntry.extraFieldLength,
-                           (jbyte*)zipEntry.extraField));
-    }
-
-  entryClass = JCL_CACHE_GET (env, CLS_java_util_zip_ZipEntry);
-  entryClass = (*env)->NewLocalRef(env, entryClass);
-  if (entryClass == NULL) {
-#ifndef HY_ZIP_API
-    zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-    zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-    return (jobject) NULL;
-  }
-  mid = JCL_CACHE_GET (env, MID_java_util_zip_ZipEntry_init);
-  /* Build a new ZipEntry from the C struct */
-  java_ZipEntry = ((*env)->NewObject (env, entryClass, mid, entryName, NULL,
-                                      extra,
-                                      (jlong) zipEntry.lastModTime,
-                                      (jlong) zipEntry.uncompressedSize,
-                                      (jlong) zipEntry.compressedSize,
-                                      (jlong) zipEntry.crc32,
-                                      zipEntry.compressionMethod,
-                                      (jlong) zipEntry.lastModDate,
-                                      (jlong) zipEntry.dataPointer));
-#ifndef HY_ZIP_API
-  zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-  zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-  return java_ZipEntry;
-}
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_closeZipImpl (JNIEnv * env, jobject recv, jlong zipPointer)
-{
-  PORT_ACCESS_FROM_ENV (env);
-#ifdef HY_ZIP_API
-  VMI_ACCESS_FROM_ENV(env);
-#endif /* HY_ZIP_API */
-
-  I_32 retval = 0;
-  jfieldID descriptorFID;
-  JCLZipFileLink *zipfileHandles;
-  JCLZipFile *jclZipFile = (JCLZipFile *) (IDATA) zipPointer;
-#ifdef HY_ZIP_API
-  VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI);
-#endif /* HY_ZIP_API */
-
-  if (jclZipFile != (void *) -1)
-    {
-      retval =
-#ifndef HY_ZIP_API
-        zip_closeZipFile (privatePortLibrary, &(jclZipFile->hyZipFile));
-#else /* HY_ZIP_API */
-        zipFuncs->zip_closeZipFile (VMI, &(jclZipFile->hyZipFile));
-#endif /* HY_ZIP_API */
-      descriptorFID = JCL_CACHE_GET (env, FID_java_util_zip_ZipFile_descriptor);
-      (*env)->SetLongField (env, recv, descriptorFID, -1);
-
-      /* Free the zip struct */
-	  zipfileHandles = JCL_CACHE_GET (env, zipfile_handles);
-      MUTEX_ENTER (zipfileHandles->mutex);
-      if (jclZipFile->last != NULL)
-        jclZipFile->last->next = jclZipFile->next;
-      if (jclZipFile->next != NULL)
-        jclZipFile->next->last = jclZipFile->last;
-      MUTEX_EXIT (zipfileHandles->mutex);
-
-      jclmem_free_memory (env, jclZipFile);
-      if (retval)
-        {
-          throwJavaZIOException (env, "");
-          return;
-        }
-    }
-}
-
 /**
   * Throw java.lang.IllegalStateException
   */
@@ -325,304 +86,4 @@
   throwNewExceptionByName(env, "java/lang/IllegalArgumentException", message);
 }
 
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_ntvinit (JNIEnv * env, jclass cls)
-{
-  PORT_ACCESS_FROM_ENV (env);
-  jmethodID mid;
-  jfieldID descriptorFID;
-  jclass javaClass;
-  JCLZipFileLink *zipfileHandles;
-
-  javaClass = (*env)->FindClass (env, "java/util/zip/ZipEntry");
-  javaClass = (*env)->NewGlobalRef (env, javaClass);
-  if (!javaClass)
-    return;
-  mid =
-    ((*env)->
-     GetMethodID (env, javaClass, "<init>",
-                  "(Ljava/lang/String;Ljava/lang/String;[BJJJJIJJ)V"));
-  if (!mid)
-    return;
-  JCL_CACHE_SET (env, CLS_java_util_zip_ZipEntry, javaClass);
-  JCL_CACHE_SET (env, MID_java_util_zip_ZipEntry_init, mid);
-
-  descriptorFID = (*env)->GetFieldID (env, cls, "descriptor", "J");
-  if (!descriptorFID)
-    return;
-  JCL_CACHE_SET (env, FID_java_util_zip_ZipFile_descriptor, descriptorFID);
-
-  javaClass = (*env)->FindClass (env, "java/util/zip/ZipFile$ZFEnum");
-  if (!javaClass)
-    return;
-  descriptorFID =
-    (*env)->GetFieldID (env, javaClass, "nextEntryPointer", "J");
-  if (!descriptorFID)
-    return;
-  JCL_CACHE_SET (env, FID_java_util_zip_ZipFile_nextEntryPointer,
-                 descriptorFID);
-
-  zipfileHandles = jclmem_allocate_memory (env, sizeof (JCLZipFileLink));
-  if (!zipfileHandles)
-    return;
-  zipfileHandles->last = NULL;
-  zipfileHandles->next = NULL;
-  MUTEX_INIT (zipfileHandles->mutex);
-  JCL_CACHE_SET (env, zipfile_handles, zipfileHandles);
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_00024ZFEnum_resetZip (JNIEnv * env, jobject recv,
-                                                 jlong descriptor)
-{
-#ifdef HY_ZIP_API
-  VMI_ACCESS_FROM_ENV(env);
-#else
-  PORT_ACCESS_FROM_ENV (env);
-#endif /* HY_ZIP_API */
-
-  IDATA nextEntryPointer;
-  JCLZipFile *jclZipFile = (JCLZipFile *) (IDATA) descriptor;
-#ifdef HY_ZIP_API
-  VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI);
-#endif /* HY_ZIP_API */
-
-  if (jclZipFile == (void *) -1)
-    {
-      throwNewIllegalStateException (env, "");
-      return 0;
-    }
-#ifndef HY_ZIP_API
-  zip_resetZipFile (privatePortLibrary,
-#else /* HY_ZIP_API */
-  zipFuncs->zip_resetZipFile (VMI,
-#endif /* HY_ZIP_API */
-		    &(jclZipFile->hyZipFile), 
-                    &nextEntryPointer);
-  return nextEntryPointer;
-}
-
-JNIEXPORT jobject JNICALL
-Java_java_util_zip_ZipFile_00024ZFEnum_getNextEntry (JNIEnv * env,
-                                                     jobject recv,
-                                                     jlong descriptor,
-                                                     jlong nextEntry)
-{
-  PORT_ACCESS_FROM_ENV (env);
-#ifdef HY_ZIP_API
-  VMI_ACCESS_FROM_ENV(env);
-#endif /* HY_ZIP_API */
-
-  I_32 retval;
-  I_32 extraval;
-#ifdef HY_ZIP_API
-  VMIZipFile *zipFile;
-  VMIZipEntry zipEntry;
-#else
-  HyZipFile *zipFile;
-  HyZipEntry zipEntry;
-#endif
-  jobject java_ZipEntry, extra;
-  jclass javaClass;
-  jmethodID mid;
-  jstring entryName = NULL;
-  IDATA nextEntryPointer;
-  JCLZipFile *jclZipFile = (JCLZipFile *) (IDATA) descriptor;
-#ifdef HY_ZIP_API
-  VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI);
-#endif /* HY_ZIP_API */
-
-  if (jclZipFile == (void *) -1)
-    {
-      throwNewIllegalStateException (env, "");
-      return NULL;
-    }
-  zipFile = &(jclZipFile->hyZipFile);
-#ifndef HY_ZIP_API
-  zip_initZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-  zipFuncs->zip_initZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-
-  nextEntryPointer = (IDATA) nextEntry;
-  retval =
-#ifndef HY_ZIP_API
-    zip_getNextZipEntry (PORTLIB, zipFile, &zipEntry, &nextEntryPointer);
-#else /* HY_ZIP_API */
-    zipFuncs->zip_getNextZipEntry (VMI, zipFile, &zipEntry, &nextEntryPointer, ZIP_FLAG_READ_DATA_POINTER);
-#endif /* HY_ZIP_API */
-  if (retval)
-    {
-      if (retval != ZIP_ERR_NO_MORE_ENTRIES)
-        {
-          char buf[40];
-          sprintf (buf, "Error %d getting next zip entry", retval);
-          throwNewInternalError (env, buf);
-        }
-      return (jobject) NULL;
-    }
-
-  /* Build a new ZipEntry from the C struct */
-  entryName = ((*env)->NewStringUTF (env, (const char*)zipEntry.filename));
-
-  if (((*env)->ExceptionCheck (env)))
-    return NULL;
-
-  extra = NULL;
-  if (zipEntry.extraFieldLength > 0)
-    {
-      extraval =
-#ifndef HY_ZIP_API
-        zip_getZipEntryExtraField (PORTLIB, zipFile, &zipEntry, NULL,
-#else /* HY_ZIP_API */
-        zipFuncs->zip_getZipEntryExtraField (VMI, zipFile, &zipEntry, NULL,
-#endif /* HY_ZIP_API */
-                                 zipEntry.extraFieldLength);
-      if (extraval || zipEntry.extraField == NULL)
-        {
-#ifndef HY_ZIP_API
-          zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-    	  zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-          if (extraval)
-            {
-              char buf[50];
-              sprintf (buf, "Error %d getting extra field of zip entry", extraval);
-              throwNewInternalError (env, buf);
-            }
-          return (jobject) NULL;
-        }
-      extra = ((*env)->NewByteArray (env, zipEntry.extraFieldLength));
-      if (((*env)->ExceptionCheck (env)))
-        {
-          /* free the extraField entry */
-#ifndef HY_ZIP_API
-          zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-          zipFuncs->zip_freeZipEntry (VMI, &zipEntry); /* not valid zipEntry (-1) */
-#endif /* HY_ZIP_API */
-          return NULL;
-        }
-      ((*env)->
-       SetByteArrayRegion (env, extra, 0, zipEntry.extraFieldLength,
-                           (jbyte*)zipEntry.extraField));
-      jclmem_free_memory (env, zipEntry.extraField);
-      zipEntry.extraField = NULL;
-    }
-
-  javaClass = JCL_CACHE_GET (env, CLS_java_util_zip_ZipEntry);
-  mid = JCL_CACHE_GET (env, MID_java_util_zip_ZipEntry_init);
-  java_ZipEntry = ((*env)->NewObject (env, javaClass, mid, entryName, NULL,     /* comment */
-                                      extra,
-                                      (jlong) zipEntry.lastModTime,
-                                      (jlong) zipEntry.uncompressedSize,
-                                      (jlong) zipEntry.compressedSize,
-                                      (jlong) zipEntry.crc32,
-                                      zipEntry.compressionMethod,
-                                      (jlong) zipEntry.lastModDate,
-                                      (jlong) zipEntry.dataPointer));
-#ifndef HY_ZIP_API
-  zip_freeZipEntry (PORTLIB, &zipEntry);
-#else /* HY_ZIP_API */
-  zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-  (*env)->SetLongField (env, recv,
-                        JCL_CACHE_GET (env,
-                                       FID_java_util_zip_ZipFile_nextEntryPointer),
-                        nextEntryPointer);
-  return java_ZipEntry;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_java_util_zip_ZipFile_inflateEntryImpl2 (JNIEnv * env, jobject recv,
-					                          jlong descriptor,
-                                              jstring entryName)
-{
-#ifdef HY_ZIP_API
-  VMI_ACCESS_FROM_ENV(env);
-#endif /* HY_ZIP_API */
-  PORT_ACCESS_FROM_ENV (env);
-
-  I_32 retval;
-#ifdef HY_ZIP_API
-  VMIZipFile *zipFile;
-  VMIZipEntry zipEntry;
-#else
-  HyZipFile *zipFile;
-  HyZipEntry zipEntry;
-#endif
-  const char *entryCopy;
-  jbyteArray buf;
-  JCLZipFile *jclZipFile = (JCLZipFile *) (IDATA) descriptor;
-#ifdef HY_ZIP_API
-  VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI);
-#endif /* HY_ZIP_API */
-
-  /* Build the zipFile */
-  if (jclZipFile == (void *) -1)
-    {
-      throwNewIllegalStateException (env, "");
-      return NULL;
-    }
-  zipFile = &(jclZipFile->hyZipFile);
-  entryCopy = (*env)->GetStringUTFChars (env, entryName, NULL);
-  if (entryCopy == NULL)
-    return NULL;
-
-#ifndef HY_ZIP_API
-  zip_initZipEntry (privatePortLibrary, &zipEntry);
-#else /* HY_ZIP_API */
-  zipFuncs->zip_initZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-  retval =
-#ifndef HY_ZIP_API
-    zip_getZipEntry (privatePortLibrary, zipFile, &zipEntry, entryCopy, TRUE);
-#else /* HY_ZIP_API */
-    zipFuncs->zip_getZipEntry (VMI, zipFile, &zipEntry, entryCopy, ZIP_FLAG_FIND_DIRECTORY|ZIP_FLAG_READ_DATA_POINTER);
-#endif /* HY_ZIP_API */
-  (*env)->ReleaseStringUTFChars (env, entryName, entryCopy);
-  if (retval)
-    {
-#ifndef HY_ZIP_API
-      zip_freeZipEntry (privatePortLibrary, &zipEntry);
-#else /* HY_ZIP_API */
-      zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-      if (retval == ZIP_ERR_OUT_OF_MEMORY)
-        throwNewOutOfMemoryError (env, "");
-      return NULL;
-    }
-
-  buf = (*env)->NewByteArray (env, zipEntry.uncompressedSize);
-  if (!buf)
-    {
-      throwNewOutOfMemoryError (env, "");
-      return NULL;
-    }
 
-  retval =
-#ifndef HY_ZIP_API
-    zip_getZipEntryData (privatePortLibrary, zipFile, &zipEntry, NULL,
-#else /* HY_ZIP_API */
-    zipFuncs->zip_getZipEntryData (VMI, zipFile, &zipEntry, NULL,
-#endif /* HY_ZIP_API */
-                         zipEntry.uncompressedSize);
-  if (retval == 0)
-    (*env)->SetByteArrayRegion (env, buf, 0, zipEntry.uncompressedSize,
-                                (jbyte*)zipEntry.data);
-#ifndef HY_ZIP_API
-  zip_freeZipEntry (privatePortLibrary, &zipEntry);
-#else /* HY_ZIP_API */
-  zipFuncs->zip_freeZipEntry (VMI, &zipEntry);
-#endif /* HY_ZIP_API */
-  if (!retval)
-    return buf;
-
-  if (retval == ZIP_ERR_OUT_OF_MEMORY)
-    throwNewOutOfMemoryError (env, "");
-  else
-    throwJavaZIOException (env, "");
-
-  return NULL;
-}

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/unix/exports.txt
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/unix/exports.txt?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/unix/exports.txt (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/native/archive/unix/exports.txt Wed Oct  7 18:54:08 2009
@@ -24,12 +24,5 @@
 Java_java_util_zip_Inflater_resetImpl
 Java_java_util_zip_Inflater_setDictionaryImpl
 Java_java_util_zip_Inflater_setInputImpl
-Java_java_util_zip_ZipFile_00024ZFEnum_getNextEntry
-Java_java_util_zip_ZipFile_00024ZFEnum_resetZip
-Java_java_util_zip_ZipFile_closeZipImpl
-Java_java_util_zip_ZipFile_getEntryImpl
-Java_java_util_zip_ZipFile_inflateEntryImpl2
-Java_java_util_zip_ZipFile_ntvinit
-Java_java_util_zip_ZipFile_openZipImpl
 JNI_OnLoad
 JNI_OnUnload

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java Wed Oct  7 18:54:08 2009
@@ -65,6 +65,18 @@
 
     private File resources;
 
+    private final String jarName = "hyts_patch.jar"; // a 'normal' jar file
+
+    private final String entryName = "foo/bar/A.class";
+
+    private final String emptyEntryJar = "EmptyEntries_signed.jar";
+
+    private final String emptyEntry1 = "subfolder/internalSubset01.js";
+
+    private final String emptyEntry2 = "svgtest.js";
+
+    private final String emptyEntry3 = "svgunit.js";
+
     @Override
     protected void setUp() {
         resources = Support_Resources.createTempFolder();
@@ -122,6 +134,72 @@
         }
     }
 
+    public void test_getEntryLjava_lang_String() throws IOException {
+        try {
+            Support_Resources.copyFile(resources, null, jarName);
+            JarFile jarFile = new JarFile(new File(resources, jarName));
+            assertEquals("Error in returned entry", 311, jarFile.getEntry(
+                    entryName).getSize());
+            jarFile.close();
+        } catch (Exception e) {
+            fail("Exception during test: " + e.toString());
+        }
+
+        Support_Resources.copyFile(resources, null, jarName);
+        JarFile jarFile = new JarFile(new File(resources, jarName));
+        Enumeration<JarEntry> enumeration = jarFile.entries();
+        assertTrue(enumeration.hasMoreElements());
+        while (enumeration.hasMoreElements()) {
+            JarEntry je = enumeration.nextElement();
+            jarFile.getEntry(je.getName());
+        }
+
+        enumeration = jarFile.entries();
+        assertTrue(enumeration.hasMoreElements());
+        JarEntry je = enumeration.nextElement();
+        try {
+            jarFile.close();
+            jarFile.getEntry(je.getName());
+            // fail("IllegalStateException expected.");
+        } catch (IllegalStateException ee) { // Per documentation exception
+            // may be thrown.
+            // expected
+        }
+    }
+
+    public void test_getJarEntryLjava_lang_String() throws IOException {
+        try {
+            Support_Resources.copyFile(resources, null, jarName);
+            JarFile jarFile = new JarFile(new File(resources, jarName));
+            assertEquals("Error in returned entry", 311, jarFile.getJarEntry(
+                    entryName).getSize());
+            jarFile.close();
+        } catch (Exception e) {
+            fail("Exception during test: " + e.toString());
+        }
+
+        Support_Resources.copyFile(resources, null, jarName);
+        JarFile jarFile = new JarFile(new File(resources, jarName));
+        Enumeration<JarEntry> enumeration = jarFile.entries();
+        assertTrue(enumeration.hasMoreElements());
+        while (enumeration.hasMoreElements()) {
+            JarEntry je = enumeration.nextElement();
+            jarFile.getJarEntry(je.getName());
+        }
+
+        enumeration = jarFile.entries();
+        assertTrue(enumeration.hasMoreElements());
+        JarEntry je = enumeration.nextElement();
+        try {
+            jarFile.close();
+            jarFile.getJarEntry(je.getName());
+            // fail("IllegalStateException expected.");
+        } catch (IllegalStateException ee) { // Per documentation exception
+            // may be thrown.
+            // expected
+        }
+    }
+
     /**
      * @tests java.util.jar.JarFile#getJarEntry(java.lang.String)
      */
@@ -310,7 +388,7 @@
         jar = new JarFile(signedFile);
         entry = jar.getJarEntry(JAR4_SIGNED_ENTRY);
         in = jar.getInputStream(entry);
-        in.read(new byte[(int) entry.getSize() - 1]);
+        readExactly(in, (int) entry.getSize() - 1);
         assertNull(entry.getCertificates());
         in.read();
         assertNotNull(entry.getCertificates());
@@ -320,7 +398,7 @@
         entry = jar.getJarEntry(JAR4_SIGNED_ENTRY);
         entry.setSize(entry.getSize() - 1);
         in = jar.getInputStream(entry);
-        in.read(new byte[(int) entry.getSize() - 1]);
+        readExactly(in, (int) entry.getSize() - 1);
         assertNull(entry.getCertificates());
         try {
             in.read();
@@ -331,6 +409,19 @@
         assertEquals(-1, in.read());
     }
 
+    /**
+     * Performs as many read() calls as necessary to read {@code numBytes} from
+     * the stream. Should the stream exhaust early, this method will fail.
+     */
+    private void readExactly(InputStream in, int numBytes) throws IOException {
+        byte[] buffer = new byte[1024];
+        while (numBytes > 0) {
+            int read = in.read(buffer, 0, Math.min(numBytes, 1024));
+            assertTrue(read != -1);
+            numBytes -= read;
+        }
+    }
+
     /*
      * The jar created by 1.4 which does not provide a
      * algorithm-Digest-Manifest-Main-Attributes entry in .SF file.
@@ -551,4 +642,23 @@
         assertNull(is);
         jf.close(); 
     }
+
+    public void testJarVerificationEmptyEntry() throws IOException {
+        Support_Resources.copyFile(resources, null, emptyEntryJar);
+        File f = new File(resources, emptyEntryJar);
+
+        JarFile jarFile = new JarFile(f);
+
+        ZipEntry zipEntry = jarFile.getJarEntry(emptyEntry1);
+        int res = jarFile.getInputStream(zipEntry).read(new byte[100], 0, 100);
+        assertEquals("Wrong length of empty jar entry", -1, res);
+
+        zipEntry = jarFile.getJarEntry(emptyEntry2);
+        res = jarFile.getInputStream(zipEntry).read(new byte[100], 0, 100);
+        assertEquals("Wrong length of empty jar entry", -1, res);
+
+        zipEntry = jarFile.getJarEntry(emptyEntry3);
+        res = jarFile.getInputStream(zipEntry).read();
+        assertEquals("Wrong length of empty jar entry", -1, res);
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java Wed Oct  7 18:54:08 2009
@@ -390,4 +390,25 @@
         jin.close();
     }    
 
+    public void test_getNextEntry() throws Exception {
+        File resources = Support_Resources.createTempFolder();
+        Support_Resources.copyFile(resources, null, "Broken_entry.jar");
+        InputStream is = Support_Resources.getStream("Broken_entry.jar");
+        JarInputStream jis = new JarInputStream(is, false);
+        jis.getNextEntry();
+        try {
+            jis.getNextEntry();
+            fail("ZipException expected");
+        } catch (ZipException ee) {
+            // expected
+        }
+
+        try {
+            jis.close();  // Android throws exception here, already!
+            jis.getNextEntry();  // But RI here, only!
+            fail("IOException expected");
+        } catch (IOException ee) {
+            // expected
+        }
+    }
 }

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java Wed Oct  7 18:54:08 2009
@@ -19,11 +19,13 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.InputStream;
+import java.io.IOException;
 import java.net.URL;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
 
 import tests.support.Support_Exec;
 import tests.support.resource.Support_Resources;
@@ -98,6 +100,53 @@
 		}
 	}
 
+    public void test_JarOutputStreamLjava_io_OutputStreamLjava_util_jar_Manifest()
+            throws IOException {
+        File fooJar = File.createTempFile("hyts_", ".jar");
+        File barZip = File.createTempFile("hyts_", ".zip");
+
+        FileOutputStream fos = new FileOutputStream(fooJar);
+
+        Manifest man = new Manifest();
+        Attributes att = man.getMainAttributes();
+        att.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+        att.put(Attributes.Name.MAIN_CLASS, "foo.bar.execjartest.Foo");
+        att.put(Attributes.Name.CLASS_PATH, barZip.getName());
+
+        fos.close();
+        try {
+            new JarOutputStream(fos, man);
+            fail("IOException expected");
+        } catch (IOException ee) {
+            // expected
+        }
+    }
+
+    public void test_JarOutputStreamLjava_io_OutputStream() throws IOException {
+        File fooJar = File.createTempFile("hyts_", ".jar");
+
+        FileOutputStream fos = new FileOutputStream(fooJar);
+        ZipEntry ze = new ZipEntry("Test");
+
+        try {
+            JarOutputStream joutFoo = new JarOutputStream(fos);
+            joutFoo.putNextEntry(ze);
+            joutFoo.write(33);
+        } catch (IOException ee) {
+            fail("IOException is not expected");
+        }
+
+        fos.close();
+        fooJar.delete();
+        try {
+            JarOutputStream joutFoo = new JarOutputStream(fos);
+            joutFoo.putNextEntry(ze);
+            fail("IOException expected");
+        } catch (IOException ee) {
+            // expected
+        }
+    }
+
 	@Override
     protected void setUp() {
 	}

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/CheckedInputStreamTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/CheckedInputStreamTest.java?rev=822846&r1=822845&r2=822846&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/CheckedInputStreamTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/CheckedInputStreamTest.java Wed Oct  7 18:54:08 2009
@@ -20,6 +20,7 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.InputStream;
+import java.io.IOException;
 import java.util.zip.CRC32;
 import java.util.zip.CheckedInputStream;
 
@@ -105,4 +106,39 @@
                 .getValue());
         checkInput.close();
     }
+
+    public void test_read() throws Exception {
+        // testing that the return by skip is valid
+        InputStream checkInput = Support_Resources
+                .getStream("hyts_checkInput.txt");
+        CheckedInputStream checkIn = new CheckedInputStream(checkInput,
+                new CRC32());
+        checkIn.read();
+        checkIn.close();
+        try {
+            checkIn.read();
+            fail("IOException expected.");
+        } catch (IOException ee) {
+            // expected
+        }
+        checkInput.close();
+    }
+
+    public void test_read$byteII() throws Exception {
+        // testing that the return by skip is valid
+        InputStream checkInput = Support_Resources
+                .getStream("hyts_checkInput.txt");
+        CheckedInputStream checkIn = new CheckedInputStream(checkInput,
+                new CRC32());
+        byte buff[] = new byte[50];
+        checkIn.read(buff, 10, 5);
+        checkIn.close();
+        try {
+            checkIn.read(buff, 10, 5);
+            fail("IOException expected.");
+        } catch (IOException ee) {
+            // expected
+        }
+        checkInput.close();
+    }
 }