src/java.base/share/classes/java/util/zip/ZipFile.java

Print this page

        

*** 48,62 **** import java.util.Objects; import java.util.NoSuchElementException; import java.util.Spliterator; import java.util.Spliterators; import java.util.WeakHashMap; import java.util.stream.Stream; import java.util.stream.StreamSupport; import jdk.internal.misc.JavaUtilZipFileAccess; import jdk.internal.misc.SharedSecrets; - import jdk.internal.misc.JavaIORandomAccessFileAccess; import jdk.internal.misc.VM; import jdk.internal.perf.PerfCounter; import static java.util.zip.ZipConstants.*; import static java.util.zip.ZipConstants64.*; --- 48,66 ---- import java.util.Objects; import java.util.NoSuchElementException; import java.util.Spliterator; import java.util.Spliterators; import java.util.WeakHashMap; + + import java.util.function.Consumer; + import java.util.function.Function; + import java.util.function.IntFunction; + import java.util.jar.JarEntry; import java.util.stream.Stream; import java.util.stream.StreamSupport; import jdk.internal.misc.JavaUtilZipFileAccess; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.VM; import jdk.internal.perf.PerfCounter; import static java.util.zip.ZipConstants.*; import static java.util.zip.ZipConstants64.*;
*** 294,310 **** * @param name the name of the entry * @return the zip file entry, or null if not found * @throws IllegalStateException if the zip file has been closed */ public ZipEntry getEntry(String name) { Objects.requireNonNull(name, "name"); synchronized (this) { ensureOpen(); byte[] bname = zc.getBytes(name); int pos = zsrc.getEntryPos(bname, true); if (pos != -1) { ! return getZipEntry(name, bname, pos); } } return null; } --- 298,328 ---- * @param name the name of the entry * @return the zip file entry, or null if not found * @throws IllegalStateException if the zip file has been closed */ public ZipEntry getEntry(String name) { + return getEntry(name, ZipEntry::new); + } + + /* + * Returns the zip file entry for the specified name, or null + * if not found. + * + * @param name the name of the entry + * @param func the function that creates the returned entry + * + * @return the zip file entry, or null if not found + * @throws IllegalStateException if the zip file has been closed + */ + private ZipEntry getEntry(String name, Function<String, ? extends ZipEntry> func) { Objects.requireNonNull(name, "name"); synchronized (this) { ensureOpen(); byte[] bname = zc.getBytes(name); int pos = zsrc.getEntryPos(bname, true); if (pos != -1) { ! return getZipEntry(name, bname, pos, func); } } return null; }
*** 372,387 **** } private class ZipFileInflaterInputStream extends InflaterInputStream { private volatile boolean closeRequested; private boolean eof = false; - private final ZipFileInputStream zfin; ZipFileInflaterInputStream(ZipFileInputStream zfin, Inflater inf, int size) { super(zfin, inf, size); - this.zfin = zfin; } public void close() throws IOException { if (closeRequested) return; --- 390,403 ----
*** 414,424 **** } public int available() throws IOException { if (closeRequested) return 0; ! long avail = zfin.size() - inf.getBytesWritten(); return (avail > (long) Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) avail); } @SuppressWarnings("deprecation") --- 430,440 ---- } public int available() throws IOException { if (closeRequested) return 0; ! long avail = ((ZipFileInputStream)in).size() - inf.getBytesWritten(); return (avail > (long) Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) avail); } @SuppressWarnings("deprecation")
*** 464,542 **** */ public String getName() { return name; } ! private class ZipEntryIterator implements Enumeration<ZipEntry>, Iterator<ZipEntry> { private int i = 0; private final int entryCount; ! public ZipEntryIterator() { ! synchronized (ZipFile.this) { ! ensureOpen(); ! this.entryCount = zsrc.total; ! } } public boolean hasMoreElements() { return hasNext(); } public boolean hasNext() { return i < entryCount; } ! public ZipEntry nextElement() { return next(); } ! public ZipEntry next() { synchronized (ZipFile.this) { ensureOpen(); if (!hasNext()) { throw new NoSuchElementException(); } // each "entry" has 3 ints in table entries ! return getZipEntry(null, null, zsrc.getEntryPos(i++ * 3)); } } ! public Iterator<ZipEntry> asIterator() { return this; } } /** * Returns an enumeration of the ZIP file entries. * @return an enumeration of the ZIP file entries * @throws IllegalStateException if the zip file has been closed */ public Enumeration<? extends ZipEntry> entries() { ! return new ZipEntryIterator(); } /** * Returns an ordered {@code Stream} over the ZIP file entries. * Entries appear in the {@code Stream} in the order they appear in * the central directory of the ZIP file. * * @return an ordered {@code Stream} of entries in this ZIP file * @throws IllegalStateException if the zip file has been closed * @since 1.8 */ public Stream<? extends ZipEntry> stream() { ! return StreamSupport.stream(Spliterators.spliterator( ! new ZipEntryIterator(), size(), ! Spliterator.ORDERED | Spliterator.DISTINCT | ! Spliterator.IMMUTABLE | Spliterator.NONNULL), false); } private String lastEntryName; private int lastEntryPos; /* Checks ensureOpen() before invoke this method */ ! private ZipEntry getZipEntry(String name, byte[] bname, int pos) { byte[] cen = zsrc.cen; int nlen = CENNAM(cen, pos); int elen = CENEXT(cen, pos); int clen = CENCOM(cen, pos); int flag = CENFLG(cen, pos); --- 480,656 ---- */ public String getName() { return name; } ! private class ZipEntryIterator<T extends ZipEntry> ! implements Enumeration<T>, Iterator<T> { ! private int i = 0; private final int entryCount; + private final Function<String, T> gen; ! public ZipEntryIterator(int entryCount, Function<String, T> gen) { ! this.entryCount = entryCount; ! this.gen = gen; } + @Override public boolean hasMoreElements() { return hasNext(); } + @Override public boolean hasNext() { return i < entryCount; } ! @Override ! public T nextElement() { return next(); } ! @Override ! @SuppressWarnings("unchecked") ! public T next() { synchronized (ZipFile.this) { ensureOpen(); if (!hasNext()) { throw new NoSuchElementException(); } // each "entry" has 3 ints in table entries ! return (T)getZipEntry(null, null, zsrc.getEntryPos(i++ * 3), gen); } } ! @Override ! public Iterator<T> asIterator() { return this; } } /** * Returns an enumeration of the ZIP file entries. * @return an enumeration of the ZIP file entries * @throws IllegalStateException if the zip file has been closed */ public Enumeration<? extends ZipEntry> entries() { ! synchronized (this) { ! ensureOpen(); ! return new ZipEntryIterator<ZipEntry>(zsrc.total, ZipEntry::new); ! } ! } ! ! private Enumeration<JarEntry> entries(Function<String, JarEntry> func) { ! synchronized (this) { ! ensureOpen(); ! return new ZipEntryIterator<JarEntry>(zsrc.total, func); ! } ! } ! ! private class EntrySpliterator<T> extends Spliterators.AbstractSpliterator<T> { ! private int index; ! private final int fence; ! private final IntFunction<T> gen; ! ! EntrySpliterator(int index, int fence, IntFunction<T> gen) { ! super((long)fence, ! Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.IMMUTABLE | ! Spliterator.NONNULL); ! this.index = index; ! this.fence = fence; ! this.gen = gen; ! } ! ! @Override ! public boolean tryAdvance(Consumer<? super T> action) { ! if (action == null) ! throw new NullPointerException(); ! if (index >= 0 && index < fence) { ! synchronized (ZipFile.this) { ! ensureOpen(); ! action.accept(gen.apply(zsrc.getEntryPos(index++ * 3))); ! } ! return true; ! } ! return false; ! } } /** * Returns an ordered {@code Stream} over the ZIP file entries. + * * Entries appear in the {@code Stream} in the order they appear in * the central directory of the ZIP file. * * @return an ordered {@code Stream} of entries in this ZIP file * @throws IllegalStateException if the zip file has been closed * @since 1.8 */ public Stream<? extends ZipEntry> stream() { ! synchronized (this) { ! ensureOpen(); ! return StreamSupport.stream(new EntrySpliterator<>(0, zsrc.total, ! pos -> getZipEntry(null, null, pos, ZipEntry::new)), false); ! } ! } ! ! private String getEntryName(int pos) { ! byte[] cen = zsrc.cen; ! int nlen = CENNAM(cen, pos); ! int clen = CENCOM(cen, pos); ! int flag = CENFLG(cen, pos); ! if (!zc.isUTF8() && (flag & EFS) != 0) { ! return zc.toStringUTF8(cen, pos + CENHDR, nlen); ! } else { ! return zc.toString(cen, pos + CENHDR, nlen); ! } ! } ! ! /* ! * Returns an ordered {@code Stream} over the zip file entry names. ! * ! * Entry names appear in the {@code Stream} in the order they appear in ! * the central directory of the ZIP file. ! * ! * @return an ordered {@code Stream} of entry names in this zip file ! * @throws IllegalStateException if the zip file has been closed ! * @since 10 ! */ ! private Stream<String> entryNameStream() { ! synchronized (this) { ! ensureOpen(); ! return StreamSupport.stream( ! new EntrySpliterator<>(0, zsrc.total, this::getEntryName), false); ! } ! } ! ! /* ! * Returns an ordered {@code Stream} over the zip file entries. ! * ! * Entries appear in the {@code Stream} in the order they appear in ! * the central directory of the jar file. ! * ! * @param func the function that creates the returned entry ! * @return an ordered {@code Stream} of entries in this zip file ! * @throws IllegalStateException if the zip file has been closed ! * @since 10 ! */ ! private Stream<JarEntry> stream(Function<String, JarEntry> func) { ! synchronized (this) { ! ensureOpen(); ! return StreamSupport.stream(new EntrySpliterator<>(0, zsrc.total, ! pos -> (JarEntry)getZipEntry(null, null, pos, func)), false); ! } } private String lastEntryName; private int lastEntryPos; /* Checks ensureOpen() before invoke this method */ ! private ZipEntry getZipEntry(String name, byte[] bname, int pos, ! Function<String, ? extends ZipEntry> func) { byte[] cen = zsrc.cen; int nlen = CENNAM(cen, pos); int elen = CENEXT(cen, pos); int clen = CENCOM(cen, pos); int flag = CENFLG(cen, pos);
*** 549,559 **** name = zc.toStringUTF8(cen, pos + CENHDR, nlen); } else { name = zc.toString(cen, pos + CENHDR, nlen); } } ! ZipEntry e = new ZipEntry(name); e.flag = flag; e.xdostime = CENTIM(cen, pos); e.crc = CENCRC(cen, pos); e.size = CENLEN(cen, pos); e.csize = CENSIZ(cen, pos); --- 663,673 ---- name = zc.toStringUTF8(cen, pos + CENHDR, nlen); } else { name = zc.toString(cen, pos + CENHDR, nlen); } } ! ZipEntry e = func.apply(name); //ZipEntry e = new ZipEntry(name); e.flag = flag; e.xdostime = CENTIM(cen, pos); e.crc = CENCRC(cen, pos); e.size = CENLEN(cen, pos); e.csize = CENSIZ(cen, pos);
*** 789,799 **** } } public long skip(long n) throws IOException { synchronized (ZipFile.this) { - ensureOpenOrZipException(); initDataOffset(); if (n > rem) { n = rem; } pos += n; --- 903,912 ----
*** 855,870 **** --- 968,1004 ---- private static boolean isWindows; static { SharedSecrets.setJavaUtilZipFileAccess( new JavaUtilZipFileAccess() { + @Override public boolean startsWithLocHeader(ZipFile zip) { return zip.zsrc.startsWithLoc; } + @Override public String[] getMetaInfEntryNames(ZipFile zip) { return zip.getMetaInfEntryNames(); } + @Override + public JarEntry getEntry(ZipFile zip, String name, + Function<String, JarEntry> func) { + return (JarEntry)zip.getEntry(name, func); + } + @Override + public Enumeration<JarEntry> entries(ZipFile zip, + Function<String, JarEntry> func) { + return zip.entries(func); + } + @Override + public Stream<JarEntry> stream(ZipFile zip, + Function<String, JarEntry> func) { + return zip.stream(func); + } + @Override + public Stream<String> entryNameStream(ZipFile zip) { + return zip.entryNameStream(); + } } ); isWindows = VM.getSavedProperty("os.name").contains("Windows"); }