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, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.io.compress;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.io.OutputStream;
024
025import org.apache.hadoop.classification.InterfaceAudience;
026import org.apache.hadoop.classification.InterfaceStability;
027import org.apache.hadoop.conf.Configuration;
028
029/**
030 * This class encapsulates a streaming compression/decompression pair.
031 */
032@InterfaceAudience.Public
033@InterfaceStability.Evolving
034public interface CompressionCodec {
035
036  /**
037   * Create a {@link CompressionOutputStream} that will write to the given 
038   * {@link OutputStream}.
039   * 
040   * @param out the location for the final output stream
041   * @return a stream the user can write uncompressed data to have it compressed
042   * @throws IOException
043   */
044  CompressionOutputStream createOutputStream(OutputStream out) 
045  throws IOException;
046  
047  /**
048   * Create a {@link CompressionOutputStream} that will write to the given 
049   * {@link OutputStream} with the given {@link Compressor}.
050   * 
051   * @param out the location for the final output stream
052   * @param compressor compressor to use
053   * @return a stream the user can write uncompressed data to have it compressed
054   * @throws IOException
055   */
056  CompressionOutputStream createOutputStream(OutputStream out, 
057                                             Compressor compressor) 
058  throws IOException;
059
060  /**
061   * Get the type of {@link Compressor} needed by this {@link CompressionCodec}.
062   * 
063   * @return the type of compressor needed by this codec.
064   */
065  Class<? extends Compressor> getCompressorType();
066  
067  /**
068   * Create a new {@link Compressor} for use by this {@link CompressionCodec}.
069   * 
070   * @return a new compressor for use by this codec
071   */
072  Compressor createCompressor();
073  
074  /**
075   * Create a {@link CompressionInputStream} that will read from the given
076   * input stream.
077   * 
078   * @param in the stream to read compressed bytes from
079   * @return a stream to read uncompressed bytes from
080   * @throws IOException
081   */
082  CompressionInputStream createInputStream(InputStream in) throws IOException;
083  
084  /**
085   * Create a {@link CompressionInputStream} that will read from the given 
086   * {@link InputStream} with the given {@link Decompressor}.
087   * 
088   * @param in the stream to read compressed bytes from
089   * @param decompressor decompressor to use
090   * @return a stream to read uncompressed bytes from
091   * @throws IOException
092   */
093  CompressionInputStream createInputStream(InputStream in, 
094                                           Decompressor decompressor) 
095  throws IOException;
096
097
098  /**
099   * Get the type of {@link Decompressor} needed by this {@link CompressionCodec}.
100   * 
101   * @return the type of decompressor needed by this codec.
102   */
103  Class<? extends Decompressor> getDecompressorType();
104  
105  /**
106   * Create a new {@link Decompressor} for use by this {@link CompressionCodec}.
107   * 
108   * @return a new decompressor for use by this codec
109   */
110  Decompressor createDecompressor();
111  
112  /**
113   * Get the default filename extension for this kind of compression.
114   * @return the extension including the '.'
115   */
116  String getDefaultExtension();
117
118  static class Util {
119    /**
120     * Create an output stream with a codec taken from the global CodecPool.
121     *
122     * @param codec       The codec to use to create the output stream.
123     * @param conf        The configuration to use if we need to create a new codec.
124     * @param out         The output stream to wrap.
125     * @return            The new output stream
126     * @throws IOException
127     */
128    static CompressionOutputStream createOutputStreamWithCodecPool(
129        CompressionCodec codec, Configuration conf, OutputStream out)
130        throws IOException {
131      Compressor compressor = CodecPool.getCompressor(codec, conf);
132      CompressionOutputStream stream = null;
133      try {
134        stream = codec.createOutputStream(out, compressor);
135      } finally {
136        if (stream == null) {
137          CodecPool.returnCompressor(compressor);
138        } else {
139          stream.setTrackedCompressor(compressor);
140        }
141      }
142      return stream;
143    }
144
145    /**
146     * Create an input stream with a codec taken from the global CodecPool.
147     *
148     * @param codec       The codec to use to create the input stream.
149     * @param conf        The configuration to use if we need to create a new codec.
150     * @param in          The input stream to wrap.
151     * @return            The new input stream
152     * @throws IOException
153     */
154    static CompressionInputStream createInputStreamWithCodecPool(
155        CompressionCodec codec,  Configuration conf, InputStream in)
156          throws IOException {
157      Decompressor decompressor = CodecPool.getDecompressor(codec);
158      CompressionInputStream stream = null;
159      try {
160        stream = codec.createInputStream(in, decompressor);
161      } finally {
162        if (stream == null) {
163          CodecPool.returnDecompressor(decompressor);
164        } else {
165          stream.setTrackedDecompressor(decompressor);
166        }
167      }
168      return stream;
169    }
170  }
171}