Author: bodewig Date: Wed Nov 2 16:13:41 2011 New Revision: 1196665 URL: http://svn.apache.org/viewvc?rev=1196665&view=rev Log: support for XZ compression format submitted by Lasse Collin. COMPRESS-156
Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorInputStream.java (with props) commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorOutputStream.java (with props) Modified: commons/proper/compress/trunk/pom.xml commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java Modified: commons/proper/compress/trunk/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/pom.xml?rev=1196665&r1=1196664&r2=1196665&view=diff ============================================================================== --- commons/proper/compress/trunk/pom.xml (original) +++ commons/proper/compress/trunk/pom.xml Wed Nov 2 16:13:41 2011 @@ -56,6 +56,11 @@ <version>4.10</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.tukaani</groupId> + <artifactId>xz</artifactId> + <version>1.0</version> + </dependency> </dependencies> <developers> Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java?rev=1196665&r1=1196664&r2=1196665&view=diff ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java (original) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java Wed Nov 2 16:13:41 2011 @@ -26,6 +26,8 @@ import org.apache.commons.compress.compr import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; +import org.apache.commons.compress.compressors.xz.XZCompressorInputStream; +import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream; import org.apache.commons.compress.compressors.pack200.Pack200CompressorInputStream; import org.apache.commons.compress.compressors.pack200.Pack200CompressorOutputStream; @@ -62,6 +64,7 @@ public class CompressorStreamFactory { * @since Commons Compress 1.1 */ public static final String BZIP2 = "bzip2"; + /** * Constant used to identify the GZIP compression algorithm. * @since Commons Compress 1.1 @@ -74,6 +77,12 @@ public class CompressorStreamFactory { public static final String PACK200 = "pack200"; /** + * Constant used to identify the XZ compression method. + * @since Commons Compress 1.4 + */ + public static final String XZ = "xz"; + + /** * Create an compressor input stream from an input stream, autodetecting * the compressor type from the first few bytes of the stream. The InputStream * must support marks, like BufferedInputStream. @@ -108,6 +117,10 @@ public class CompressorStreamFactory { return new GzipCompressorInputStream(in); } + if (XZCompressorInputStream.matches(signature, signatureLength)) { + return new XZCompressorInputStream(in); + } + if (Pack200CompressorInputStream.matches(signature, signatureLength)) { return new Pack200CompressorInputStream(in); } @@ -122,7 +135,7 @@ public class CompressorStreamFactory { /** * Create a compressor input stream from a compressor name and an input stream. * - * @param name of the compressor, i.e. "gz", "bzip2" or "pack200" + * @param name of the compressor, i.e. "gz", "bzip2", "xz", or "pack200" * @param in the input stream * @return compressor input stream * @throws CompressorException if the compressor name is not known @@ -145,6 +158,10 @@ public class CompressorStreamFactory { return new BZip2CompressorInputStream(in); } + if (XZ.equalsIgnoreCase(name)) { + return new XZCompressorInputStream(in); + } + if (PACK200.equalsIgnoreCase(name)) { return new Pack200CompressorInputStream(in); } @@ -159,7 +176,7 @@ public class CompressorStreamFactory { /** * Create an compressor output stream from an compressor name and an input stream. * - * @param name the compressor name, i.e. "gz", "bzip2" or "pack200" + * @param name the compressor name, i.e. "gz", "bzip2", "xz", or "pack200" * @param out the output stream * @return the compressor output stream * @throws CompressorException if the archiver name is not known @@ -183,6 +200,10 @@ public class CompressorStreamFactory { return new BZip2CompressorOutputStream(out); } + if (XZ.equalsIgnoreCase(name)) { + return new XZCompressorOutputStream(out); + } + if (PACK200.equalsIgnoreCase(name)) { return new Pack200CompressorOutputStream(out); } Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorInputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorInputStream.java?rev=1196665&view=auto ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorInputStream.java (added) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorInputStream.java Wed Nov 2 16:13:41 2011 @@ -0,0 +1,125 @@ +/* + * 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.xz; + +import java.io.IOException; +import java.io.InputStream; +import org.tukaani.xz.XZ; +import org.tukaani.xz.SingleXZInputStream; +import org.tukaani.xz.XZInputStream; + +import org.apache.commons.compress.compressors.CompressorInputStream; + +/** + * XZ decompressor. + * @since Commons Compress 1.4 + */ +public class XZCompressorInputStream extends CompressorInputStream { + private final InputStream in; + + /** + * Checks if the signature matches what is expected for a .xz file. + * + * @param signature the bytes to check + * @param length the number of bytes to check + * @return true if signature matches the .xz magic bytes, false otherwise + */ + public static boolean matches(byte[] signature, int length) { + if (length < XZ.HEADER_MAGIC.length) + return false; + + for (int i = 0; i < XZ.HEADER_MAGIC.length; ++i) + if (signature[i] != XZ.HEADER_MAGIC[i]) + return false; + + return true; + } + + /** + * Creates a new input stream that decompresses XZ-compressed data + * from the specified input stream. This supports concatenated .xz files. + * + * @param inputStream where to read the compressed data + * + * @throws IOException if the input is not in the .xz format, + * the input is corrupt or truncated, the .xz + * headers specify options that are not supported + * by this implementation, or the underlying + * <code>inputStream</code> throws an exception + */ + public XZCompressorInputStream(InputStream inputStream) + throws IOException { + this(inputStream, true); + } + + /** + * Creates a new input stream that decompresses XZ-compressed data + * from the specified input stream. + * + * @param inputStream where to read the compressed data + * @param decompressConcatenated + * if true, decompress until the end of the + * input; if false, stop after the first .xz + * stream and leave the input position to point + * to the next byte after the .xz stream + * + * @throws IOException if the input is not in the .xz format, + * the input is corrupt or truncated, the .xz + * headers specify options that are not supported + * by this implementation, or the underlying + * <code>inputStream</code> throws an exception + */ + public XZCompressorInputStream(InputStream inputStream, + boolean decompressConcatenated) + throws IOException { + if (decompressConcatenated) + in = new XZInputStream(inputStream); + else + in = new SingleXZInputStream(inputStream); + } + + /** {@inheritDoc} */ + public int read() throws IOException { + int ret = in.read(); + count(ret == -1 ? -1 : 1); + return ret; + } + + /** {@inheritDoc} */ + public int read(byte[] buf, int off, int len) throws IOException { + int ret = in.read(buf, off, len); + count(ret); + return ret; + } + + /** {@inheritDoc} */ + public long skip(long n) throws IOException { + return in.skip(n); + } + + /** {@inheritDoc} */ + public int available() throws IOException { + return in.available(); + } + + /** {@inheritDoc} */ + public void close() throws IOException { + in.close(); + } +} Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorInputStream.java ------------------------------------------------------------------------------ svn:eol-style = native Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorOutputStream.java URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorOutputStream.java?rev=1196665&view=auto ============================================================================== --- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorOutputStream.java (added) +++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorOutputStream.java Wed Nov 2 16:13:41 2011 @@ -0,0 +1,94 @@ +/* + * 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.xz; + +import java.io.IOException; +import java.io.OutputStream; +import org.tukaani.xz.LZMA2Options; +import org.tukaani.xz.XZOutputStream; + +import org.apache.commons.compress.compressors.CompressorOutputStream; + +/** + * XZ compressor. + * @since Commons Compress 1.4 + */ +public class XZCompressorOutputStream extends CompressorOutputStream { + private final XZOutputStream out; + + /** + * Creates a new XZ compressor using the default LZMA2 options. + * This is equivalent to <code>XZCompressorOutputStream(6)</code>. + */ + public XZCompressorOutputStream(OutputStream outputStream) + throws IOException { + out = new XZOutputStream(outputStream, new LZMA2Options()); + } + + /** + * Creates a new XZ compressor using the specified LZMA2 preset level. + * <p> + * The presets 0-3 are fast presets with medium compression. + * The presets 4-6 are fairly slow presets with high compression. + * The default preset is 6. + * <p> + * The presets 7-9 are like the preset 6 but use bigger dictionaries + * and have higher compressor and decompressor memory requirements. + * Unless the uncompressed size of the file exceeds 8 MiB, + * 16 MiB, or 32 MiB, it is waste of memory to use the + * presets 7, 8, or 9, respectively. + */ + public XZCompressorOutputStream(OutputStream outputStream, int preset) + throws IOException { + out = new XZOutputStream(outputStream, new LZMA2Options(preset)); + } + + /** {@inheritDoc} */ + public void write(int b) throws IOException { + out.write(b); + } + + /** {@inheritDoc} */ + public void write(byte[] buf, int off, int len) throws IOException { + out.write(buf, off, len); + } + + /** + * Flushes the encoder and calls <code>outputStream.flush()</code>. + * All buffered pending data will then be decompressible from + * the output stream. Calling this function very often may increase + * the compressed file size a lot. + */ + public void flush() throws IOException { + out.flush(); + } + + /** + * Finishes compression without closing the underlying stream. + * No more data can be written to this stream after finishing. + */ + public void finish() throws IOException { + out.finish(); + } + + /** {@inheritDoc} */ + public void close() throws IOException { + out.close(); + } +} Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/compressors/xz/XZCompressorOutputStream.java ------------------------------------------------------------------------------ svn:eol-style = native