    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one
    003     * or more contributor license agreements.  See the NOTICE file
    004     * distributed with this work for additional information
    005     * regarding copyright ownership.  The ASF licenses this file
    006     * to you under the Apache License, Version 2.0 (the
    007     * "License"); you may not use this file except in compliance
    008     * with the License.  You may obtain a copy of the License at
    009     *
    010     * http://www.apache.org/licenses/LICENSE-2.0
    011     *
    012     * Unless required by applicable law or agreed to in writing,
    013     * software distributed under the License is distributed on an
    014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015     * KIND, either express or implied.  See the License for the
    016     * specific language governing permissions and limitations
    017     * under the License.
    018     */
    019    package org.apache.commons.compress.compressors;
    020
    021    import java.io.IOException;
    022    import java.io.InputStream;
    023    import java.io.OutputStream;
    024
    025    import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
    026    import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
    027    import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
    028    import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
    029
    030    /**
    031     * <p>Factory to create Compressor[In|Out]putStreams from names. To add other
    032     * implementations you should extend CompressorStreamFactory and override the
    033     * appropriate methods (and call their implementation from super of course).</p>
    034     *
    035     * Example (Compressing a file):
    036     *
    037     * <pre>
    038     * final OutputStream out = new FileOutputStream(output);
    039     * CompressorOutputStream cos =
    040     *      new CompressorStreamFactory().createCompressorOutputStream(CompressorStreamFactory.BZIP2, out);
    041     * IOUtils.copy(new FileInputStream(input), cos);
    042     * cos.close();
    043     * </pre>
    044     *
    045     * Example (Compressing a file):
    046     * <pre>
    047     * final InputStream is = new FileInputStream(input);
    048     * CompressorInputStream in =
    049     *      new CompressorStreamFactory().createCompressorInputStream(CompressorStreamFactory.BZIP2, is);
    050     * IOUtils.copy(in, new FileOutputStream(output));
    051     * in.close();
    052     * </pre>
    053     *
    054     * @Immutable
    055     */
    056    public class CompressorStreamFactory {
    057
    058        /**
    059         * Constant used to identify the BZIP2 compression algorithm.
    060         * @since Commons Compress 1.1
    061         */
    062        public static final String BZIP2 = "bzip2";
    063        /**
    064         * Constant used to identify the GZIP compression algorithm.
    065         * @since Commons Compress 1.1
    066         */
    067        public static final String GZIP = "gz";
    068
    069        /**
    070         * Create an compressor input stream from an input stream, autodetecting
    071         * the compressor type from the first few bytes of the stream. The InputStream
    072         * must support marks, like BufferedInputStream.
    073         *
    074         * @param in the input stream
    075         * @return the compressor input stream
    076         * @throws CompressorException if the compressor name is not known
    077         * @throws IllegalArgumentException if the stream is null or does not support mark
    078         * @since Commons Compress 1.1
    079         */
    080        public CompressorInputStream createCompressorInputStream(final InputStream in)
    081                throws CompressorException {
    082            if (in == null) {
    083                throw new IllegalArgumentException("Stream must not be null.");
    084            }
    085
    086            if (!in.markSupported()) {
    087                throw new IllegalArgumentException("Mark is not supported.");
    088            }
    089
    090            final byte[] signature = new byte[12];
    091            in.mark(signature.length);
    092            try {
    093                int signatureLength = in.read(signature);
    094                in.reset();
    095
    096                if (BZip2CompressorInputStream.matches(signature, signatureLength)) {
    097                    return new BZip2CompressorInputStream(in);
    098                }
    099
    100                if (GzipCompressorInputStream.matches(signature, signatureLength)) {
    101                    return new GzipCompressorInputStream(in);
    102                }
    103
    104            } catch (IOException e) {
    105                throw new CompressorException("Failed to detect Compressor from InputStream.", e);
    106            }
    107
    108            throw new CompressorException("No Compressor found for the stream signature.");
    109        }
    110
    111        /**
    112         * Create a compressor input stream from a compressor name and an input stream.
    113         *
    114         * @param name of the compressor, i.e. "gz" or "bzip2"
    115         * @param in the input stream
    116         * @return compressor input stream
    117         * @throws CompressorException if the compressor name is not known
    118         * @throws IllegalArgumentException if the name or input stream is null
    119         */
    120        public CompressorInputStream createCompressorInputStream(final String name,
    121                final InputStream in) throws CompressorException {
    122            if (name == null || in == null) {
    123                throw new IllegalArgumentException(
    124                        "Compressor name and stream must not be null.");
    125            }
    126
    127            try {
    128
    129                if (GZIP.equalsIgnoreCase(name)) {
    130                    return new GzipCompressorInputStream(in);
    131                }
    132
    133                if (BZIP2.equalsIgnoreCase(name)) {
    134                    return new BZip2CompressorInputStream(in);
    135                }
    136
    137            } catch (IOException e) {
    138                throw new CompressorException(
    139                        "Could not create CompressorInputStream.", e);
    140            }
    141            throw new CompressorException("Compressor: " + name + " not found.");
    142        }
    143
    144        /**
    145         * Create an compressor output stream from an compressor name and an input stream.
    146         *
    147         * @param name the compressor name, i.e. "gz" or "bzip2"
    148         * @param out the output stream
    149         * @return the compressor output stream
    150         * @throws CompressorException if the archiver name is not known
    151         * @throws IllegalArgumentException if the archiver name or stream is null
    152         */
    153        public CompressorOutputStream createCompressorOutputStream(
    154                final String name, final OutputStream out)
    155                throws CompressorException {
    156            if (name == null || out == null) {
    157                throw new IllegalArgumentException(
    158                        "Compressor name and stream must not be null.");
    159            }
    160
    161            try {
    162
    163                if (GZIP.equalsIgnoreCase(name)) {
    164                    return new GzipCompressorOutputStream(out);
    165                }
    166
    167                if (BZIP2.equalsIgnoreCase(name)) {
    168                    return new BZip2CompressorOutputStream(out);
    169                }
    170
    171            } catch (IOException e) {
    172                throw new CompressorException(
    173                        "Could not create CompressorOutputStream", e);
    174            }
    175            throw new CompressorException("Compressor: " + name + " not found.");
    176        }
    177    }