< 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 >