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.*;
022    import java.util.zip.GZIPOutputStream;
023    import java.util.zip.GZIPInputStream;
024    
025    import org.apache.hadoop.classification.InterfaceAudience;
026    import org.apache.hadoop.classification.InterfaceStability;
027    import org.apache.hadoop.conf.Configuration;
028    import org.apache.hadoop.io.compress.DefaultCodec;
029    import org.apache.hadoop.io.compress.zlib.*;
030    import org.apache.hadoop.io.compress.zlib.ZlibCompressor.CompressionLevel;
031    import org.apache.hadoop.io.compress.zlib.ZlibCompressor.CompressionStrategy;
032    
033    /**
034     * This class creates gzip compressors/decompressors. 
035     */
036    @InterfaceAudience.Public
037    @InterfaceStability.Evolving
038    public class GzipCodec extends DefaultCodec {
039      /**
040       * A bridge that wraps around a DeflaterOutputStream to make it 
041       * a CompressionOutputStream.
042       */
043      @InterfaceStability.Evolving
044      protected static class GzipOutputStream extends CompressorStream {
045    
046        private static class ResetableGZIPOutputStream extends GZIPOutputStream {
047          
048          public ResetableGZIPOutputStream(OutputStream out) throws IOException {
049            super(out);
050          }
051          
052          public void resetState() throws IOException {
053            def.reset();
054          }
055        }
056    
057        public GzipOutputStream(OutputStream out) throws IOException {
058          super(new ResetableGZIPOutputStream(out));
059        }
060        
061        /**
062         * Allow children types to put a different type in here.
063         * @param out the Deflater stream to use
064         */
065        protected GzipOutputStream(CompressorStream out) {
066          super(out);
067        }
068        
069        public void close() throws IOException {
070          out.close();
071        }
072        
073        public void flush() throws IOException {
074          out.flush();
075        }
076        
077        public void write(int b) throws IOException {
078          out.write(b);
079        }
080        
081        public void write(byte[] data, int offset, int length) 
082          throws IOException {
083          out.write(data, offset, length);
084        }
085        
086        public void finish() throws IOException {
087          ((ResetableGZIPOutputStream) out).finish();
088        }
089    
090        public void resetState() throws IOException {
091          ((ResetableGZIPOutputStream) out).resetState();
092        }
093      }
094    
095      public CompressionOutputStream createOutputStream(OutputStream out) 
096        throws IOException {
097        return (ZlibFactory.isNativeZlibLoaded(conf)) ?
098                   new CompressorStream(out, createCompressor(),
099                                        conf.getInt("io.file.buffer.size", 4*1024)) :
100                   new GzipOutputStream(out);
101      }
102      
103      public CompressionOutputStream createOutputStream(OutputStream out, 
104                                                        Compressor compressor) 
105      throws IOException {
106        return (compressor != null) ?
107                   new CompressorStream(out, compressor,
108                                        conf.getInt("io.file.buffer.size", 
109                                                    4*1024)) :
110                   createOutputStream(out);
111      }
112    
113      public Compressor createCompressor() {
114        return (ZlibFactory.isNativeZlibLoaded(conf))
115          ? new GzipZlibCompressor(conf)
116          : null;
117      }
118    
119      public Class<? extends Compressor> getCompressorType() {
120        return ZlibFactory.isNativeZlibLoaded(conf)
121          ? GzipZlibCompressor.class
122          : null;
123      }
124    
125      public CompressionInputStream createInputStream(InputStream in)
126      throws IOException {
127        return createInputStream(in, null);
128      }
129    
130      public CompressionInputStream createInputStream(InputStream in,
131                                                      Decompressor decompressor)
132      throws IOException {
133        if (decompressor == null) {
134          decompressor = createDecompressor();  // always succeeds (or throws)
135        }
136        return new DecompressorStream(in, decompressor,
137                                      conf.getInt("io.file.buffer.size", 4*1024));
138      }
139    
140      public Decompressor createDecompressor() {
141        return (ZlibFactory.isNativeZlibLoaded(conf))
142          ? new GzipZlibDecompressor()
143          : new BuiltInGzipDecompressor();
144      }
145    
146      public Class<? extends Decompressor> getDecompressorType() {
147        return ZlibFactory.isNativeZlibLoaded(conf)
148          ? GzipZlibDecompressor.class
149          : BuiltInGzipDecompressor.class;
150      }
151    
152      public String getDefaultExtension() {
153        return ".gz";
154      }
155    
156      static final class GzipZlibCompressor extends ZlibCompressor {
157        public GzipZlibCompressor() {
158          super(ZlibCompressor.CompressionLevel.DEFAULT_COMPRESSION,
159              ZlibCompressor.CompressionStrategy.DEFAULT_STRATEGY,
160              ZlibCompressor.CompressionHeader.GZIP_FORMAT, 64*1024);
161        }
162        
163        public GzipZlibCompressor(Configuration conf) {
164          super(ZlibFactory.getCompressionLevel(conf),
165               ZlibFactory.getCompressionStrategy(conf),
166               ZlibCompressor.CompressionHeader.GZIP_FORMAT,
167               64 * 1024);
168        }
169      }
170    
171      static final class GzipZlibDecompressor extends ZlibDecompressor {
172        public GzipZlibDecompressor() {
173          super(ZlibDecompressor.CompressionHeader.AUTODETECT_GZIP_ZLIB, 64*1024);
174        }
175      }
176    
177    }