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();
+ }
}