Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6DFF610BBA for ; Fri, 11 Oct 2013 11:14:59 +0000 (UTC) Received: (qmail 43886 invoked by uid 500); 11 Oct 2013 11:14:58 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 43559 invoked by uid 500); 11 Oct 2013 11:14:57 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 43546 invoked by uid 99); 11 Oct 2013 11:14:57 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Oct 2013 11:14:57 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Oct 2013 11:14:53 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id EB5C62388906; Fri, 11 Oct 2013 11:14:31 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1531251 - in /commons/proper/compress/trunk/src: main/java/org/apache/commons/compress/archivers/sevenz/ test/java/org/apache/commons/compress/archivers/ Date: Fri, 11 Oct 2013 11:14:31 -0000 To: commits@commons.apache.org From: bodewig@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20131011111431.EB5C62388906@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: bodewig Date: Fri Oct 11 11:14:31 2013 New Revision: 1531251 URL: http://svn.apache.org/r1531251 Log: LZMA2 compression when writing 7z archives Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java (with props) Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZMethod.java commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java?rev=1531251&r1=1531250&r2=1531251&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/Coders.java Fri Oct 11 11:14:31 2013 @@ -39,7 +39,6 @@ import javax.crypto.spec.SecretKeySpec; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; import org.tukaani.xz.LZMAInputStream; -import org.tukaani.xz.LZMA2InputStream; class Coders { static InputStream addDecoder(final InputStream is, @@ -103,27 +102,6 @@ class Coders { } } - static class LZMA2Decoder extends CoderBase { - @Override - InputStream decode(final InputStream in, final Coder coder, - String password) throws IOException { - final int dictionarySizeBits = 0xff & coder.properties[0]; - if ((dictionarySizeBits & (~0x3f)) != 0) { - throw new IOException("Unsupported LZMA2 property bits"); - } - if (dictionarySizeBits > 40) { - throw new IOException("Dictionary larger than 4GiB maximum size"); - } - final int dictionarySize; - if (dictionarySizeBits == 40) { - dictionarySize = 0xFFFFffff; - } else { - dictionarySize = (2 | (dictionarySizeBits & 0x1)) << (dictionarySizeBits / 2 + 11); - } - return new LZMA2InputStream(in, dictionarySize); - } - } - static class LZMADecoder extends CoderBase { @Override InputStream decode(final InputStream in, final Coder coder, Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java?rev=1531251&view=auto ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java (added) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java Fri Oct 11 11:14:31 2013 @@ -0,0 +1,70 @@ +/* + * 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.FinishableWrapperOutputStream; +import org.tukaani.xz.FinishableOutputStream; +import org.tukaani.xz.LZMA2InputStream; +import org.tukaani.xz.LZMA2Options; + +class LZMA2Decoder extends Coders.CoderBase { + @Override + InputStream decode(final InputStream in, final Coder coder, String password) + throws IOException { + final int dictionarySizeBits = 0xff & coder.properties[0]; + if ((dictionarySizeBits & (~0x3f)) != 0) { + throw new IOException("Unsupported LZMA2 property bits"); + } + if (dictionarySizeBits > 40) { + throw new IOException("Dictionary larger than 4GiB maximum size"); + } + final int dictionarySize; + if (dictionarySizeBits == 40) { + dictionarySize = 0xFFFFffff; + } else { + dictionarySize = (2 | (dictionarySizeBits & 0x1)) << (dictionarySizeBits / 2 + 11); + } + return new LZMA2InputStream(in, dictionarySize); + } + + @Override + OutputStream encode(final OutputStream out, final String password) + throws IOException { + LZMA2Options options = new LZMA2Options(); + options.setDictSize(LZMA2Options.DICT_SIZE_DEFAULT); + FinishableOutputStream wrapped = new FinishableWrapperOutputStream(out); + return new FinishOnCloseStream(options.getOutputStream(wrapped)); + } + + private static class FinishOnCloseStream extends FilterOutputStream { + + private FinishOnCloseStream(FinishableOutputStream out) { + super(out); + } + + @Override + public void close() throws IOException { + ((FinishableOutputStream) out).finish(); + super.close(); + } + } +} Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/LZMA2Decoder.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZMethod.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZMethod.java?rev=1531251&r1=1531250&r2=1531251&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZMethod.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZMethod.java Fri Oct 11 11:14:31 2013 @@ -17,6 +17,8 @@ */ package org.apache.commons.compress.archivers.sevenz; +import org.tukaani.xz.LZMA2Options; + /** * The (partially) supported compression/encryption methods used in 7z archives. */ @@ -25,11 +27,21 @@ public enum SevenZMethod { COPY(new byte[] { (byte)0x00 }), /** LZMA - only supported when reading */ LZMA(new byte[] { (byte)0x03, (byte)0x01, (byte)0x01 }), - /** LZMA2 - only supported when reading */ - LZMA2(new byte[] { (byte)0x21 }), - /** Deflate - only supported when reading */ + /** LZMA2 */ + LZMA2(new byte[] { (byte)0x21 }) { + @Override + byte[] getProperties() { + int dictSize = LZMA2Options.DICT_SIZE_DEFAULT; + int lead = Integer.numberOfLeadingZeros(dictSize); + int secondBit = (dictSize >>> (30 - lead)) - 2; + return new byte[] { + (byte) ((19 - lead) * 2 + secondBit) + }; + } + }, + /** Deflate */ DEFLATE(new byte[] { (byte)0x04, (byte)0x01, (byte)0x08 }), - /** BZIP2 - only supported when reading */ + /** BZIP2 */ BZIP2(new byte[] { (byte)0x04, (byte)0x02, (byte)0x02 }), /** * AES encryption with a key length of 256 bit using SHA256 for @@ -49,4 +61,8 @@ public enum SevenZMethod { return copy; } + byte[] getProperties() { + return new byte[0]; + } + } Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java?rev=1531251&r1=1531250&r2=1531251&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFile.java Fri Oct 11 11:14:31 2013 @@ -46,7 +46,7 @@ public class SevenZOutputFile { private long fileBytesWritten = 0; private boolean finished = false; private CountingOutputStream currentOutputStream; - private SevenZMethod contentCompression = SevenZMethod.COPY; + private SevenZMethod contentCompression = SevenZMethod.LZMA2; public SevenZOutputFile(final File filename) throws IOException { file = new RandomAccessFile(filename, "rw"); @@ -312,9 +312,19 @@ public class SevenZOutputFile { // one coder writeUint64(header, 1); byte[] id = contentCompression.getId(); - // FIXME - deal with coder properties - header.write(id.length); + byte[] properties = contentCompression.getProperties(); + + int codecFlags = id.length; + if (properties.length > 0) { + codecFlags |= 0x20; + } + header.write(codecFlags); header.write(id); + + if (properties.length > 0) { + header.write(properties.length); + header.write(properties); + } } private void writeSubStreamsInfo(final DataOutput header) throws IOException { Modified: commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java?rev=1531251&r1=1531250&r2=1531251&view=diff ============================================================================== --- commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java (original) +++ commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/SevenZTestCase.java Fri Oct 11 11:14:31 2013 @@ -33,6 +33,10 @@ public class SevenZTestCase extends Abst testSevenZArchiveCreation(SevenZMethod.COPY); } + public void testSevenZArchiveCreationUsingLZMA2() throws Exception { + testSevenZArchiveCreation(SevenZMethod.LZMA2); + } + public void testSevenZArchiveCreationUsingBZIP2() throws Exception { testSevenZArchiveCreation(SevenZMethod.BZIP2); }