On Tue, May 28, 2013 at 2:08 PM, sebb <seb...@gmail.com> wrote: > On 25 May 2013 18:47, <bode...@apache.org> wrote: > > Author: bodewig > > Date: Sat May 25 17:47:00 2013 > > New Revision: 1486348 > > > > URL: http://svn.apache.org/r1486348 > > Log: > > provide access to all entries of a given name in ZipFile, COMPRESS-227 > > -1, see below > > > Modified: > > > commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java > > > commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java > > > > Modified: > commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java > > URL: > http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java?rev=1486348&r1=1486347&r2=1486348&view=diff > > > ============================================================================== > > --- > commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java > (original) > > +++ > commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java > Sat May 25 17:47:00 2013 > > @@ -25,9 +25,12 @@ import java.io.RandomAccessFile; > > import java.util.Arrays; > > import java.util.Collections; > > import java.util.Comparator; > > +import java.util.Deque; > > That requires Java 1.6; Compress currently targets 1.5 >
Well, let's change the requirement to Java 6 for Compress 1.6. Gary > > > import java.util.Enumeration; > > import java.util.HashMap; > > -import java.util.LinkedHashMap; > > +import java.util.Iterator; > > +import java.util.LinkedList; > > +import java.util.List; > > import java.util.Map; > > import java.util.zip.Inflater; > > import java.util.zip.InflaterInputStream; > > @@ -83,17 +86,17 @@ public class ZipFile { > > private static final int POS_3 = 3; > > > > /** > > - * Maps ZipArchiveEntrys to two longs, recording the offsets of > > - * the local file headers and the start of entry data. > > + * List of entries in the order they appear inside the central > > + * directory. > > */ > > - private final Map<ZipArchiveEntry, OffsetEntry> entries = > > - new LinkedHashMap<ZipArchiveEntry, OffsetEntry>(HASH_SIZE); > > + private final List<ZipArchiveEntry> entries = > > + new LinkedList<ZipArchiveEntry>(); > > > > /** > > - * Maps String to ZipArchiveEntrys, name -> actual entry. > > + * Maps String to list of ZipArchiveEntrys, name -> actual entries. > > */ > > - private final Map<String, ZipArchiveEntry> nameMap = > > - new HashMap<String, ZipArchiveEntry>(HASH_SIZE); > > + private final Map<String, Deque<ZipArchiveEntry>> nameMap = > > + new HashMap<String, Deque<ZipArchiveEntry>>(HASH_SIZE); > > > > private static final class OffsetEntry { > > private long headerOffset = -1; > > @@ -273,7 +276,7 @@ public class ZipFile { > > * @return all entries as {@link ZipArchiveEntry} instances > > */ > > public Enumeration<ZipArchiveEntry> getEntries() { > > - return Collections.enumeration(entries.keySet()); > > + return Collections.enumeration(entries); > > } > > > > /** > > @@ -287,8 +290,7 @@ public class ZipFile { > > * @since 1.1 > > */ > > public Enumeration<ZipArchiveEntry> getEntriesInPhysicalOrder() { > > - ZipArchiveEntry[] allEntries = > > - entries.keySet().toArray(new ZipArchiveEntry[0]); > > + ZipArchiveEntry[] allEntries = entries.toArray(new > ZipArchiveEntry[0]); > > Arrays.sort(allEntries, OFFSET_COMPARATOR); > > return Collections.enumeration(Arrays.asList(allEntries)); > > } > > @@ -296,12 +298,51 @@ public class ZipFile { > > /** > > * Returns a named entry - or {@code null} if no entry by > > * that name exists. > > + * > > + * <p>If multiple entries with the same name exist the first entry > > + * in the archive's central directory by that name is > > + * returned.</p> > > + * > > * @param name name of the entry. > > * @return the ZipArchiveEntry corresponding to the given name - or > > * {@code null} if not present. > > */ > > public ZipArchiveEntry getEntry(String name) { > > - return nameMap.get(name); > > + Deque<ZipArchiveEntry> entriesOfThatName = nameMap.get(name); > > + return entriesOfThatName != null ? entriesOfThatName.getFirst() > : null; > > + } > > + > > + /** > > + * Returns all named entries in the same order they appear within > > + * the archive's central directory. > > + * > > + * @param name name of the entry. > > + * @return the Iterator<ZipArchiveEntry> corresponding to the > > + * given name > > + * @since 1.6 > > + */ > > + public Iterator<ZipArchiveEntry> getEntries(String name) { > > + Deque<ZipArchiveEntry> entriesOfThatName = nameMap.get(name); > > + return entriesOfThatName != null ? entriesOfThatName.iterator() > > + : Collections.<ZipArchiveEntry>emptyList().iterator(); > > + } > > + > > + /** > > + * Returns all named entries in the same order their contents > > + * appear within the archive. > > + * > > + * @param name name of the entry. > > + * @return the Iterator<ZipArchiveEntry> corresponding to the > > + * given name > > + * @since 1.6 > > + */ > > + public Iterator<ZipArchiveEntry> getEntriesInPhysicalOrder(String > name) { > > + ZipArchiveEntry[] entriesOfThatName = new ZipArchiveEntry[0]; > > + if (nameMap.containsKey(name)) { > > + entriesOfThatName = > nameMap.get(name).toArray(entriesOfThatName); > > + Arrays.sort(entriesOfThatName, OFFSET_COMPARATOR); > > + } > > + return Arrays.asList(entriesOfThatName).iterator(); > > } > > > > /** > > @@ -325,10 +366,12 @@ public class ZipFile { > > */ > > public InputStream getInputStream(ZipArchiveEntry ze) > > throws IOException, ZipException { > > - OffsetEntry offsetEntry = entries.get(ze); > > - if (offsetEntry == null) { > > + if (!(ze instanceof Entry)) { > > return null; > > } > > + // checked just above > > + @SuppressWarnings("unchecked") OffsetEntry offsetEntry = > > + ((Entry) ze).getOffsetEntry(); > > ZipUtil.checkRequestedFeatures(ze); > > long start = offsetEntry.dataOffset; > > BoundedInputStream bis = > > @@ -474,7 +517,8 @@ public class ZipFile { > > throws IOException { > > archive.readFully(CFH_BUF); > > int off = 0; > > - ZipArchiveEntry ze = new ZipArchiveEntry(); > > + OffsetEntry offset = new OffsetEntry(); > > + Entry ze = new Entry(offset); > > > > int versionMadeBy = ZipShort.getValue(CFH_BUF, off); > > off += SHORT; > > @@ -529,10 +573,9 @@ public class ZipFile { > > ze.setName(entryEncoding.decode(fileName), fileName); > > > > // LFH offset, > > - OffsetEntry offset = new OffsetEntry(); > > offset.headerOffset = ZipLong.getValue(CFH_BUF, off); > > // data offset will be filled later > > - entries.put(ze, offset); > > + entries.add(ze); > > > > byte[] cdExtraData = new byte[extraLen]; > > archive.readFully(cdExtraData); > > @@ -851,16 +894,11 @@ public class ZipFile { > > private void resolveLocalFileHeaderData(Map<ZipArchiveEntry, > NameAndComment> > > entriesWithoutUTF8Flag) > > throws IOException { > > - // changing the name of a ZipArchiveEntry is going to change > > - // the hashcode - see COMPRESS-164 > > - // Map needs to be reconstructed in order to keep central > > - // directory order > > - Map<ZipArchiveEntry, OffsetEntry> origMap = > > - new LinkedHashMap<ZipArchiveEntry, OffsetEntry>(entries); > > - entries.clear(); > > - for (Map.Entry<ZipArchiveEntry, OffsetEntry> ent : > origMap.entrySet()) { > > - ZipArchiveEntry ze = ent.getKey(); > > - OffsetEntry offsetEntry = ent.getValue(); > > + for (Iterator<ZipArchiveEntry> it = entries.iterator(); > it.hasNext(); ) { > > + // entries is filled in populateFromCentralDirectory and > > + // never modified > > + @SuppressWarnings("unchecked") Entry ze = (Entry) it.next(); > > + OffsetEntry offsetEntry = ze.getOffsetEntry(); > > long offset = offsetEntry.headerOffset; > > archive.seek(offset + LFH_OFFSET_FOR_FILENAME_LENGTH); > > archive.readFully(SHORT_BUF); > > @@ -883,13 +921,18 @@ public class ZipFile { > > + SHORT + SHORT + fileNameLen + extraFieldLen; > > > > if (entriesWithoutUTF8Flag.containsKey(ze)) { > > - String orig = ze.getName(); > > NameAndComment nc = entriesWithoutUTF8Flag.get(ze); > > ZipUtil.setNameAndCommentFromExtraFields(ze, nc.name, > > nc.comment); > > } > > - entries.put(ze, offsetEntry); > > - nameMap.put(ze.getName(), ze); > > + > > + String name = ze.getName(); > > + Deque<ZipArchiveEntry> entriesOfThatName = > nameMap.get(name); > > + if (entriesOfThatName == null) { > > + entriesOfThatName = new LinkedList<ZipArchiveEntry>(); > > + nameMap.put(name, entriesOfThatName); > > + } > > + entriesOfThatName.addLast(ze); > > } > > } > > > > @@ -996,16 +1039,54 @@ public class ZipFile { > > return 0; > > } > > > > - OffsetEntry off1 = entries.get(e1); > > - OffsetEntry off2 = entries.get(e2); > > - if (off1 == null) { > > + @SuppressWarnings("unchecked") Entry ent1 = > > + e1 instanceof Entry ? (Entry) e1 : null; > > + @SuppressWarnings("unchecked") Entry ent2 = > > + e2 instanceof Entry ? (Entry) e2 : null; > > + if (ent1 == null) { > > return 1; > > } > > - if (off2 == null) { > > + if (ent2 == null) { > > return -1; > > } > > - long val = (off1.headerOffset - off2.headerOffset); > > + long val = (ent1.getOffsetEntry().headerOffset > > + - ent2.getOffsetEntry().headerOffset); > > return val == 0 ? 0 : val < 0 ? -1 : +1; > > } > > }; > > + > > + /** > > + * Extends ZipArchiveEntry to store the offset within the archive. > > + */ > > + private static class Entry extends ZipArchiveEntry { > > + > > + private final OffsetEntry offsetEntry; > > + > > + Entry(OffsetEntry offset) { > > + this.offsetEntry = offset; > > + } > > + > > + OffsetEntry getOffsetEntry() { > > + return offsetEntry; > > + } > > + > > + @Override > > + public int hashCode() { > > + return 3 * super.hashCode() > > + + (int) (offsetEntry.headerOffset % Integer.MAX_VALUE); > > + } > > + > > + @Override > > + public boolean equals(Object other) { > > + if (super.equals(other)) { > > + // super.equals would return false otherwise > > + @SuppressWarnings("unchecked") Entry otherEntry = > (Entry) other; > > + return offsetEntry.headerOffset > > + == otherEntry.offsetEntry.headerOffset > > + && offsetEntry.dataOffset > > + == otherEntry.offsetEntry.dataOffset; > > + } > > + return false; > > + } > > + } > > } > > > > Modified: > commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java > > URL: > http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java?rev=1486348&r1=1486347&r2=1486348&view=diff > > > ============================================================================== > > --- > commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java > (original) > > +++ > commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipFileTest.java > Sat May 25 17:47:00 2013 > > @@ -27,6 +27,7 @@ import java.io.OutputStream; > > import java.util.ArrayList; > > import java.util.Collections; > > import java.util.Enumeration; > > +import java.util.Iterator; > > import java.util.TreeMap; > > import java.util.zip.ZipEntry; > > > > @@ -214,6 +215,12 @@ public class ZipFileTest extends TestCas > > ZipArchiveEntry ze = zf.getEntry("test1.txt"); > > assertNotNull(ze); > > assertNotNull(zf.getInputStream(ze)); > > + > > + int numberOfEntries = 0; > > + for (Iterator it = zf.getEntries("test1.txt"); it.hasNext(); > it.next()) { > > + numberOfEntries++; > > + } > > + assertEquals(2, numberOfEntries); > > } > > > > /* > > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org > For additional commands, e-mail: dev-h...@commons.apache.org > > -- E-Mail: garydgreg...@gmail.com | ggreg...@apache.org Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> Spring Batch in Action <http://www.manning.com/templier/> Blog: http://garygregory.wordpress.com Home: http://garygregory.com/ Tweet! http://twitter.com/GaryGregory