commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bode...@apache.org
Subject [2/2] commons-compress git commit: COMPRESS-374 support writing LZMA in 7z archives
Date Tue, 29 Nov 2016 21:28:41 GMT
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 <bodewig@apache.org>
Authored: Tue Nov 29 22:27:58 2016 +0100
Committer: Stefan Bodewig <bodewig@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


Mime
View raw message