On 28 May 2013 19:15, Gary Gregory <[email protected]> wrote:
> On Tue, May 28, 2013 at 2:08 PM, sebb <[email protected]> wrote:
>
>> On 25 May 2013 18:47, <[email protected]> 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.
That is not something to be done without considering the effect on
downstream users.
> 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: [email protected]
>> For additional commands, e-mail: [email protected]
>>
>>
>
>
> --
> E-Mail: [email protected] | [email protected]
> 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
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]