You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2016/11/29 21:28:41 UTC
[2/2] commons-compress git commit: COMPRESS-374 support writing LZMA
in 7z archives
COMPRESS-374 support writing LZMA in 7z archives
Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/9238eab6
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/9238eab6
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/9238eab6
Branch: refs/heads/master
Commit: 9238eab678395743bce4bd273c4534d10f77f715
Parents: e8cee81
Author: Stefan Bodewig <bo...@apache.org>
Authored: Tue Nov 29 22:27:58 2016 +0100
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Tue Nov 29 22:27:58 2016 +0100
----------------------------------------------------------------------
src/changes/changes.xml | 4 +
.../compress/archivers/sevenz/Coders.java | 16 ---
.../compress/archivers/sevenz/LZMADecoder.java | 121 +++++++++++++++++++
src/site/xdoc/examples.xml | 10 +-
src/site/xdoc/index.xml | 5 +-
src/site/xdoc/limitations.xml | 7 +-
.../compress/archivers/SevenZTestCase.java | 5 +
.../sevenz/SevenZMethodConfigurationTest.java | 18 +++
.../archivers/sevenz/SevenZOutputFileTest.java | 16 +++
9 files changed, 176 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c7d67ca..e25e4c6 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -76,6 +76,10 @@ The <action> type attribute can be add,update,fix,remove.
Add write support for the legacy LZMA format, this requires XZ
for Java 1.6.
</action>
+ <action issue="COMPRESS-374" type="add" date="2016-11-29">
+ Add write support for the legacy LZMA stream to 7z, this
+ requires XZ for Java 1.6.
+ </action>
</release>
<release version="1.12" date="2016-06-21"
description="Release 1.12 - API compatible to 1.11 but requires Java 6 at runtime.
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java
index 1d7244b..b36895c 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java
@@ -99,22 +99,6 @@ class Coders {
}
}
- static class LZMADecoder extends CoderBase {
- @Override
- InputStream decode(final String archiveName, final InputStream in, final long uncompressedLength,
- final Coder coder, final byte[] password) throws IOException {
- final byte propsByte = coder.properties[0];
- long dictSize = coder.properties[1];
- for (int i = 1; i < 4; i++) {
- dictSize |= (coder.properties[i + 1] & 0xffl) << (8 * i);
- }
- if (dictSize > LZMAInputStream.DICT_SIZE_MAX) {
- throw new IOException("Dictionary larger than 4GiB maximum size used in " + archiveName);
- }
- return new LZMAInputStream(in, uncompressedLength, propsByte, (int) dictSize);
- }
- }
-
static class BCJDecoder extends CoderBase {
private final FilterOptions opts;
BCJDecoder(final FilterOptions opts) {
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java
new file mode 100644
index 0000000..78e1fc8
--- /dev/null
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMADecoder.java
@@ -0,0 +1,121 @@
+/*
+ * 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.sevenz;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.tukaani.xz.LZMA2Options;
+import org.tukaani.xz.LZMAInputStream;
+import org.tukaani.xz.LZMAOutputStream;
+import org.tukaani.xz.UnsupportedOptionsException;
+
+class LZMADecoder extends CoderBase {
+ LZMADecoder() {
+ super(LZMA2Options.class, Number.class);
+ }
+
+ @Override
+ InputStream decode(final String archiveName, final InputStream in, final long uncompressedLength,
+ final Coder coder, final byte[] password) throws IOException {
+ final byte propsByte = coder.properties[0];
+ final int dictSize = getDictionarySize(coder);
+ if (dictSize > LZMAInputStream.DICT_SIZE_MAX) {
+ throw new IOException("Dictionary larger than 4GiB maximum size used in " + archiveName);
+ }
+ return new LZMAInputStream(in, uncompressedLength, propsByte, (int) dictSize);
+ }
+
+ @Override
+ OutputStream encode(final OutputStream out, final Object opts)
+ throws IOException {
+ return new FilterOutputStream(new LZMAOutputStream(out, getOptions(opts), false)) {
+ @Override
+ public void flush() {
+ // NOOP as LZMAOutputStream throws an exception in flush
+ }
+ };
+ }
+
+ @Override
+ byte[] getOptionsAsProperties(final Object opts) {
+ final LZMA2Options options = getOptions(opts);
+ final byte props = (byte) ((options.getPb() * 5 + options.getLp()) * 9 + options.getLc());
+ int dictSize = options.getDictSize();
+ return new byte[] {
+ props,
+ (byte) (dictSize & 0xff),
+ (byte) ((dictSize >> 8) & 0xff),
+ (byte) ((dictSize >> 16) & 0xff),
+ (byte) ((dictSize >> 24) & 0xff),
+ };
+ }
+
+ @Override
+ Object getOptionsFromCoder(final Coder coder, final InputStream in) {
+ try {
+ final byte propsByte = coder.properties[0];
+ int props = propsByte & 0xFF;
+ int pb = props / (9 * 5);
+ props -= pb * 9 * 5;
+ int lp = props / 9;
+ int lc = props - lp * 9;
+ LZMA2Options opts = new LZMA2Options();
+ opts.setPb(pb);
+ opts.setLcLp(lc, lp);
+ opts.setDictSize(getDictionarySize(coder));
+ return opts;
+ } catch (UnsupportedOptionsException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private int getDictSize(final Object opts) {
+ if (opts instanceof LZMA2Options) {
+ return ((LZMA2Options) opts).getDictSize();
+ }
+ return numberOptionOrDefault(opts);
+ }
+
+ private int getDictionarySize(final Coder coder) throws IllegalArgumentException {
+ long dictSize = coder.properties[1];
+ for (int i = 1; i < 4; i++) {
+ dictSize |= (coder.properties[i + 1] & 0xffl) << (8 * i);
+ }
+ return (int) dictSize;
+ }
+
+ private LZMA2Options getOptions(final Object opts) {
+ if (opts instanceof LZMA2Options) {
+ return (LZMA2Options) opts;
+ }
+ final LZMA2Options options = new LZMA2Options();
+ try {
+ options.setDictSize(numberOptionOrDefault(opts));
+ } catch (UnsupportedOptionsException ex) {
+ throw new RuntimeException(ex);
+ }
+ return options;
+ }
+
+ private int numberOptionOrDefault(final Object opts) {
+ return numberOptionOrDefault(opts, LZMA2Options.DICT_SIZE_DEFAULT);
+ }
+}
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/site/xdoc/examples.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/examples.xml b/src/site/xdoc/examples.xml
index a0b1059..c894d36 100644
--- a/src/site/xdoc/examples.xml
+++ b/src/site/xdoc/examples.xml
@@ -556,11 +556,11 @@ defIn.close();
<subsection name="7z">
- <p>Note that Commons Compress currently only supports
- a subset of compression and encryption algorithms used for 7z
- archives. For writing only uncompressed entries,
- LZMA2, BZIP2 and Deflate are supported - reading also supports
- LZMA and AES-256/SHA-256.</p>
+ <p>Note that Commons Compress currently only supports a subset
+ of compression and encryption algorithms used for 7z archives.
+ For writing only uncompressed entries, LZMA, LZMA2, BZIP2 and
+ Deflate are supported - reading also supports
+ AES-256/SHA-256.</p>
<p>Multipart archives are not supported at all.</p>
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/site/xdoc/index.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
index 6e8b626..7280ccb 100644
--- a/src/site/xdoc/index.xml
+++ b/src/site/xdoc/index.xml
@@ -79,8 +79,9 @@
needed. This allows archives to be read from inputs and
written to outputs that are seekable but are not
represented by <code>File</code>s.</li>
- <li>Added support for writing the legacy LZMA format -
- this requires XZ for Java 1.6.</li>
+ <li>Added support for writing the legacy LZMA format as
+ compressor stream and inside 7z archives - this requires
+ XZ for Java 1.6.</li>
</ul>
</subsection>
</section>
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/site/xdoc/limitations.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/limitations.xml b/src/site/xdoc/limitations.xml
index bd60293..c5c2be4 100644
--- a/src/site/xdoc/limitations.xml
+++ b/src/site/xdoc/limitations.xml
@@ -38,9 +38,10 @@
archives, starting with 1.8 it will throw a
<code>StreamingNotSupportedException</code> when reading from
a 7z archive.</li>
- <li>Encryption, solid compression, header compression and
- LZMA (not LZMA2) are only supported when reading
- archives</li>
+ <li>Encryption, solid compression and header compression and
+ are only supported when reading archives</li>
+ <li>Commons Compress 1.12 and earlier didn't support writing
+ LZMA.</li>
<li>Several of the "methods" supported by 7z are not
implemented in Compress.</li>
<li>No support for multi-volume archives</li>
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java b/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java
index 79e0019..d898be1 100644
--- a/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java
+++ b/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java
@@ -38,6 +38,11 @@ public class SevenZTestCase extends AbstractTestCase {
}
@Test
+ public void testSevenZArchiveCreationUsingLZMA() throws Exception {
+ testSevenZArchiveCreation(SevenZMethod.LZMA);
+ }
+
+ @Test
public void testSevenZArchiveCreationUsingLZMA2() throws Exception {
testSevenZArchiveCreation(SevenZMethod.LZMA2);
}
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZMethodConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZMethodConfigurationTest.java b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZMethodConfigurationTest.java
index 1a08880..20fccbd 100644
--- a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZMethodConfigurationTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZMethodConfigurationTest.java
@@ -30,6 +30,19 @@ public class SevenZMethodConfigurationTest {
}
@Test
+ public void shouldAllowLZMA2OptionsForLZMA() {
+ Assert.assertNotNull(new SevenZMethodConfiguration(SevenZMethod.LZMA,
+ new LZMA2Options())
+ .getOptions());
+ }
+
+ @Test
+ public void shouldAllowNumberForLZMA() {
+ Assert.assertNotNull(new SevenZMethodConfiguration(SevenZMethod.LZMA, 42)
+ .getOptions());
+ }
+
+ @Test
public void shouldAllowLZMA2OptionsForLZMA2() {
Assert.assertNotNull(new SevenZMethodConfiguration(SevenZMethod.LZMA2,
new LZMA2Options())
@@ -55,6 +68,11 @@ public class SevenZMethodConfigurationTest {
}
@Test(expected = IllegalArgumentException.class)
+ public void shouldNotAllowStringOptionsForLZMA() {
+ new SevenZMethodConfiguration(SevenZMethod.LZMA, "");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
public void shouldNotAllowStringOptionsForLZMA2() {
new SevenZMethodConfiguration(SevenZMethod.LZMA2, "");
}
http://git-wip-us.apache.org/repos/asf/commons-compress/blob/9238eab6/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
index aee1e02..feb988a 100644
--- a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
@@ -328,6 +328,22 @@ public class SevenZOutputFileTest extends AbstractTestCase {
}
@Test
+ public void testLzmaWithIntConfiguration() throws Exception {
+ output = new File(dir, "lzma-options.7z");
+ // 1 MB dictionary
+ createAndReadBack(output, Collections
+ .singletonList(new SevenZMethodConfiguration(SevenZMethod.LZMA, 1 << 20)));
+ }
+
+ @Test
+ public void testLzmaWithOptionsConfiguration() throws Exception {
+ output = new File(dir, "lzma-options2.7z");
+ final LZMA2Options opts = new LZMA2Options(1);
+ createAndReadBack(output, Collections
+ .singletonList(new SevenZMethodConfiguration(SevenZMethod.LZMA, opts)));
+ }
+
+ @Test
public void testLzma2WithIntConfiguration() throws Exception {
output = new File(dir, "lzma2-options.7z");
// 1 MB dictionary