< prev index next >
src/java.base/share/classes/java/util/zip/ZipFile.java
Print this page
*** 23,32 ****
--- 23,33 ----
* questions.
*/
package java.util.zip;
+ import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
import java.io.File;
*** 65,74 ****
--- 66,78 ----
private volatile boolean closeRequested = false;
private static final int STORED = ZipEntry.STORED;
private static final int DEFLATED = ZipEntry.DEFLATED;
+ // Max buffer size when returning bytebuffers directly
+ private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
+
/**
* Mode flag to open a zip file for reading.
*/
public static final int OPEN_READ = 0x1;
*** 343,375 ****
*/
public InputStream getInputStream(ZipEntry entry) throws IOException {
if (entry == null) {
throw new NullPointerException("entry");
}
! long jzentry = 0;
! ZipFileInputStream in = null;
synchronized (this) {
ensureOpen();
if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
} else {
jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
}
if (jzentry == 0) {
return null;
}
! in = new ZipFileInputStream(jzentry);
! switch (getEntryMethod(jzentry)) {
case STORED:
synchronized (streams) {
streams.put(in, null);
}
return in;
case DEFLATED:
// MORE: Compute good size for inflater stream:
! long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack
if (size > 65536) size = 8192;
if (size <= 0) size = 4096;
Inflater inf = getInflater();
InputStream is =
new ZipFileInflaterInputStream(in, inf, (int)size);
--- 347,397 ----
*/
public InputStream getInputStream(ZipEntry entry) throws IOException {
if (entry == null) {
throw new NullPointerException("entry");
}
!
! long jzentry, csize, size;
! int cmethod;
synchronized (this) {
ensureOpen();
if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
} else {
jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
}
if (jzentry == 0) {
return null;
}
! size = getEntrySize(jzentry);
! csize = getEntryCSize(jzentry);
! cmethod = getEntryMethod(jzentry);
! }
! if (csize >= 0 && size > 0 && size < 128 * 1024) {
! try {
! return new ByteArrayInputStream(getBytes(jzentry, csize, size, cmethod));
! } finally {
! synchronized (this) {
! if (jzfile != 0) {
! freeEntry(jzfile, jzentry);
! }
! }
! }
! }
!
! ZipFileInputStream in = new ZipFileInputStream(jzentry, csize, size);
!
! switch (cmethod) {
case STORED:
synchronized (streams) {
streams.put(in, null);
}
return in;
case DEFLATED:
// MORE: Compute good size for inflater stream:
! size += 2; // Inflater likes a bit of slack
if (size > 65536) size = 8192;
if (size <= 0) size = 4096;
Inflater inf = getInflater();
InputStream is =
new ZipFileInflaterInputStream(in, inf, (int)size);
*** 379,389 ****
return is;
default:
throw new ZipException("invalid compression method");
}
}
- }
private class ZipFileInflaterInputStream extends InflaterInputStream {
private volatile boolean closeRequested = false;
private boolean eof = false;
private final ZipFileInputStream zfin;
--- 401,410 ----
*** 467,476 ****
--- 488,594 ----
}
// List of available Inflater objects for decompression
private Deque<Inflater> inflaterCache = new ArrayDeque<>();
+ /*
+ * Uncompress the zip entry into a new byte[].
+ *
+ * This method can only read entries smaller than 2GB, for larger entries
+ * use getInputStream.
+ *
+ * @param entry the zip file entry
+ *
+ * @return the byte[] with the deflated contents of the specified zip file entry.
+ *
+ * @throws ZipException if a ZIP format error has occurred
+ * @throws IOException if an I/O error has occurred
+ * @throws IllegalStateException if the zip file has been closed
+ * @throws OutOfMemory if the zip entry is larger than 2GB
+ */
+ private byte[] getBytes(ZipEntry entry) throws IOException {
+ if (entry == null) {
+ throw new NullPointerException("entry");
+ }
+
+ long jzentry, csize, size;
+ int cmethod;
+ synchronized (this) {
+ ensureOpen();
+ if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
+ jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
+ } else {
+ jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
+ }
+ if (jzentry == 0) {
+ return null;
+ }
+
+ csize = getEntryCSize(jzentry);
+ size = getEntrySize(jzentry);
+ cmethod = getEntryMethod(jzentry);
+ }
+
+ try {
+ return getBytes(jzentry, csize, size, cmethod);
+ } finally {
+ synchronized (this) {
+ if (jzfile != 0) {
+ freeEntry(jzfile, jzentry);
+ }
+ }
+ }
+ }
+
+ private byte[] getBytes(long jzentry, long csize, long size, int cmethod)
+ throws IOException {
+
+ if (csize < 0 || size < 0) {
+ throw new ZipException("Unknown size of ZipEntry");
+ }
+ if (csize > MAX_BUFFER_SIZE || size > MAX_BUFFER_SIZE) {
+ throw new OutOfMemoryError("ZipEntry too large");
+ }
+
+ byte[] cbytes = new byte[(int) csize];
+ readCompressedBytes(jzentry, (int) csize, cbytes);
+ switch (cmethod) {
+ case STORED:
+ return cbytes;
+ case DEFLATED:
+ byte[] bytes = new byte[(int) size];
+ Inflater inf = getInflater();
+ try {
+ inf.setInput(cbytes);
+ inf.inflate(bytes);
+ } catch (DataFormatException e) {
+ String s = e.getMessage();
+ throw new ZipException(s != null ? s : "Invalid ZLIB data format");
+ } finally {
+ releaseInflater(inf);
+ }
+ return bytes;
+ default:
+ throw new ZipException("invalid compression method");
+ }
+ }
+
+ private int readCompressedBytes(long jzentry, int csize, byte[] buf)
+ throws IOException {
+ assert csize == buf.length;
+ synchronized (this) {
+ ensureOpenOrZipException();
+ int n = 0;
+ int nread = 0;
+ while (nread < csize
+ && (n = read(jzfile, jzentry, nread, buf, nread, csize - nread)) > 0) {
+ nread += n;
+ }
+ return nread;
+ }
+ }
+
/**
* Returns the path name of the ZIP file.
* @return the path name of the ZIP file
*/
public String getName() {
*** 689,702 ****
protected long jzentry; // address of jzentry data
private long pos; // current position within entry data
protected long rem; // number of remaining bytes within entry
protected long size; // uncompressed size of this entry
! ZipFileInputStream(long jzentry) {
pos = 0;
! rem = getEntryCSize(jzentry);
! size = getEntrySize(jzentry);
this.jzentry = jzentry;
}
public int read(byte b[], int off, int len) throws IOException {
synchronized (ZipFile.this) {
--- 807,820 ----
protected long jzentry; // address of jzentry data
private long pos; // current position within entry data
protected long rem; // number of remaining bytes within entry
protected long size; // uncompressed size of this entry
! ZipFileInputStream(long jzentry, long csize, long size) {
pos = 0;
! rem = csize;
! this.size = size;
this.jzentry = jzentry;
}
public int read(byte b[], int off, int len) throws IOException {
synchronized (ZipFile.this) {
*** 777,789 ****
--- 895,914 ----
}
static {
sun.misc.SharedSecrets.setJavaUtilZipFileAccess(
new sun.misc.JavaUtilZipFileAccess() {
+ @Override
public boolean startsWithLocHeader(ZipFile zip) {
return zip.startsWithLocHeader();
}
+
+ @Override
+ public byte[] getBytes(ZipFile zip, ZipEntry entry)
+ throws IOException {
+ return zip.getBytes(entry);
+ }
}
);
}
/**
< prev index next >