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 }