001: /*
002: * @(#)Inflater.java 1.46 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.util.zip;
029:
030: /**
031: * This class provides support for general purpose decompression using
032: * popular ZLIB compression library. The ZLIB compression library was
033: * initially developed as part of the PNG graphics standard and is not
034: * protected by patents. It is fully described in the specifications at
035: * the <a href="package-summary.html#package_description">java.util.zip
036: * package description</a>.
037: *
038: * <p>The following code fragment demonstrates a trivial compression
039: * and decompression of a string using <tt>Deflater</tt> and
040: * <tt>Inflater</tt>.
041: * NOTE: <B>java.util.zip.Defalter</B> is found in J2ME CDC profiles such as
042: * J2ME Foundation Profile.
043: *
044: * <blockquote><pre>
045: * // Encode a String into bytes
046: * String inputString = "blahblahblah\u20AC\u20AC";
047: * byte[] input = inputString.getBytes("UTF-8");
048: *
049: * // Compress the bytes
050: * byte[] output = new byte[100];
051: * Deflater compresser = new Deflater();
052: * compresser.setInput(input);
053: * compresser.finish();
054: * int compressedDataLength = compresser.deflate(output);
055: *
056: * NOTE: <B>java.util.zip.Defalter</B> is found in J2ME CDC profiles such as
057: * J2ME Foundation Profile.
058: *
059: * // Decompress the bytes
060: * Inflater decompresser = new Inflater();
061: * decompresser.setInput(output, 0, compressedDataLength);
062: * byte[] result = new byte[100];
063: * int resultLength = decompresser.inflate(result);
064: * decompresser.end();
065: *
066: * // Decode the bytes into a String
067: * String outputString = new String(result, 0, resultLength, "UTF-8");
068: * </pre></blockquote>
069: *
070: * @see Deflater
071: * @version 1.36, 05/03/00
072: * @author David Connelly
073: *
074: */
075: public class Inflater {
076: private long strm;
077: private byte[] buf = new byte[0];
078: private int off, len;
079: private boolean finished;
080: private boolean needDict;
081:
082: /*
083: * Loads the ZLIB library.
084: */
085: static {
086: java.security.AccessController
087: .doPrivileged(new sun.security.action.LoadLibraryAction(
088: "zip"));
089: initIDs();
090: }
091:
092: /**
093: * Creates a new decompressor. If the parameter 'nowrap' is true then
094: * the ZLIB header and checksum fields will not be used. This provides
095: * compatibility with the compression format used by both GZIP and PKZIP.
096: * <p>
097: * Note: When using the 'nowrap' option it is also necessary to provide
098: * an extra "dummy" byte as input. This is required by the ZLIB native
099: * library in order to support certain optimizations.
100: *
101: * @param nowrap if true then support GZIP compatible compression
102: */
103: public Inflater(boolean nowrap) {
104: strm = init(nowrap);
105: }
106:
107: /**
108: * Creates a new decompressor.
109: */
110: public Inflater() {
111: this (false);
112: }
113:
114: /**
115: * Sets input data for decompression. Should be called whenever
116: * needsInput() returns true indicating that more input data is
117: * required.
118: * @param b the input data bytes
119: * @param off the start offset of the input data
120: * @param len the length of the input data
121: * @see Inflater#needsInput
122: */
123: public synchronized void setInput(byte[] b, int off, int len) {
124: if (b == null) {
125: throw new NullPointerException();
126: }
127: if (off < 0 || len < 0 || off > b.length - len) {
128: throw new ArrayIndexOutOfBoundsException();
129: }
130: this .buf = b;
131: this .off = off;
132: this .len = len;
133: }
134:
135: /**
136: * Sets input data for decompression. Should be called whenever
137: * needsInput() returns true indicating that more input data is
138: * required.
139: * @param b the input data bytes
140: * @see Inflater#needsInput
141: */
142: public void setInput(byte[] b) {
143: setInput(b, 0, b.length);
144: }
145:
146: /**
147: * Sets the preset dictionary to the given array of bytes. Should be
148: * called when inflate() returns 0 and needsDictionary() returns true
149: * indicating that a preset dictionary is required. The method getAdler()
150: * can be used to get the Adler-32 value of the dictionary needed.
151: * @param b the dictionary data bytes
152: * @param off the start offset of the data
153: * @param len the length of the data
154: * @see Inflater#needsDictionary
155: * @see Inflater#getAdler
156: */
157: public synchronized void setDictionary(byte[] b, int off, int len) {
158: if (strm == 0 || b == null) {
159: throw new NullPointerException();
160: }
161: if (off < 0 || len < 0 || off > b.length - len) {
162: throw new ArrayIndexOutOfBoundsException();
163: }
164: setDictionary(strm, b, off, len);
165: needDict = false;
166: }
167:
168: /**
169: * Sets the preset dictionary to the given array of bytes. Should be
170: * called when inflate() returns 0 and needsDictionary() returns true
171: * indicating that a preset dictionary is required. The method getAdler()
172: * can be used to get the Adler-32 value of the dictionary needed.
173: * @param b the dictionary data bytes
174: * @see Inflater#needsDictionary
175: * @see Inflater#getAdler
176: */
177: public void setDictionary(byte[] b) {
178: setDictionary(b, 0, b.length);
179: }
180:
181: /**
182: * Returns the total number of bytes remaining in the input buffer.
183: * This can be used to find out what bytes still remain in the input
184: * buffer after decompression has finished.
185: * @return the total number of bytes remaining in the input buffer
186: */
187: public synchronized int getRemaining() {
188: return len;
189: }
190:
191: /**
192: * Returns true if no data remains in the input buffer. This can
193: * be used to determine if #setInput should be called in order
194: * to provide more input.
195: * @return true if no data remains in the input buffer
196: */
197: public synchronized boolean needsInput() {
198: return len <= 0;
199: }
200:
201: /**
202: * Returns true if a preset dictionary is needed for decompression.
203: * @return true if a preset dictionary is needed for decompression
204: * @see Inflater#setDictionary
205: */
206: public synchronized boolean needsDictionary() {
207: return needDict;
208: }
209:
210: /**
211: * Return true if the end of the compressed data stream has been
212: * reached.
213: * @return true if the end of the compressed data stream has been
214: * reached
215: */
216: public synchronized boolean finished() {
217: return finished;
218: }
219:
220: /**
221: * Uncompresses bytes into specified buffer. Returns actual number
222: * of bytes uncompressed. A return value of 0 indicates that
223: * needsInput() or needsDictionary() should be called in order to
224: * determine if more input data or a preset dictionary is required.
225: * In the later case, getAdler() can be used to get the Adler-32
226: * value of the dictionary required.
227: * @param b the buffer for the uncompressed data
228: * @param off the start offset of the data
229: * @param len the maximum number of uncompressed bytes
230: * @return the actual number of uncompressed bytes
231: * @exception DataFormatException if the compressed data format is invalid
232: * @see Inflater#needsInput
233: * @see Inflater#needsDictionary
234: */
235: public synchronized int inflate(byte[] b, int off, int len)
236: throws DataFormatException {
237: if (b == null) {
238: throw new NullPointerException();
239: }
240: if (off < 0 || len < 0 || off > b.length - len) {
241: throw new ArrayIndexOutOfBoundsException();
242: }
243: return inflateBytes(b, off, len);
244: }
245:
246: /**
247: * Uncompresses bytes into specified buffer. Returns actual number
248: * of bytes uncompressed. A return value of 0 indicates that
249: * needsInput() or needsDictionary() should be called in order to
250: * determine if more input data or a preset dictionary is required.
251: * In the later case, getAdler() can be used to get the Adler-32
252: * value of the dictionary required.
253: * @param b the buffer for the uncompressed data
254: * @return the actual number of uncompressed bytes
255: * @exception DataFormatException if the compressed data format is invalid
256: * @see Inflater#needsInput
257: * @see Inflater#needsDictionary
258: */
259: public int inflate(byte[] b) throws DataFormatException {
260: return inflate(b, 0, b.length);
261: }
262:
263: /**
264: * Returns the ADLER-32 value of the uncompressed data.
265: * @return the ADLER-32 value of the uncompressed data
266: */
267: public synchronized int getAdler() {
268: if (strm == 0) {
269: throw new NullPointerException();
270: }
271: return getAdler(strm);
272: }
273:
274: /**
275: * Returns the total number of bytes input so far.
276: * @return the total number of bytes input so far
277: */
278: public synchronized int getTotalIn() {
279: if (strm == 0) {
280: throw new NullPointerException();
281: }
282: return getTotalIn(strm);
283: }
284:
285: /**
286: * Returns the total number of bytes output so far.
287: * @return the total number of bytes output so far
288: */
289: public synchronized int getTotalOut() {
290: if (strm == 0) {
291: throw new NullPointerException();
292: }
293: return getTotalOut(strm);
294: }
295:
296: /**
297: * Resets inflater so that a new set of input data can be processed.
298: */
299: public synchronized void reset() {
300: if (strm == 0) {
301: throw new NullPointerException();
302: }
303: reset(strm);
304: finished = false;
305: needDict = false;
306: off = len = 0;
307: }
308:
309: /**
310: * Closes the decompressor and discards any unprocessed input.
311: * This method should be called when the decompressor is no longer
312: * being used, but will also be called automatically by the finalize()
313: * method. Once this method is called, the behavior of the Inflater
314: * object is undefined.
315: */
316: public synchronized void end() {
317: if (strm != 0) {
318: end(strm);
319: strm = 0;
320: }
321: }
322:
323: /**
324: * Closes the decompressor when garbage is collected.
325: */
326: protected void finalize() {
327: end();
328: }
329:
330: private native static void initIDs();
331:
332: private native static long init(boolean nowrap);
333:
334: private native static void setDictionary(long strm, byte[] b,
335: int off, int len);
336:
337: private native int inflateBytes(byte[] b, int off, int len)
338: throws DataFormatException;
339:
340: private native static int getAdler(long strm);
341:
342: private native static int getTotalIn(long strm);
343:
344: private native static int getTotalOut(long strm);
345:
346: private native static void reset(long strm);
347:
348: private native static void end(long strm);
349: }
|