COMPRESS-380 make Defalt64InputStream a CompressorInputStream
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/79e76d5f Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/79e76d5f Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/79e76d5f Branch: refs/heads/master Commit: 79e76d5f48fc44ae3d716ac28ebe1a76ebb90b61 Parents: a62c3d0 Author: Stefan Bodewig <bode...@apache.org> Authored: Thu Jan 4 10:48:04 2018 +0100 Committer: Stefan Bodewig <bode...@apache.org> Committed: Thu Jan 4 10:48:04 2018 +0100 ---------------------------------------------------------------------- .../commons/compress/archivers/zip/ZipFile.java | 4 +- .../Deflate64CompressorInputStream.java | 101 +++++++++++++++ .../deflate64/Deflate64InputStream.java | 88 ------------- .../compressors/deflate64/HuffmanDecoder.java | 2 +- .../compress/compressors/deflate64/package.html | 25 ++++ .../Deflate64CompressorInputStreamTest.java | 127 ++++++++++++++++++ .../deflate64/Deflate64InputStreamTest.java | 128 ------------------- 7 files changed, 256 insertions(+), 219 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-compress/blob/79e76d5f/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java index c10fc1a..c661eeb 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java @@ -42,7 +42,7 @@ import java.util.zip.InflaterInputStream; import java.util.zip.ZipException; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; -import org.apache.commons.compress.compressors.deflate64.Deflate64InputStream; +import org.apache.commons.compress.compressors.deflate64.Deflate64CompressorInputStream; import org.apache.commons.compress.utils.IOUtils; import static org.apache.commons.compress.archivers.zip.ZipConstants.DWORD; @@ -504,7 +504,7 @@ public class ZipFile implements Closeable { case BZIP2: return new BZip2CompressorInputStream(bis); case ENHANCED_DEFLATED: - return new Deflate64InputStream(bis, ze.getSize()); + return new Deflate64CompressorInputStream(bis, ze.getSize()); case AES_ENCRYPTED: case EXPANDING_LEVEL_1: case EXPANDING_LEVEL_2: http://git-wip-us.apache.org/repos/asf/commons-compress/blob/79e76d5f/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStream.java new file mode 100644 index 0000000..c097ab3 --- /dev/null +++ b/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStream.java @@ -0,0 +1,101 @@ +/* + * 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.compressors.deflate64; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.compress.compressors.CompressorInputStream; +import static org.apache.commons.compress.utils.IOUtils.closeQuietly; + +/** + * Deflate64 decompressor. + * + * @since 1.16 + */ +public class Deflate64CompressorInputStream extends CompressorInputStream { + private HuffmanDecoder decoder; + private long uncompressedSize; + private long totalRead = 0; + + /** + * Constructs a Deflate64CompressorInputStream. + * + * @param in the stream to read from + * @param uncompressedSize the uncompressed size of the data to be read from in + */ + public Deflate64CompressorInputStream(InputStream in, long uncompressedSize) { + this(new HuffmanDecoder(in), uncompressedSize); + } + + Deflate64CompressorInputStream(HuffmanDecoder decoder, long uncompressedSize) { + this.uncompressedSize = uncompressedSize; + this.decoder = decoder; + } + + @Override + public int read() throws IOException { + byte[] b = new byte[1]; + while (true) { + int r = read(b); + switch (r) { + case 1: + return b[0] & 0xFF; + case -1: + return -1; + case 0: + continue; + default: + throw new IllegalStateException("Invalid return value from read: " + r); + } + } + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int read = -1; + if (decoder != null) { + read = decoder.decode(b, off, len); + count(read); + if (read == -1) { + close(); + } else { + totalRead += read; + } + } + return read; + } + + @Override + public int available() throws IOException { + long available = 0; + if (decoder != null) { + available = uncompressedSize - totalRead; + if (Long.compare(available, Integer.MAX_VALUE) > 0) { + available = Integer.MAX_VALUE; + } + } + return (int) available; + } + + @Override + public void close() throws IOException { + closeQuietly(decoder); + decoder = null; + } +} http://git-wip-us.apache.org/repos/asf/commons-compress/blob/79e76d5f/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStream.java b/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStream.java deleted file mode 100644 index e45f87f..0000000 --- a/src/main/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStream.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.compressors.deflate64; - -import java.io.IOException; -import java.io.InputStream; - -import static org.apache.commons.compress.utils.IOUtils.closeQuietly; - -public class Deflate64InputStream extends InputStream { - private HuffmanDecoder decoder; - private long uncompressedSize; - private long totalRead = 0; - - public Deflate64InputStream(InputStream in, long uncompressedSize) { - this(new HuffmanDecoder(in), uncompressedSize); - } - - Deflate64InputStream(HuffmanDecoder decoder, long uncompressedSize) { - this.uncompressedSize = uncompressedSize; - this.decoder = decoder; - } - - @Override - public int read() throws IOException { - byte[] b = new byte[1]; - while (true) { - int r = read(b); - switch (r) { - case 1: - return b[0] & 0xFF; - case -1: - return -1; - case 0: - continue; - default: - throw new IllegalStateException("Invalid return value from read: " + r); - } - } - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - int read = -1; - if (decoder != null) { - read = decoder.decode(b, off, len); - if (read == -1) { - close(); - } else { - totalRead += read; - } - } - return read; - } - - @Override - public int available() throws IOException { - long available = 0; - if (decoder != null) { - available = uncompressedSize - totalRead; - if (Long.compare(available, Integer.MAX_VALUE) > 0) { - available = Integer.MAX_VALUE; - } - } - return (int) available; - } - - @Override - public void close() throws IOException { - closeQuietly(decoder); - decoder = null; - } -} http://git-wip-us.apache.org/repos/asf/commons-compress/blob/79e76d5f/src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java b/src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java index bf1c4ad..de909db 100644 --- a/src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java +++ b/src/main/java/org/apache/commons/compress/compressors/deflate64/HuffmanDecoder.java @@ -28,7 +28,7 @@ import java.util.Arrays; import static org.apache.commons.compress.compressors.deflate64.HuffmanState.*; import static org.apache.commons.compress.utils.IOUtils.closeQuietly; -public class HuffmanDecoder implements Closeable { +class HuffmanDecoder implements Closeable { /** * -------------------------------------------------------------------- * idx xtra base idx xtra base idx xtra base http://git-wip-us.apache.org/repos/asf/commons-compress/blob/79e76d5f/src/main/java/org/apache/commons/compress/compressors/deflate64/package.html ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/compress/compressors/deflate64/package.html b/src/main/java/org/apache/commons/compress/compressors/deflate64/package.html new file mode 100644 index 0000000..4a0cdd0 --- /dev/null +++ b/src/main/java/org/apache/commons/compress/compressors/deflate64/package.html @@ -0,0 +1,25 @@ +<html> +<!-- + + 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. + +--> + <body> + <p>Provides a stream that allows decompressing streams using the + DEFLATE64(tm) algorithm. DEFLATE64 is a trademark of PKWARE, + Inc.</p> + </body> +</html> http://git-wip-us.apache.org/repos/asf/commons-compress/blob/79e76d5f/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStreamTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStreamTest.java b/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStreamTest.java new file mode 100644 index 0000000..92e7b90 --- /dev/null +++ b/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64CompressorInputStreamTest.java @@ -0,0 +1,127 @@ +/* + * 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.compressors.deflate64; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.InputStreamReader; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.times; + +@RunWith(MockitoJUnitRunner.class) +public class Deflate64CompressorInputStreamTest { + private final HuffmanDecoder nullDecoder = null; + + @Mock + private HuffmanDecoder decoder; + + @Test + public void readWhenClosed() throws Exception + { + long size = Integer.MAX_VALUE - 1; + Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(nullDecoder, size); + assertEquals(-1, input.read()); + assertEquals(-1, input.read(new byte[1])); + assertEquals(-1, input.read(new byte[1], 0, 1)); + } + + @Test + public void properSizeWhenClosed() throws Exception + { + long size = Integer.MAX_VALUE - 1; + Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(nullDecoder, size); + assertEquals(0, input.available()); + } + + @Test + public void properSizeWhenInRange() throws Exception + { + long size = Integer.MAX_VALUE - 1; + Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder, size); + assertEquals(size, input.available()); + } + + @Test + public void properSizeWhenOutOfRange() throws Exception + { + long size = Integer.MAX_VALUE + 1L; + Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder, size); + assertEquals(Integer.MAX_VALUE, input.available()); + } + + @Test + public void properSizeAfterReading() throws Exception + { + byte[] buf = new byte[4096]; + int offset = 1000; + int length = 3096; + + Mockito.when(decoder.decode(buf, offset, length)).thenReturn(2048); + + long size = Integer.MAX_VALUE + 2047L; + Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder, size); + assertEquals(2048, input.read(buf, offset, length)); + assertEquals(Integer.MAX_VALUE - 1, input.available()); + } + + @Test + public void closeCallsDecoder() throws Exception + { + + Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder, 10); + input.close(); + + Mockito.verify(decoder, times(1)).close(); + } + + @Test + public void closeIsDelegatedJustOnce() throws Exception + { + + Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(decoder, 10); + + input.close(); + input.close(); + + Mockito.verify(decoder, times(1)).close(); + } + + @Test + public void uncompressedBlock() throws Exception + { + byte[] data = { + 1, 11, 0, -12, -1, + 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' + }; + + try (Deflate64CompressorInputStream input = new Deflate64CompressorInputStream(new ByteArrayInputStream(data), 11); + BufferedReader br = new BufferedReader(new InputStreamReader(input))) + { + assertEquals("Hello World", br.readLine()); + assertEquals(null, br.readLine()); + } + } + +} http://git-wip-us.apache.org/repos/asf/commons-compress/blob/79e76d5f/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStreamTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStreamTest.java b/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStreamTest.java deleted file mode 100644 index f9d1f3b..0000000 --- a/src/test/java/org/apache/commons/compress/compressors/deflate64/Deflate64InputStreamTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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.compressors.deflate64; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.InputStreamReader; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.times; - -@RunWith(MockitoJUnitRunner.class) -public class Deflate64InputStreamTest -{ - private final HuffmanDecoder nullDecoder = null; - - @Mock - private HuffmanDecoder decoder; - - @Test - public void readWhenClosed() throws Exception - { - long size = Integer.MAX_VALUE - 1; - Deflate64InputStream input = new Deflate64InputStream(nullDecoder, size); - assertEquals(-1, input.read()); - assertEquals(-1, input.read(new byte[1])); - assertEquals(-1, input.read(new byte[1], 0, 1)); - } - - @Test - public void properSizeWhenClosed() throws Exception - { - long size = Integer.MAX_VALUE - 1; - Deflate64InputStream input = new Deflate64InputStream(nullDecoder, size); - assertEquals(0, input.available()); - } - - @Test - public void properSizeWhenInRange() throws Exception - { - long size = Integer.MAX_VALUE - 1; - Deflate64InputStream input = new Deflate64InputStream(decoder, size); - assertEquals(size, input.available()); - } - - @Test - public void properSizeWhenOutOfRange() throws Exception - { - long size = Integer.MAX_VALUE + 1L; - Deflate64InputStream input = new Deflate64InputStream(decoder, size); - assertEquals(Integer.MAX_VALUE, input.available()); - } - - @Test - public void properSizeAfterReading() throws Exception - { - byte[] buf = new byte[4096]; - int offset = 1000; - int length = 3096; - - Mockito.when(decoder.decode(buf, offset, length)).thenReturn(2048); - - long size = Integer.MAX_VALUE + 2047L; - Deflate64InputStream input = new Deflate64InputStream(decoder, size); - assertEquals(2048, input.read(buf, offset, length)); - assertEquals(Integer.MAX_VALUE - 1, input.available()); - } - - @Test - public void closeCallsDecoder() throws Exception - { - - Deflate64InputStream input = new Deflate64InputStream(decoder, 10); - input.close(); - - Mockito.verify(decoder, times(1)).close(); - } - - @Test - public void closeIsDelegatedJustOnce() throws Exception - { - - Deflate64InputStream input = new Deflate64InputStream(decoder, 10); - - input.close(); - input.close(); - - Mockito.verify(decoder, times(1)).close(); - } - - @Test - public void uncompressedBlock() throws Exception - { - byte[] data = { - 1, 11, 0, -12, -1, - 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' - }; - - try (Deflate64InputStream input = new Deflate64InputStream(new ByteArrayInputStream(data), 11); - BufferedReader br = new BufferedReader(new InputStreamReader(input))) - { - assertEquals("Hello World", br.readLine()); - assertEquals(null, br.readLine()); - } - } - -}