History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/util/zip/GZIPInputStream.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/util/zip/GZIPInputStream.java+289−0
@@ -0,0 +1,289 @@
1/*
2 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.util.zip;
27
28import java.io.SequenceInputStream;
29import java.io.ByteArrayInputStream;
30import java.io.InputStream;
31import java.io.IOException;
32import java.io.EOFException;
33
34/**
35 * This class implements a stream filter for reading compressed data in
36 * the GZIP file format.
37 *
38 * @see InflaterInputStream
39 * @author David Connelly
40 *
41 */
42public
43class GZIPInputStream extends InflaterInputStream {
44 /**
45 * CRC-32 for uncompressed data.
46 */
47 protected CRC32 crc = new CRC32();
48
49 /**
50 * Indicates end of input stream.
51 */
52 protected boolean eos;
53
54 private boolean closed = false;
55
56 /**
57 * Check to make sure that this stream has not been closed
58 */
59 private void ensureOpen() throws IOException {
60 if (closed) {
61 throw new IOException("Stream closed");
62 }
63 }
64
65 /**
66 * Creates a new input stream with the specified buffer size.
67 * @param in the input stream
68 * @param size the input buffer size
69 *
70 * @exception ZipException if a GZIP format error has occurred or the
71 * compression method used is unsupported
72 * @exception IOException if an I/O error has occurred
73 * @exception IllegalArgumentException if size is <= 0
74 */
75 public GZIPInputStream(InputStream in, int size) throws IOException {
76 super(in, new Inflater(true), size);
77 usesDefaultInflater = true;
78 readHeader(in);
79 }
80
81 /**
82 * Creates a new input stream with a default buffer size.
83 * @param in the input stream
84 *
85 * @exception ZipException if a GZIP format error has occurred or the
86 * compression method used is unsupported
87 * @exception IOException if an I/O error has occurred
88 */
89 public GZIPInputStream(InputStream in) throws IOException {
90 this(in, 512);
91 }
92
93 /**
94 * Reads uncompressed data into an array of bytes. If <code>len</code> is not
95 * zero, the method will block until some input can be decompressed; otherwise,
96 * no bytes are read and <code>0</code> is returned.
97 * @param buf the buffer into which the data is read
98 * @param off the start offset in the destination array <code>b</code>
99 * @param len the maximum number of bytes read
100 * @return the actual number of bytes read, or -1 if the end of the
101 * compressed input stream is reached
102 *
103 * @exception NullPointerException If <code>buf</code> is <code>null</code>.
104 * @exception IndexOutOfBoundsException If <code>off</code> is negative,
105 * <code>len</code> is negative, or <code>len</code> is greater than
106 * <code>buf.length - off</code>
107 * @exception ZipException if the compressed input data is corrupt.
108 * @exception IOException if an I/O error has occurred.
109 *
110 */
111 public int read(byte[] buf, int off, int len) throws IOException {
112 ensureOpen();
113 if (eos) {
114 return -1;
115 }
116 int n = super.read(buf, off, len);
117 if (n == -1) {
118 if (readTrailer())
119 eos = true;
120 else
121 return this.read(buf, off, len);
122 } else {
123 crc.update(buf, off, n);
124 }
125 return n;
126 }
127
128 /**
129 * Closes this input stream and releases any system resources associated
130 * with the stream.
131 * @exception IOException if an I/O error has occurred
132 */
133 public void close() throws IOException {
134 if (!closed) {
135 super.close();
136 eos = true;
137 closed = true;
138 }
139 }
140
141 /**
142 * GZIP header magic number.
143 */
144 public final static int GZIP_MAGIC = 0x8b1f;
145
146 /*
147 * File header flags.
148 */
149 private final static int FTEXT = 1; // Extra text
150 private final static int FHCRC = 2; // Header CRC
151 private final static int FEXTRA = 4; // Extra field
152 private final static int FNAME = 8; // File name
153 private final static int FCOMMENT = 16; // File comment
154
155 /*
156 * Reads GZIP member header and returns the total byte number
157 * of this member header.
158 */
159 private int readHeader(InputStream this_in) throws IOException {
160 CheckedInputStream in = new CheckedInputStream(this_in, crc);
161 crc.reset();
162 // Check header magic
163 if (readUShort(in) != GZIP_MAGIC) {
164 throw new ZipException("Not in GZIP format");
165 }
166 // Check compression method
167 if (readUByte(in) != 8) {
168 throw new ZipException("Unsupported compression method");
169 }
170 // Read flags
171 int flg = readUByte(in);
172 // Skip MTIME, XFL, and OS fields
173 skipBytes(in, 6);
174 int n = 2 + 2 + 6;
175 // Skip optional extra field
176 if ((flg & FEXTRA) == FEXTRA) {
177 int m = readUShort(in);
178 skipBytes(in, m);
179 n += m + 2;
180 }
181 // Skip optional file name
182 if ((flg & FNAME) == FNAME) {
183 do {
184 n++;
185 } while (readUByte(in) != 0);
186 }
187 // Skip optional file comment
188 if ((flg & FCOMMENT) == FCOMMENT) {
189 do {
190 n++;
191 } while (readUByte(in) != 0);
192 }
193 // Check optional header CRC
194 if ((flg & FHCRC) == FHCRC) {
195 int v = (int)crc.getValue() & 0xffff;
196 if (readUShort(in) != v) {
197 throw new ZipException("Corrupt GZIP header");
198 }
199 n += 2;
200 }
201 crc.reset();
202 return n;
203 }
204
205 /*
206 * Reads GZIP member trailer and returns true if the eos
207 * reached, false if there are more (concatenated gzip
208 * data set)
209 */
210 private boolean readTrailer() throws IOException {
211 InputStream in = this.in;
212 int n = inf.getRemaining();
213 if (n > 0) {
214 in = new SequenceInputStream(
215 new ByteArrayInputStream(buf, len - n, n), in);
216 }
217 // Uses left-to-right evaluation order
218 if ((readUInt(in) != crc.getValue()) ||
219 // rfc1952; ISIZE is the input size modulo 2^32
220 (readUInt(in) != (inf.getBytesWritten() & 0xffffffffL)))
221 throw new ZipException("Corrupt GZIP trailer");
222
223 // If there are more bytes available in "in" or
224 // the leftover in the "inf" is > 26 bytes:
225 // this.trailer(8) + next.header.min(10) + next.trailer(8)
226 // try concatenated case
227 if (this.in.available() > 0 || n > 26) {
228 int m = 8; // this.trailer
229 try {
230 m += readHeader(in); // next.header
231 } catch (IOException ze) {
232 return true; // ignore any malformed, do nothing
233 }
234 inf.reset();
235 if (n > m)
236 inf.setInput(buf, len - n + m, n - m);
237 return false;
238 }
239 return true;
240 }
241
242 /*
243 * Reads unsigned integer in Intel byte order.
244 */
245 private long readUInt(InputStream in) throws IOException {
246 long s = readUShort(in);
247 return ((long)readUShort(in) << 16) | s;
248 }
249
250 /*
251 * Reads unsigned short in Intel byte order.
252 */
253 private int readUShort(InputStream in) throws IOException {
254 int b = readUByte(in);
255 return ((int)readUByte(in) << 8) | b;
256 }
257
258 /*
259 * Reads unsigned byte.
260 */
261 private int readUByte(InputStream in) throws IOException {
262 int b = in.read();
263 if (b == -1) {
264 throw new EOFException();
265 }
266 if (b < -1 || b > 255) {
267 // Report on this.in, not argument in; see read{Header, Trailer}.
268 throw new IOException(this.in.getClass().getName()
269 + ".read() returned value out of range -1..255: " + b);
270 }
271 return b;
272 }
273
274 private byte[] tmpbuf = new byte[128];
275
276 /*
277 * Skips bytes of input data blocking until all bytes are skipped.
278 * Does not assume that the input stream is capable of seeking.
279 */
280 private void skipBytes(InputStream in, int n) throws IOException {
281 while (n > 0) {
282 int len = in.read(tmpbuf, 0, n < tmpbuf.length ? n : tmpbuf.length);
283 if (len == -1) {
284 throw new EOFException();
285 }
286 n -= len;
287 }
288 }
289}