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    
019    package org.apache.hadoop.io.compress;
020    
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.OutputStream;
024    
025    import org.apache.hadoop.classification.InterfaceAudience;
026    import org.apache.hadoop.classification.InterfaceStability;
027    import org.apache.hadoop.conf.Configuration;
028    
029    /**
030     * This class encapsulates a streaming compression/decompression pair.
031     */
032    @InterfaceAudience.Public
033    @InterfaceStability.Evolving
034    public 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    }