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