Author: ebourg
Date: Thu Dec 19 16:09:54 2013
New Revision: 1552325
URL: http://svn.apache.org/r1552325
Log:
Explode support for ZipFile and ZipArchiveInputStream (COMPRESS-115)
Added:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
(with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
(with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/CircularBuffer.java
(with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
(with props)
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BinaryTreeTest.java
(with props)
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BitStreamTest.java
(with props)
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/CircularBufferTest.java
(with props)
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ExplodeSupportTest.java
(with props)
commons/proper/compress/trunk/src/test/resources/archives/imploding-4Kdict-2trees.zip
(with props)
commons/proper/compress/trunk/src/test/resources/archives/imploding-8Kdict-3trees.zip
(with props)
Modified:
commons/proper/compress/trunk/src/changes/changes.xml
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/GeneralPurposeBit.java
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipUtil.java
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
commons/proper/compress/trunk/src/test/resources/moby.zip
Modified: commons/proper/compress/trunk/src/changes/changes.xml
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/changes/changes.xml?rev=1552325&r1=1552324&r2=1552325&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/changes/changes.xml (original)
+++ commons/proper/compress/trunk/src/changes/changes.xml Thu Dec 19 16:09:54
2013
@@ -78,6 +78,9 @@ The <action> type attribute can be add,u
GzipCompressorOutputStream now supports setting the compression level
and the header metadata
(filename, comment, modification time, operating system and extra
flags)
</action>
+ <action issue="COMPRESS-115" type="add" date="2012-12-19"
due-to="Emmanuel Bourg">
+ ZipFile and ZipArchiveInputStream now support reading entries
compressed using the IMPLODE method.
+ </action>
</release>
<release version="1.6" date="2013-10-26"
description="Release 1.6">
Added:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
(added)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+/**
+ * Binary tree of positive values.
+ *
+ * @author Emmanuel Bourg
+ * @since 1.7
+ */
+class BinaryTree {
+
+ /** Value in the array indicating an undefined node */
+ private static final int UNDEFINED = -1;
+
+ /** Value in the array indicating a non leaf node */
+ private static final int NODE = -2;
+
+ /**
+ * The array representing the binary tree. The root is at index 0,
+ * the left children are at 2*i+1 and the right children at 2*i+2.
+ */
+ private final int[] tree;
+
+ public BinaryTree(int depth) {
+ tree = new int[(1 << (depth + 1)) - 1];
+ Arrays.fill(tree, UNDEFINED);
+ }
+
+ /**
+ * Adds a leaf to the tree.
+ *
+ * @param node the index of the node where the path is appended
+ * @param path the path to the leaf (bits are parsed from the right to
the left)
+ * @param depth the number of nodes in the path
+ * @param value the value of the leaf (must be positive)
+ */
+ public void addLeaf(int node, int path, int depth, int value) {
+ if (depth == 0) {
+ // end of the path reached, add the value to the current node
+ if (tree[node] == UNDEFINED) {
+ tree[node] = value;
+ } else {
+ throw new IllegalArgumentException("Tree value at index " +
node + " has already been assigned (" + tree[node] + ")");
+ }
+ } else {
+ // mark the current node as a non leaf node
+ tree[node] = NODE;
+
+ // move down the path recursively
+ int nextChild = 2 * node + 1 + (path & 1);
+ addLeaf(nextChild, path >>> 1, depth - 1, value);
+ }
+ }
+
+ /**
+ * Reads a value from the specified bit stream.
+ *
+ * @param stream
+ * @return the value decoded, or -1 if the end of the stream is reached
+ */
+ public int read(BitStream stream) throws IOException {
+ short currentIndex = 0;
+
+ while (true) {
+ int bit = stream.nextBit();
+ if (bit == -1) {
+ return -1;
+ }
+
+ short childIndex = (short) (2 * currentIndex + 1 + bit);
+ int value = tree[childIndex];
+ if (value == NODE) {
+ // consume the next bit
+ currentIndex = childIndex;
+ } else if (value != UNDEFINED) {
+ return value;
+ } else {
+ throw new IOException("The child " + bit + " of node at index
" + currentIndex + " is not defined");
+ }
+ }
+ }
+
+
+ /**
+ * Decodes the packed binary tree from the specified stream.
+ */
+ static BinaryTree decode(InputStream in, final int totalNumberOfValues)
throws IOException {
+ // the first byte contains the size of the structure minus one
+ int size = in.read() + 1;
+ if (size == 0) {
+ throw new IOException("Cannot read the size of the encoded tree,
unexpected end of stream");
+ }
+
+ byte[] encodedTree = new byte[size];
+ new DataInputStream(in).readFully(encodedTree);
+
+ /** The maximum bit length for a value (16 or lower) */
+ int maxLength = 0;
+
+ int[] originalBitLengths = new int[totalNumberOfValues];
+ int pos = 0;
+ for (byte b : encodedTree) {
+ // each byte encodes the number of values (upper 4 bits) for a bit
length (lower 4 bits)
+ int numberOfValues = ((b & 0xF0) >> 4) + 1;
+ int bitLength = (b & 0x0F) + 1;
+
+ for (int j = 0; j < numberOfValues; j++) {
+ originalBitLengths[pos++] = bitLength;
+ }
+
+ maxLength = Math.max(maxLength, bitLength);
+ }
+
+ // sort the array of bit lengths and memorize the permutation used to
restore the order of the codes
+ int[] permutation = new int[originalBitLengths.length];
+ for (int k = 0; k < permutation.length; k++) {
+ permutation[k] = k;
+ }
+
+ int c = 0;
+ int[] sortedBitLengths = new int[originalBitLengths.length];
+ for (int k = 0; k < originalBitLengths.length; k++) {
+ // iterate over the values
+ for (int l = 0; l < originalBitLengths.length; l++) {
+ // look for the value in the original array
+ if (originalBitLengths[l] == k) {
+ // put the value at the current position in the sorted
array...
+ sortedBitLengths[c] = k;
+
+ // ...and memorize the permutation
+ permutation[c] = l;
+
+ c++;
+ }
+ }
+ }
+
+ // decode the values of the tree
+ int code = 0;
+ int codeIncrement = 0;
+ int lastBitLength = 0;
+
+ int[] codes = new int[totalNumberOfValues];
+
+ for (int i = totalNumberOfValues - 1; i >= 0; i--) {
+ code = code + codeIncrement;
+ if (sortedBitLengths[i] != lastBitLength) {
+ lastBitLength = sortedBitLengths[i];
+ codeIncrement = 1 << (16 - lastBitLength);
+ }
+ codes[permutation[i]] = code;
+ }
+
+ // build the tree
+ BinaryTree tree = new BinaryTree(maxLength);
+
+ for (int k = 0; k < codes.length; k++) {
+ int bitLength = originalBitLengths[k];
+ if (bitLength > 0) {
+ tree.addLeaf(0, Integer.reverse(codes[k] << 16), bitLength, k);
+ }
+ }
+
+ return tree;
+ }
+}
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BinaryTree.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
(added)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Iterates over the bits of an InputStream. For each byte the bits
+ * are read from the right to the left.
+ *
+ * @since 1.7
+ */
+class BitStream {
+
+ private final InputStream in;
+
+ /** The bits read from the underlying stream but not consumed by
nextBits() */
+ private long bitCache;
+
+ /** The number of bits available in the bit cache */
+ private int bitCacheSize;
+
+ /** Bit masks for extracting the right most bits from a byte */
+ private static final int[] MASKS = new int[]{
+ 0x00, // 00000000
+ 0x01, // 00000001
+ 0x03, // 00000011
+ 0x07, // 00000111
+ 0x0F, // 00001111
+ 0x1F, // 00011111
+ 0x3F, // 00111111
+ 0x7F, // 01111111
+ 0xFF // 11111111
+ };
+
+ BitStream(InputStream in) {
+ this.in = in;
+ }
+
+ private boolean fillCache() throws IOException {
+ boolean filled = false;
+
+ while (bitCacheSize <= 56) {
+ long nextByte = in.read();
+ if (nextByte == -1) {
+ break;
+ }
+
+ filled = true;
+ bitCache = bitCache | (nextByte << bitCacheSize);
+ bitCacheSize += 8;
+ }
+
+ return filled;
+ }
+
+ /**
+ * Returns the next bit.
+ *
+ * @return The next bit (0 or 1) or -1 if the end of the stream has been
reached
+ */
+ int nextBit() throws IOException {
+ if (bitCacheSize == 0) {
+ if (!fillCache()) {
+ return -1;
+ }
+ }
+
+ int bit = (int) (bitCache & 1); // extract the right most bit
+
+ bitCache = (bitCache >>> 1); // shift the remaning bits to the right
+ bitCacheSize--;
+
+ return bit;
+ }
+
+ /**
+ * Returns the integer value formed by the n next bits (up to 8 bits).
+ *
+ * @param n the number of bits read (up to 8)
+ * @return The value formed by the n bits, or -1 if the end of the stream
has been reached
+ */
+ int nextBits(final int n) throws IOException {
+ if (bitCacheSize < n) {
+ if (!fillCache()) {
+ return -1;
+ }
+ }
+
+ final int bits = (int) (bitCache & MASKS[n]); // extract the right
most bits
+
+ bitCache = (bitCache >>> n); // shift the remaning bits to the right
+ bitCacheSize = bitCacheSize - n;
+
+ return bits;
+ }
+
+ int nextByte() throws IOException {
+ return nextBits(8);
+ }
+}
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/BitStream.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/CircularBuffer.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/CircularBuffer.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/CircularBuffer.java
(added)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/CircularBuffer.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+/**
+ * Circular byte buffer.
+ *
+ * @author Emmanuel Bourg
+ * @since 1.7
+ */
+class CircularBuffer {
+
+ /** Size of the buffer */
+ private final int size;
+
+ /** The buffer */
+ private final byte[] buffer;
+
+ /** Index of the next data to be read from the buffer */
+ private int readIndex;
+
+ /** Index of the next data written in the buffer */
+ private int writeIndex;
+
+ CircularBuffer(int size) {
+ this.size = size;
+ buffer = new byte[size];
+ }
+
+ /**
+ * Tells if a new byte can be read from the buffer.
+ */
+ public boolean available() {
+ return readIndex != writeIndex;
+ }
+
+ /**
+ * Writes a byte to the buffer.
+ */
+ public void put(int value) {
+ buffer[writeIndex] = (byte) value;
+ writeIndex = (writeIndex + 1) % size;
+ }
+
+ /**
+ * Reads a byte from the buffer.
+ */
+ public int get() {
+ if (available()) {
+ int value = buffer[readIndex];
+ readIndex = (readIndex + 1) % size;
+ return value & 0xFF;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Copy a previous interval in the buffer to the current position.
+ *
+ * @param distance the distance from the current write position
+ * @param length the number of bytes to copy
+ */
+ public void copy(int distance, int length) {
+ int pos1 = writeIndex - distance;
+ int pos2 = pos1 + length;
+ for (int i = pos1; i < pos2; i++) {
+ buffer[writeIndex] = buffer[(i + size) % size];
+ writeIndex = (writeIndex + 1) % size;
+ }
+ }
+}
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/CircularBuffer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/CircularBuffer.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
(added)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * The implode compression method was added to PKZIP 1.01 released in 1989.
+ * It was then dropped from PKZIP 2.0 released in 1993 in favor of the deflate
+ * method.
+ * <p>
+ * The algorithm is described in the ZIP File Format Specification.
+ *
+ * @see <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">ZIP
File Format Specification</a>
+ *
+ * @author Emmanuel Bourg
+ * @since 1.7
+ */
+class ExplodingInputStream extends InputStream {
+
+ /** The underlying stream containing the compressed data */
+ private final InputStream in;
+
+ /** The stream of bits read from the input stream */
+ private BitStream bits;
+
+ /** The size of the sliding dictionary (4K or 8K) */
+ private final int dictionarySize;
+
+ /** The number of Shannon-Fano trees (2 or 3) */
+ private final int numberOfTrees;
+
+ private final int minimumMatchLength;
+
+ /** The binary tree containing the 256 encoded literals (null when only
two trees are used) */
+ private BinaryTree literalTree;
+
+ /** The binary tree containing the 64 encoded lengths */
+ private BinaryTree lengthTree;
+
+ /** The binary tree containing the 64 encoded distances */
+ private BinaryTree distanceTree;
+
+ /** Output buffer holding the decompressed data */
+ private final CircularBuffer buffer = new CircularBuffer(32 * 1024);
+
+ /**
+ * Create a new stream decompressing the content of the specified stream
+ * using the explode algorithm.
+ *
+ * @param dictionarySize the size of the sliding dictionary (4096 or 8192)
+ * @param numberOfTrees the number of trees (2 or 3)
+ * @param in the compressed data stream
+ */
+ public ExplodingInputStream(int dictionarySize, int numberOfTrees,
InputStream in) {
+ if (dictionarySize != 4096 && dictionarySize != 8192) {
+ throw new IllegalArgumentException("The dictionary size must be
4096 or 8192");
+ }
+ if (numberOfTrees != 2 && numberOfTrees != 3) {
+ throw new IllegalArgumentException("The number of trees must be 2
or 3");
+ }
+ this.dictionarySize = dictionarySize;
+ this.numberOfTrees = numberOfTrees;
+ this.minimumMatchLength = numberOfTrees;
+ this.in = in;
+ }
+
+ /**
+ * Reads the encoded binary trees and prepares the bit stream.
+ *
+ * @throws IOException
+ */
+ private void init() throws IOException {
+ if (bits == null) {
+ if (numberOfTrees == 3) {
+ literalTree = BinaryTree.decode(in, 256);
+ }
+
+ lengthTree = BinaryTree.decode(in, 64);
+ distanceTree = BinaryTree.decode(in, 64);
+
+ bits = new BitStream(in);
+ }
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (!buffer.available()) {
+ fillBuffer();
+ }
+
+ return buffer.get();
+ }
+
+ /**
+ * Fill the sliding dictionary with more data.
+ * @throws IOException
+ */
+ private void fillBuffer() throws IOException {
+ init();
+
+ int bit = bits.nextBit();
+ if (bit == 1) {
+ // literal value
+ int literal;
+ if (literalTree != null) {
+ literal = literalTree.read(bits);
+ } else {
+ literal = bits.nextBits(8);
+ }
+
+ if (literal == -1) {
+ // end of stream reached, nothing left to decode
+ return;
+ }
+
+ buffer.put(literal);
+
+ } else if (bit == 0) {
+ // back reference
+ int distanceLowSize = dictionarySize == 4096 ? 6 : 7;
+ int distanceLow = bits.nextBits(distanceLowSize);
+ int distanceHigh = distanceTree.read(bits);
+ if (distanceHigh == -1 && distanceLow <= 0) {
+ // end of stream reached, nothing left to decode
+ return;
+ }
+ int distance = distanceHigh << distanceLowSize | distanceLow;
+
+ int length = lengthTree.read(bits);
+ if (length == 63) {
+ length += bits.nextBits(8);
+ }
+ length += minimumMatchLength;
+
+ buffer.copy(distance + 1, length);
+ }
+ }
+
+}
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ExplodingInputStream.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/GeneralPurposeBit.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/GeneralPurposeBit.java?rev=1552325&r1=1552324&r2=1552325&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/GeneralPurposeBit.java
(original)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/GeneralPurposeBit.java
Thu Dec 19 16:09:54 2013
@@ -20,16 +20,36 @@ package org.apache.commons.compress.arch
/**
* Parser/encoder for the "general purpose bit" field in ZIP's local
* file and central directory headers.
+ *
* @since 1.1
* @NotThreadSafe
*/
public final class GeneralPurposeBit {
+
/**
* Indicates that the file is encrypted.
*/
private static final int ENCRYPTION_FLAG = 1 << 0;
/**
+ * Indicates the size of the sliding dictionary used by the compression
method 6 (imploding).
+ * <ul>
+ * <li>0: 4096 bytes</li>
+ * <li>1: 8192 bytes</li>
+ * </ul>
+ */
+ private static final int SLIDING_DICTIONARY_SIZE_FLAG = 1 << 1;
+
+ /**
+ * Indicates the number of Shannon-Fano trees used by the compression
method 6 (imploding).
+ * <ul>
+ * <li>0: 2 trees (lengths, distances)</li>
+ * <li>1: 3 trees (literals, lengths, distances)</li>
+ * </ul>
+ */
+ private static final int NUMBER_OF_SHANNON_FANO_TREES_FLAG = 1 << 2;
+
+ /**
* Indicates that a data descriptor stored after the file contents
* will hold CRC and size information.
*/
@@ -53,6 +73,8 @@ public final class GeneralPurposeBit {
private boolean dataDescriptorFlag = false;
private boolean encryptionFlag = false;
private boolean strongEncryptionFlag = false;
+ private int slidingDictionarySize;
+ private int numberOfShannonFanoTrees;
public GeneralPurposeBit() {
}
@@ -119,6 +141,20 @@ public final class GeneralPurposeBit {
}
/**
+ * Returns the sliding dictionary size used by the compression method 6
(imploding).
+ */
+ int getSlidingDictionarySize() {
+ return slidingDictionarySize;
+ }
+
+ /**
+ * Returns the number of trees used by the compression method 6
(imploding).
+ */
+ int getNumberOfShannonFanoTrees() {
+ return numberOfShannonFanoTrees;
+ }
+
+ /**
* Encodes the set bits in a form suitable for ZIP archives.
*/
public byte[] encode() {
@@ -135,6 +171,7 @@ public final class GeneralPurposeBit {
/**
* Parses the supported flags from the given archive data.
+ *
* @param data local file header or a central directory entry.
* @param offset offset at which the general purpose bit starts
*/
@@ -143,9 +180,10 @@ public final class GeneralPurposeBit {
GeneralPurposeBit b = new GeneralPurposeBit();
b.useDataDescriptor((generalPurposeFlag & DATA_DESCRIPTOR_FLAG) != 0);
b.useUTF8ForNames((generalPurposeFlag & UFT8_NAMES_FLAG) != 0);
- b.useStrongEncryption((generalPurposeFlag & STRONG_ENCRYPTION_FLAG)
- != 0);
+ b.useStrongEncryption((generalPurposeFlag & STRONG_ENCRYPTION_FLAG) !=
0);
b.useEncryption((generalPurposeFlag & ENCRYPTION_FLAG) != 0);
+ b.slidingDictionarySize = ((generalPurposeFlag &
SLIDING_DICTIONARY_SIZE_FLAG) != 0) ? 8192 : 4096;
+ b.numberOfShannonFanoTrees = ((generalPurposeFlag &
NUMBER_OF_SHANNON_FANO_TREES_FLAG) != 0) ? 3 : 2;
return b;
}
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java?rev=1552325&r1=1552324&r2=1552325&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
(original)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
Thu Dec 19 16:09:54 2013
@@ -271,10 +271,16 @@ public class ZipArchiveInputStream exten
}
processZip64Extra(size, cSize);
-
- if (current.entry.getCompressedSize() != -1
- && current.entry.getMethod() ==
ZipMethod.UNSHRINKING.getCode()) {
- current.in = new UnshrinkingInputStream(new BoundedInputStream(in,
current.entry.getCompressedSize()));
+
+ if (current.entry.getCompressedSize() != -1) {
+ if (current.entry.getMethod() == ZipMethod.UNSHRINKING.getCode()) {
+ current.in = new UnshrinkingInputStream(new
BoundedInputStream(in, current.entry.getCompressedSize()));
+ } else if (current.entry.getMethod() ==
ZipMethod.IMPLODING.getCode()) {
+ current.in = new ExplodingInputStream(
+
current.entry.getGeneralPurposeBit().getSlidingDictionarySize(),
+
current.entry.getGeneralPurposeBit().getNumberOfShannonFanoTrees(),
+ new BoundedInputStream(in,
current.entry.getCompressedSize()));
+ }
}
entriesRead++;
@@ -374,7 +380,8 @@ public class ZipArchiveInputStream exten
read = readStored(buffer, offset, length);
} else if (current.entry.getMethod() ==
ZipArchiveOutputStream.DEFLATED) {
read = readDeflated(buffer, offset, length);
- } else if (current.entry.getMethod() ==
ZipMethod.UNSHRINKING.getCode()) {
+ } else if (current.entry.getMethod() == ZipMethod.UNSHRINKING.getCode()
+ || current.entry.getMethod() == ZipMethod.IMPLODING.getCode())
{
read = current.in.read(buffer, offset, length);
} else {
throw new
UnsupportedZipFeatureException(ZipMethod.getMethodByCode(current.entry.getMethod()),
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java?rev=1552325&r1=1552324&r2=1552325&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
(original)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
Thu Dec 19 16:09:54 2013
@@ -741,7 +741,8 @@ public class ZipArchiveOutputStream exte
@Override
public boolean canWriteEntryData(ArchiveEntry ae) {
if (ae instanceof ZipArchiveEntry) {
- return ZipUtil.canHandleEntryData((ZipArchiveEntry) ae);
+ ZipArchiveEntry zae = (ZipArchiveEntry) ae;
+ return zae.getMethod() != ZipMethod.IMPLODING.getCode() &&
ZipUtil.canHandleEntryData(zae);
}
return false;
}
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=1552325&r1=1552324&r2=1552325&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
Thu Dec 19 16:09:54 2013
@@ -17,6 +17,7 @@
*/
package org.apache.commons.compress.archivers.zip;
+import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
@@ -378,6 +379,9 @@ public class ZipFile {
return bis;
case UNSHRINKING:
return new UnshrinkingInputStream(bis);
+ case IMPLODING:
+ return new
ExplodingInputStream(ze.getGeneralPurposeBit().getSlidingDictionarySize(),
+
ze.getGeneralPurposeBit().getNumberOfShannonFanoTrees(), new
BufferedInputStream(bis));
case DEFLATED:
bis.addDummy();
final Inflater inflater = new Inflater(true);
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipUtil.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipUtil.java?rev=1552325&r1=1552324&r2=1552325&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipUtil.java
(original)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipUtil.java
Thu Dec 19 16:09:54 2013
@@ -303,6 +303,7 @@ public abstract class ZipUtil {
private static boolean supportsMethodOf(ZipArchiveEntry entry) {
return entry.getMethod() == ZipEntry.STORED
|| entry.getMethod() == ZipMethod.UNSHRINKING.getCode()
+ || entry.getMethod() == ZipMethod.IMPLODING.getCode()
|| entry.getMethod() == ZipEntry.DEFLATED;
}
Modified:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java?rev=1552325&r1=1552324&r2=1552325&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
(original)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/ZipTestCase.java
Thu Dec 19 16:09:54 2013
@@ -32,6 +32,7 @@ import org.apache.commons.compress.archi
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
+import org.apache.commons.compress.archivers.zip.ZipMethod;
import org.apache.commons.compress.utils.IOUtils;
public final class ZipTestCase extends AbstractTestCase {
@@ -139,12 +140,16 @@ public final class ZipTestCase extends A
* >COMPRESS-93</a>.
*/
public void testSupportedCompressionMethod() throws IOException {
+ /*
ZipFile bla = new ZipFile(getFile("bla.zip"));
assertTrue(bla.canReadEntryData(bla.getEntry("test1.xml")));
bla.close();
-
+ */
+
ZipFile moby = new ZipFile(getFile("moby.zip"));
- assertFalse(moby.canReadEntryData(moby.getEntry("README")));
+ ZipArchiveEntry entry = moby.getEntry("README");
+ assertEquals("method", ZipMethod.TOKENIZATION.getCode(),
entry.getMethod());
+ assertFalse(moby.canReadEntryData(entry));
moby.close();
}
@@ -162,6 +167,7 @@ public final class ZipTestCase extends A
new ZipArchiveInputStream(new
FileInputStream(getFile("moby.zip")));
try {
ZipArchiveEntry entry = zip.getNextZipEntry();
+ assertEquals("method", ZipMethod.TOKENIZATION.getCode(),
entry.getMethod());
assertEquals("README", entry.getName());
assertFalse(zip.canReadEntryData(entry));
try {
Added:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BinaryTreeTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BinaryTreeTest.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BinaryTreeTest.java
(added)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BinaryTreeTest.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+public class BinaryTreeTest extends TestCase {
+
+ public void testDecode() throws IOException {
+ InputStream in = new ByteArrayInputStream(new byte[] { 0x02, 0x42,
0x01, 0x13 });
+
+ BinaryTree tree = BinaryTree.decode(in, 8);
+
+ assertNotNull(tree);
+
+ BitStream stream = new BitStream(new ByteArrayInputStream(new byte[] {
(byte) 0x8D, (byte) 0xC5, (byte) 0x11, 0x00 }));
+ assertEquals(0, tree.read(stream));
+ assertEquals(1, tree.read(stream));
+ assertEquals(2, tree.read(stream));
+ assertEquals(3, tree.read(stream));
+ assertEquals(4, tree.read(stream));
+ assertEquals(5, tree.read(stream));
+ assertEquals(6, tree.read(stream));
+ assertEquals(7, tree.read(stream));
+ }
+}
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BinaryTreeTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BinaryTreeTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BitStreamTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BitStreamTest.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BitStreamTest.java
(added)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BitStreamTest.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import java.io.ByteArrayInputStream;
+
+import junit.framework.TestCase;
+
+public class BitStreamTest extends TestCase {
+
+ public void testEmptyStream() throws Exception {
+ BitStream stream = new BitStream(new ByteArrayInputStream(new
byte[0]));
+ assertEquals("next bit", -1, stream.nextBit());
+ assertEquals("next bit", -1, stream.nextBit());
+ assertEquals("next bit", -1, stream.nextBit());
+ }
+
+ public void testStream() throws Exception {
+ BitStream stream = new BitStream(new ByteArrayInputStream(new byte[] {
(byte) 0xEA, 0x03 }));
+
+ assertEquals("bit 0", 0, stream.nextBit());
+ assertEquals("bit 1", 1, stream.nextBit());
+ assertEquals("bit 2", 0, stream.nextBit());
+ assertEquals("bit 3", 1, stream.nextBit());
+ assertEquals("bit 4", 0, stream.nextBit());
+ assertEquals("bit 5", 1, stream.nextBit());
+ assertEquals("bit 6", 1, stream.nextBit());
+ assertEquals("bit 7", 1, stream.nextBit());
+
+ assertEquals("bit 8", 1, stream.nextBit());
+ assertEquals("bit 9", 1, stream.nextBit());
+ assertEquals("bit 10", 0, stream.nextBit());
+ assertEquals("bit 11", 0, stream.nextBit());
+ assertEquals("bit 12", 0, stream.nextBit());
+ assertEquals("bit 13", 0, stream.nextBit());
+ assertEquals("bit 14", 0, stream.nextBit());
+ assertEquals("bit 15", 0, stream.nextBit());
+
+ assertEquals("next bit", -1, stream.nextBit());
+ }
+
+ public void testNextByteFromEmptyStream() throws Exception {
+ BitStream stream = new BitStream(new ByteArrayInputStream(new
byte[0]));
+ assertEquals("next byte", -1, stream.nextByte());
+ assertEquals("next byte", -1, stream.nextByte());
+ }
+
+ public void testReadAlignedBytes() throws Exception {
+ BitStream stream = new BitStream(new ByteArrayInputStream(new byte[] {
(byte) 0xEA, 0x35 }));
+ assertEquals("next byte", 0xEA, stream.nextByte());
+ assertEquals("next byte", 0x35, stream.nextByte());
+ assertEquals("next byte", -1, stream.nextByte());
+ }
+
+ public void testNextByte() throws Exception {
+ BitStream stream = new BitStream(new ByteArrayInputStream(new byte[] {
(byte) 0xEA, 0x35 }));
+ assertEquals("bit 0", 0, stream.nextBit());
+ assertEquals("bit 1", 1, stream.nextBit());
+ assertEquals("bit 2", 0, stream.nextBit());
+ assertEquals("bit 3", 1, stream.nextBit());
+
+ assertEquals("next byte", 0x5E, stream.nextByte());
+ assertEquals("next byte", -1, stream.nextByte()); // not enough bits
left to read a byte
+ }
+}
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BitStreamTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/BitStreamTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/CircularBufferTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/CircularBufferTest.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/CircularBufferTest.java
(added)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/CircularBufferTest.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import junit.framework.TestCase;
+
+public class CircularBufferTest extends TestCase {
+
+ public void testPutAndGet() throws Exception {
+ int size = 16;
+ CircularBuffer buffer = new CircularBuffer(size);
+ for (int i = 0; i < size / 2; i++) {
+ buffer.put(i);
+ }
+
+ assertTrue("available", buffer.available());
+
+ for (int i = 0; i < size / 2; i++) {
+ assertEquals("buffer[" + i + "]", i, buffer.get());
+ }
+
+ assertEquals(-1, buffer.get());
+ assertFalse("available", buffer.available());
+ }
+
+ public void testCopy() throws Exception {
+ CircularBuffer buffer = new CircularBuffer(16);
+
+ buffer.put(1);
+ buffer.put(2);
+ buffer.get();
+ buffer.get();
+
+ // copy uninitialized data
+ buffer.copy(6, 8);
+
+ for (int i = 2; i < 6; i++) {
+ assertEquals("buffer[" + i + "]", 0, buffer.get());
+ }
+ assertEquals("buffer[" + 6 + "]", 1, buffer.get());
+ assertEquals("buffer[" + 7 + "]", 2, buffer.get());
+ assertEquals("buffer[" + 8 + "]", 0, buffer.get());
+ assertEquals("buffer[" + 9 + "]", 0, buffer.get());
+
+ for (int i = 10; i < 14; i++) {
+ buffer.put(i);
+ buffer.get();
+ }
+
+ assertFalse("available", buffer.available());
+
+ // copy data and wrap
+ buffer.copy(2, 8);
+
+ for (int i = 14; i < 18; i++) {
+ assertEquals("buffer[" + i + "]", i % 2 == 0 ? 12 : 13,
buffer.get());
+ }
+ }
+}
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/CircularBufferTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/CircularBufferTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ExplodeSupportTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ExplodeSupportTest.java?rev=1552325&view=auto
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ExplodeSupportTest.java
(added)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ExplodeSupportTest.java
Thu Dec 19 16:09:54 2013
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.commons.compress.archivers.zip;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.CRC32;
+import java.util.zip.CheckedOutputStream;
+
+import junit.framework.TestCase;
+import org.apache.commons.compress.utils.BoundedInputStream;
+import org.apache.commons.compress.utils.IOUtils;
+
+public class ExplodeSupportTest extends TestCase {
+
+ private void testArchiveWithImplodeCompression(String filename, String
entryName) throws IOException {
+ ZipFile zip = new ZipFile(new File(filename));
+ ZipArchiveEntry entry = zip.getEntries().nextElement();
+ assertEquals("entry name", entryName, entry.getName());
+ assertTrue("entry can't be read", zip.canReadEntryData(entry));
+ assertEquals("method", ZipMethod.IMPLODING.getCode(),
entry.getMethod());
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ CheckedOutputStream out = new CheckedOutputStream(bout, new CRC32());
+ IOUtils.copy(zip.getInputStream(entry), out);
+
+ out.flush();
+
+ assertEquals("CRC32", entry.getCrc(), out.getChecksum().getValue());
+ }
+
+ public void testArchiveWithImplodeCompression4K2Trees() throws IOException
{
+
testArchiveWithImplodeCompression("target/test-classes/archives/imploding-4Kdict-2trees.zip",
"HEADER.TXT");
+ }
+
+ public void testArchiveWithImplodeCompression8K3Trees() throws IOException
{
+
testArchiveWithImplodeCompression("target/test-classes/archives/imploding-8Kdict-3trees.zip",
"LICENSE.TXT");
+ }
+
+ private void testZipStreamWithImplodeCompression(String filename, String
entryName) throws IOException {
+ ZipArchiveInputStream zin = new ZipArchiveInputStream(new
FileInputStream(new File(filename)));
+ ZipArchiveEntry entry = zin.getNextZipEntry();
+ assertEquals("entry name", entryName, entry.getName());
+ assertTrue("entry can't be read", zin.canReadEntryData(entry));
+ assertEquals("method", ZipMethod.IMPLODING.getCode(),
entry.getMethod());
+
+ InputStream bio = new BoundedInputStream(zin, entry.getSize());
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ CheckedOutputStream out = new CheckedOutputStream(bout, new CRC32());
+ IOUtils.copy(bio, out);
+
+ out.flush();
+
+ assertEquals("CRC32", entry.getCrc(), out.getChecksum().getValue());
+ }
+
+ public void testZipStreamWithImplodeCompression4K2Trees() throws
IOException {
+
testZipStreamWithImplodeCompression("target/test-classes/archives/imploding-4Kdict-2trees.zip",
"HEADER.TXT");
+ }
+
+ public void testZipStreamWithImplodeCompression8K3Trees() throws
IOException {
+
testZipStreamWithImplodeCompression("target/test-classes/archives/imploding-8Kdict-3trees.zip",
"LICENSE.TXT");
+ }
+}
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ExplodeSupportTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ExplodeSupportTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Added:
commons/proper/compress/trunk/src/test/resources/archives/imploding-4Kdict-2trees.zip
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/resources/archives/imploding-4Kdict-2trees.zip?rev=1552325&view=auto
==============================================================================
Binary file - no diff available.
Propchange:
commons/proper/compress/trunk/src/test/resources/archives/imploding-4Kdict-2trees.zip
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added:
commons/proper/compress/trunk/src/test/resources/archives/imploding-8Kdict-3trees.zip
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/resources/archives/imploding-8Kdict-3trees.zip?rev=1552325&view=auto
==============================================================================
Binary file - no diff available.
Propchange:
commons/proper/compress/trunk/src/test/resources/archives/imploding-8Kdict-3trees.zip
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: commons/proper/compress/trunk/src/test/resources/moby.zip
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/resources/moby.zip?rev=1552325&r1=1552324&r2=1552325&view=diff
==============================================================================
Binary files - no diff available.