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 import org.apache.commons.compress.compressors.pack200.Pack200CompressorInputStream;
030 import org.apache.commons.compress.compressors.pack200.Pack200CompressorOutputStream;
031
032 /**
033 * <p>Factory to create Compressor[In|Out]putStreams from names. To add other
034 * implementations you should extend CompressorStreamFactory and override the
035 * appropriate methods (and call their implementation from super of course).</p>
036 *
037 * Example (Compressing a file):
038 *
039 * <pre>
040 * final OutputStream out = new FileOutputStream(output);
041 * CompressorOutputStream cos =
042 * new CompressorStreamFactory().createCompressorOutputStream(CompressorStreamFactory.BZIP2, out);
043 * IOUtils.copy(new FileInputStream(input), cos);
044 * cos.close();
045 * </pre>
046 *
047 * Example (Compressing a file):
048 * <pre>
049 * final InputStream is = new FileInputStream(input);
050 * CompressorInputStream in =
051 * new CompressorStreamFactory().createCompressorInputStream(CompressorStreamFactory.BZIP2, is);
052 * IOUtils.copy(in, new FileOutputStream(output));
053 * in.close();
054 * </pre>
055 *
056 * @Immutable
057 */
058 public class CompressorStreamFactory {
059
060 /**
061 * Constant used to identify the BZIP2 compression algorithm.
062 * @since Commons Compress 1.1
063 */
064 public static final String BZIP2 = "bzip2";
065 /**
066 * Constant used to identify the GZIP compression algorithm.
067 * @since Commons Compress 1.1
068 */
069 public static final String GZIP = "gz";
070 /**
071 * Constant used to identify the PACK200 compression algorithm.
072 * @since Commons Compress 1.3
073 */
074 public static final String PACK200 = "pack200";
075
076 /**
077 * Create an compressor input stream from an input stream, autodetecting
078 * the compressor type from the first few bytes of the stream. The InputStream
079 * must support marks, like BufferedInputStream.
080 *
081 * @param in the input stream
082 * @return the compressor input stream
083 * @throws CompressorException if the compressor name is not known
084 * @throws IllegalArgumentException if the stream is null or does not support mark
085 * @since Commons Compress 1.1
086 */
087 public CompressorInputStream createCompressorInputStream(final InputStream in)
088 throws CompressorException {
089 if (in == null) {
090 throw new IllegalArgumentException("Stream must not be null.");
091 }
092
093 if (!in.markSupported()) {
094 throw new IllegalArgumentException("Mark is not supported.");
095 }
096
097 final byte[] signature = new byte[12];
098 in.mark(signature.length);
099 try {
100 int signatureLength = in.read(signature);
101 in.reset();
102
103 if (BZip2CompressorInputStream.matches(signature, signatureLength)) {
104 return new BZip2CompressorInputStream(in);
105 }
106
107 if (GzipCompressorInputStream.matches(signature, signatureLength)) {
108 return new GzipCompressorInputStream(in);
109 }
110
111 if (Pack200CompressorInputStream.matches(signature, signatureLength)) {
112 return new Pack200CompressorInputStream(in);
113 }
114
115 } catch (IOException e) {
116 throw new CompressorException("Failed to detect Compressor from InputStream.", e);
117 }
118
119 throw new CompressorException("No Compressor found for the stream signature.");
120 }
121
122 /**
123 * Create a compressor input stream from a compressor name and an input stream.
124 *
125 * @param name of the compressor, i.e. "gz", "bzip2" or "pack200"
126 * @param in the input stream
127 * @return compressor input stream
128 * @throws CompressorException if the compressor name is not known
129 * @throws IllegalArgumentException if the name or input stream is null
130 */
131 public CompressorInputStream createCompressorInputStream(final String name,
132 final InputStream in) throws CompressorException {
133 if (name == null || in == null) {
134 throw new IllegalArgumentException(
135 "Compressor name and stream must not be null.");
136 }
137
138 try {
139
140 if (GZIP.equalsIgnoreCase(name)) {
141 return new GzipCompressorInputStream(in);
142 }
143
144 if (BZIP2.equalsIgnoreCase(name)) {
145 return new BZip2CompressorInputStream(in);
146 }
147
148 if (PACK200.equalsIgnoreCase(name)) {
149 return new Pack200CompressorInputStream(in);
150 }
151
152 } catch (IOException e) {
153 throw new CompressorException(
154 "Could not create CompressorInputStream.", e);
155 }
156 throw new CompressorException("Compressor: " + name + " not found.");
157 }
158
159 /**
160 * Create an compressor output stream from an compressor name and an input stream.
161 *
162 * @param name the compressor name, i.e. "gz", "bzip2" or "pack200"
163 * @param out the output stream
164 * @return the compressor output stream
165 * @throws CompressorException if the archiver name is not known
166 * @throws IllegalArgumentException if the archiver name or stream is null
167 */
168 public CompressorOutputStream createCompressorOutputStream(
169 final String name, final OutputStream out)
170 throws CompressorException {
171 if (name == null || out == null) {
172 throw new IllegalArgumentException(
173 "Compressor name and stream must not be null.");
174 }
175
176 try {
177
178 if (GZIP.equalsIgnoreCase(name)) {
179 return new GzipCompressorOutputStream(out);
180 }
181
182 if (BZIP2.equalsIgnoreCase(name)) {
183 return new BZip2CompressorOutputStream(out);
184 }
185
186 if (PACK200.equalsIgnoreCase(name)) {
187 return new Pack200CompressorOutputStream(out);
188 }
189
190 } catch (IOException e) {
191 throw new CompressorException(
192 "Could not create CompressorOutputStream", e);
193 }
194 throw new CompressorException("Compressor: " + name + " not found.");
195 }
196 }