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.FilterInputStream;
29 import java.io.InputStream;
30 import java.io.IOException;
31 import java.io.EOFException;
32
33 /**
34 * This class implements a stream filter for uncompressing data in the
35 * "deflate" compression format. It is also used as the basis for other
36 * decompression filters, such as GZIPInputStream.
37 *
38 * @see Inflater
39 * @author David Connelly
40 * @since 1.1
41 */
42 public
43 class InflaterInputStream extends FilterInputStream {
44 /**
45 * Decompressor for this stream.
46 */
47 protected Inflater inf;
48
49 /**
50 * Input buffer for decompression.
51 */
52 protected byte[] buf;
53
54 /**
55 * Length of input buffer.
56 */
57 protected int len;
58
59 private boolean closed = false;
60 // this flag is set to true after EOF has reached
61 private boolean reachEOF = false;
62
63 /**
64 * Check to make sure that this stream has not been closed
65 */
66 private void ensureOpen() throws IOException {
67 if (closed) {
68 throw new IOException("Stream closed");
69 }
70 }
71
72
73 /**
74 * Creates a new input stream with the specified decompressor and
75 * buffer size.
76 * @param in the input stream
77 * @param inf the decompressor ("inflater")
78 * @param size the input buffer size
79 * @exception IllegalArgumentException if {@code size <= 0}
80 */
81 public InflaterInputStream(InputStream in, Inflater inf, int size) {
82 super(in);
83 if (in == null || inf == null) {
84 throw new NullPointerException();
85 } else if (size <= 0) {
86 throw new IllegalArgumentException("buffer size <= 0");
87 }
88 this.inf = inf;
89 buf = new byte[size];
90 }
91
92 /**
93 * Creates a new input stream with the specified decompressor and a
94 * default buffer size.
95 * @param in the input stream
96 * @param inf the decompressor ("inflater")
97 */
98 public InflaterInputStream(InputStream in, Inflater inf) {
99 this(in, inf, 512);
100 }
101
102 boolean usesDefaultInflater = false;
103
104 /**
105 * Creates a new input stream with a default decompressor and buffer size.
106 * @param in the input stream
107 */
108 public InflaterInputStream(InputStream in) {
109 this(in, new Inflater());
110 usesDefaultInflater = true;
111 }
112
113 private byte[] singleByteBuf = new byte[1];
114
115 /**
116 * Reads a byte of uncompressed data. This method will block until
117 * enough input is available for decompression.
118 * @return the byte read, or -1 if end of compressed input is reached
119 * @exception IOException if an I/O error has occurred
120 */
121 public int read() throws IOException {
122 ensureOpen();
123 return read(singleByteBuf, 0, 1) == -1 ? -1 : Byte.toUnsignedInt(singleByteBuf[0]);
124 }
125
126 /**
127 * Reads uncompressed data into an array of bytes. If <code>len</code> is not
128 * zero, the method will block until some input can be decompressed; otherwise,
129 * no bytes are read and <code>0</code> is returned.
130 * @param b the buffer into which the data is read
131 * @param off the start offset in the destination array <code>b</code>
132 * @param len the maximum number of bytes read
210 if (len > b.length) {
211 len = b.length;
212 }
213 len = read(b, 0, len);
214 if (len == -1) {
215 reachEOF = true;
216 break;
217 }
218 total += len;
219 }
220 return total;
221 }
222
223 /**
224 * Closes this input stream and releases any system resources associated
225 * with the stream.
226 * @exception IOException if an I/O error has occurred
227 */
228 public void close() throws IOException {
229 if (!closed) {
230 if (usesDefaultInflater)
231 inf.end();
232 in.close();
233 closed = true;
234 }
235 }
236
237 /**
238 * Fills input buffer with more data to decompress.
239 * @exception IOException if an I/O error has occurred
240 */
241 protected void fill() throws IOException {
242 ensureOpen();
243 len = in.read(buf, 0, buf.length);
244 if (len == -1) {
245 throw new EOFException("Unexpected end of ZLIB input stream");
246 }
247 inf.setInput(buf, 0, len);
248 }
249
250 /**
|
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 jdk.internal.ref.CleanerFactory;
29
30 import java.io.EOFException;
31 import java.io.FilterInputStream;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.lang.ref.Cleaner;
35 import java.util.function.Consumer;
36 import java.util.function.Supplier;
37
38 /**
39 * This class implements a stream filter for uncompressing data in the
40 * "deflate" compression format. It is also used as the basis for other
41 * decompression filters, such as GZIPInputStream.
42 *
43 * @see Inflater
44 * @author David Connelly
45 * @since 1.1
46 */
47 public
48 class InflaterInputStream extends FilterInputStream {
49 /**
50 * Decompressor for this stream.
51 */
52 protected Inflater inf;
53
54 /**
55 * Input buffer for decompression.
56 */
57 protected byte[] buf;
58
59 /**
60 * Length of input buffer.
61 */
62 protected int len;
63
64 private boolean closed = false;
65 // this flag is set to true after EOF has reached
66 private boolean reachEOF = false;
67
68 // in case this stream manages own Inflater, else null
69 private final Cleaner.CleanableResource<Inflater> infRes;
70
71 /**
72 * Check to make sure that this stream has not been closed
73 */
74 private void ensureOpen() throws IOException {
75 if (closed) {
76 throw new IOException("Stream closed");
77 }
78 }
79
80
81 /**
82 * Creates a new input stream with the specified decompressor and
83 * buffer size.
84 * @param in the input stream
85 * @param inf the decompressor ("inflater")
86 * @param size the input buffer size
87 * @exception IllegalArgumentException if {@code size <= 0}
88 */
89 public InflaterInputStream(InputStream in, Inflater inf, int size) {
90 super(in);
91 if (in == null || inf == null) {
92 throw new NullPointerException();
93 } else if (size <= 0) {
94 throw new IllegalArgumentException("buffer size <= 0");
95 }
96 this.buf = new byte[size];
97 this.infRes = null; // uses specified/default decompressor
98 this.inf = inf;
99 }
100
101 /**
102 * Creates a new input stream with the specified decompressor and a
103 * default buffer size.
104 * @param in the input stream
105 * @param inf the decompressor ("inflater")
106 */
107 public InflaterInputStream(InputStream in, Inflater inf) {
108 this(in, inf, 512);
109 }
110
111 boolean usesDefaultInflater = false;
112
113 /**
114 * Creates a new input stream with a default decompressor and buffer size.
115 * @param in the input stream
116 */
117 public InflaterInputStream(InputStream in) {
118 this(in, new Inflater());
119 usesDefaultInflater = true;
120 }
121
122 /**
123 * Creates a new input stream with a decompressor allocated by inflaterAllocator
124 * and deallocated by inflaterDeallocator and buffer size.
125 * @param in the input stream
126 * @param inflaterAllocator the inflater allocator function
127 * @param inflaterDeallocator the inflater de-allocator function
128 * @param size the input buffer size
129 */
130 InflaterInputStream(InputStream in,
131 Supplier<Inflater> inflaterAllocator,
132 Consumer<Inflater> inflaterDeallocator,
133 int size) {
134 super(in);
135 if (in == null) {
136 throw new NullPointerException();
137 } else if (size <= 0) {
138 throw new IllegalArgumentException("buffer size <= 0");
139 }
140 this.buf = new byte[size];
141 this.infRes = CleanerFactory
142 .cleaner()
143 .createResource(this, inflaterAllocator, inflaterDeallocator);
144 this.inf = infRes.value();
145 }
146
147 private byte[] singleByteBuf = new byte[1];
148
149 /**
150 * Reads a byte of uncompressed data. This method will block until
151 * enough input is available for decompression.
152 * @return the byte read, or -1 if end of compressed input is reached
153 * @exception IOException if an I/O error has occurred
154 */
155 public int read() throws IOException {
156 ensureOpen();
157 return read(singleByteBuf, 0, 1) == -1 ? -1 : Byte.toUnsignedInt(singleByteBuf[0]);
158 }
159
160 /**
161 * Reads uncompressed data into an array of bytes. If <code>len</code> is not
162 * zero, the method will block until some input can be decompressed; otherwise,
163 * no bytes are read and <code>0</code> is returned.
164 * @param b the buffer into which the data is read
165 * @param off the start offset in the destination array <code>b</code>
166 * @param len the maximum number of bytes read
244 if (len > b.length) {
245 len = b.length;
246 }
247 len = read(b, 0, len);
248 if (len == -1) {
249 reachEOF = true;
250 break;
251 }
252 total += len;
253 }
254 return total;
255 }
256
257 /**
258 * Closes this input stream and releases any system resources associated
259 * with the stream.
260 * @exception IOException if an I/O error has occurred
261 */
262 public void close() throws IOException {
263 if (!closed) {
264 if (infRes != null)
265 infRes.clean();
266 else if (usesDefaultInflater)
267 inf.end();
268 in.close();
269 closed = true;
270 }
271 }
272
273 /**
274 * Fills input buffer with more data to decompress.
275 * @exception IOException if an I/O error has occurred
276 */
277 protected void fill() throws IOException {
278 ensureOpen();
279 len = in.read(buf, 0, buf.length);
280 if (len == -1) {
281 throw new EOFException("Unexpected end of ZLIB input stream");
282 }
283 inf.setInput(buf, 0, len);
284 }
285
286 /**
|