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.*;
022import java.util.zip.GZIPOutputStream;
023import java.util.zip.GZIPInputStream;
024
025import org.apache.hadoop.classification.InterfaceAudience;
026import org.apache.hadoop.classification.InterfaceStability;
027import org.apache.hadoop.conf.Configuration;
028import org.apache.hadoop.io.compress.DefaultCodec;
029import org.apache.hadoop.io.compress.zlib.*;
030import org.apache.hadoop.io.compress.zlib.ZlibCompressor.CompressionLevel;
031import org.apache.hadoop.io.compress.zlib.ZlibCompressor.CompressionStrategy;
032
033/**
034 * This class creates gzip compressors/decompressors. 
035 */
036@InterfaceAudience.Public
037@InterfaceStability.Evolving
038public 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}