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+
26+package java.util.zip;
27+
28+import java.io.SequenceInputStream;
29+import java.io.ByteArrayInputStream;
30+import java.io.InputStream;
31+import java.io.IOException;
32+import 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+ */
42+public
43+class 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+}