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