1. /*
  2. * @(#)Inflater.java 1.41 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util.zip;
  8. /**
  9. * This class provides support for general purpose decompression using the
  10. * popular ZLIB compression library. The ZLIB compression library was
  11. * initially developed as part of the PNG graphics standard and is not
  12. * protected by patents. It is fully described in the specifications at
  13. * the <a href="package-summary.html#package_description">java.util.zip
  14. * package description</a>.
  15. *
  16. * <p>The following code fragment demonstrates a trivial compression
  17. * and decompression of a string using <tt>Deflater</tt> and
  18. * <tt>Inflater</tt>.
  19. *
  20. * <blockquote><pre>
  21. * // Encode a String into bytes
  22. * String inputString = "blahblahblah\u20AC\u20AC";
  23. * byte[] input = inputString.getBytes("UTF-8");
  24. *
  25. * // Compress the bytes
  26. * byte[] output = new byte[100];
  27. * Deflater compresser = new Deflater();
  28. * compresser.setInput(input);
  29. * compresser.finish();
  30. * int compressedDataLength = compresser.deflate(output);
  31. *
  32. * // Decompress the bytes
  33. * Inflater decompresser = new Inflater();
  34. * decompresser.setInput(output, 0, compressedDataLength);
  35. * byte[] result = new byte[100];
  36. * int resultLength = decompresser.inflate(result);
  37. * decompresser.end();
  38. *
  39. * // Decode the bytes into a String
  40. * String outputString = new String(result, 0, resultLength, "UTF-8");
  41. * </pre></blockquote>
  42. *
  43. * @see Deflater
  44. * @version 1.41, 12/19/03
  45. * @author David Connelly
  46. *
  47. */
  48. public
  49. class Inflater {
  50. private long strm;
  51. private byte[] buf = new byte[0];
  52. private int off, len;
  53. private boolean finished;
  54. private boolean needDict;
  55. /*
  56. * Loads the ZLIB library.
  57. */
  58. static {
  59. java.security.AccessController.doPrivileged(
  60. new sun.security.action.LoadLibraryAction("zip"));
  61. initIDs();
  62. }
  63. /**
  64. * Creates a new decompressor. If the parameter 'nowrap' is true then
  65. * the ZLIB header and checksum fields will not be used. This provides
  66. * compatibility with the compression format used by both GZIP and PKZIP.
  67. * <p>
  68. * Note: When using the 'nowrap' option it is also necessary to provide
  69. * an extra "dummy" byte as input. This is required by the ZLIB native
  70. * library in order to support certain optimizations.
  71. *
  72. * @param nowrap if true then support GZIP compatible compression
  73. */
  74. public Inflater(boolean nowrap) {
  75. strm = init(nowrap);
  76. }
  77. /**
  78. * Creates a new decompressor.
  79. */
  80. public Inflater() {
  81. this(false);
  82. }
  83. /**
  84. * Sets input data for decompression. Should be called whenever
  85. * needsInput() returns true indicating that more input data is
  86. * required.
  87. * @param b the input data bytes
  88. * @param off the start offset of the input data
  89. * @param len the length of the input data
  90. * @see Inflater#needsInput
  91. */
  92. public synchronized void setInput(byte[] b, int off, int len) {
  93. if (b == null) {
  94. throw new NullPointerException();
  95. }
  96. if (off < 0 || len < 0 || off > b.length - len) {
  97. throw new ArrayIndexOutOfBoundsException();
  98. }
  99. this.buf = b;
  100. this.off = off;
  101. this.len = len;
  102. }
  103. /**
  104. * Sets input data for decompression. Should be called whenever
  105. * needsInput() returns true indicating that more input data is
  106. * required.
  107. * @param b the input data bytes
  108. * @see Inflater#needsInput
  109. */
  110. public void setInput(byte[] b) {
  111. setInput(b, 0, b.length);
  112. }
  113. /**
  114. * Sets the preset dictionary to the given array of bytes. Should be
  115. * called when inflate() returns 0 and needsDictionary() returns true
  116. * indicating that a preset dictionary is required. The method getAdler()
  117. * can be used to get the Adler-32 value of the dictionary needed.
  118. * @param b the dictionary data bytes
  119. * @param off the start offset of the data
  120. * @param len the length of the data
  121. * @see Inflater#needsDictionary
  122. * @see Inflater#getAdler
  123. */
  124. public synchronized void setDictionary(byte[] b, int off, int len) {
  125. if (strm == 0 || b == null) {
  126. throw new NullPointerException();
  127. }
  128. if (off < 0 || len < 0 || off > b.length - len) {
  129. throw new ArrayIndexOutOfBoundsException();
  130. }
  131. setDictionary(strm, b, off, len);
  132. needDict = false;
  133. }
  134. /**
  135. * Sets the preset dictionary to the given array of bytes. Should be
  136. * called when inflate() returns 0 and needsDictionary() returns true
  137. * indicating that a preset dictionary is required. The method getAdler()
  138. * can be used to get the Adler-32 value of the dictionary needed.
  139. * @param b the dictionary data bytes
  140. * @see Inflater#needsDictionary
  141. * @see Inflater#getAdler
  142. */
  143. public void setDictionary(byte[] b) {
  144. setDictionary(b, 0, b.length);
  145. }
  146. /**
  147. * Returns the total number of bytes remaining in the input buffer.
  148. * This can be used to find out what bytes still remain in the input
  149. * buffer after decompression has finished.
  150. * @return the total number of bytes remaining in the input buffer
  151. */
  152. public synchronized int getRemaining() {
  153. return len;
  154. }
  155. /**
  156. * Returns true if no data remains in the input buffer. This can
  157. * be used to determine if #setInput should be called in order
  158. * to provide more input.
  159. * @return true if no data remains in the input buffer
  160. */
  161. public synchronized boolean needsInput() {
  162. return len <= 0;
  163. }
  164. /**
  165. * Returns true if a preset dictionary is needed for decompression.
  166. * @return true if a preset dictionary is needed for decompression
  167. * @see Inflater#setDictionary
  168. */
  169. public synchronized boolean needsDictionary() {
  170. return needDict;
  171. }
  172. /**
  173. * Returns true if the end of the compressed data stream has been
  174. * reached.
  175. * @return true if the end of the compressed data stream has been
  176. * reached
  177. */
  178. public synchronized boolean finished() {
  179. return finished;
  180. }
  181. /**
  182. * Uncompresses bytes into specified buffer. Returns actual number
  183. * of bytes uncompressed. A return value of 0 indicates that
  184. * needsInput() or needsDictionary() should be called in order to
  185. * determine if more input data or a preset dictionary is required.
  186. * In the later case, getAdler() can be used to get the Adler-32
  187. * value of the dictionary required.
  188. * @param b the buffer for the uncompressed data
  189. * @param off the start offset of the data
  190. * @param len the maximum number of uncompressed bytes
  191. * @return the actual number of uncompressed bytes
  192. * @exception DataFormatException if the compressed data format is invalid
  193. * @see Inflater#needsInput
  194. * @see Inflater#needsDictionary
  195. */
  196. public synchronized int inflate(byte[] b, int off, int len)
  197. throws DataFormatException
  198. {
  199. if (b == null) {
  200. throw new NullPointerException();
  201. }
  202. if (off < 0 || len < 0 || off > b.length - len) {
  203. throw new ArrayIndexOutOfBoundsException();
  204. }
  205. return inflateBytes(b, off, len);
  206. }
  207. /**
  208. * Uncompresses bytes into specified buffer. Returns actual number
  209. * of bytes uncompressed. A return value of 0 indicates that
  210. * needsInput() or needsDictionary() should be called in order to
  211. * determine if more input data or a preset dictionary is required.
  212. * In the later case, getAdler() can be used to get the Adler-32
  213. * value of the dictionary required.
  214. * @param b the buffer for the uncompressed data
  215. * @return the actual number of uncompressed bytes
  216. * @exception DataFormatException if the compressed data format is invalid
  217. * @see Inflater#needsInput
  218. * @see Inflater#needsDictionary
  219. */
  220. public int inflate(byte[] b) throws DataFormatException {
  221. return inflate(b, 0, b.length);
  222. }
  223. /**
  224. * Returns the ADLER-32 value of the uncompressed data.
  225. * @return the ADLER-32 value of the uncompressed data
  226. */
  227. public synchronized int getAdler() {
  228. ensureOpen();
  229. return getAdler(strm);
  230. }
  231. /**
  232. * Returns the total number of compressed bytes input so far.
  233. *
  234. * <p>Since the number of bytes may be greater than
  235. * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
  236. * the preferred means of obtaining this information.</p>
  237. *
  238. * @return the total number of compressed bytes input so far
  239. */
  240. public int getTotalIn() {
  241. return (int) getBytesRead();
  242. }
  243. /**
  244. * Returns the total number of compressed bytes input so far.</p>
  245. *
  246. * @return the total (non-negative) number of compressed bytes input so far
  247. */
  248. public synchronized long getBytesRead() {
  249. ensureOpen();
  250. return getBytesRead(strm);
  251. }
  252. /**
  253. * Returns the total number of uncompressed bytes output so far.
  254. *
  255. * <p>Since the number of bytes may be greater than
  256. * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now
  257. * the preferred means of obtaining this information.</p>
  258. *
  259. * @return the total number of uncompressed bytes output so far
  260. */
  261. public int getTotalOut() {
  262. return (int) getBytesWritten();
  263. }
  264. /**
  265. * Returns the total number of uncompressed bytes output so far.</p>
  266. *
  267. * @return the total (non-negative) number of uncompressed bytes output so far
  268. */
  269. public synchronized long getBytesWritten() {
  270. ensureOpen();
  271. return getBytesWritten(strm);
  272. }
  273. /**
  274. * Resets inflater so that a new set of input data can be processed.
  275. */
  276. public synchronized void reset() {
  277. ensureOpen();
  278. reset(strm);
  279. finished = false;
  280. needDict = false;
  281. off = len = 0;
  282. }
  283. /**
  284. * Closes the decompressor and discards any unprocessed input.
  285. * This method should be called when the decompressor is no longer
  286. * being used, but will also be called automatically by the finalize()
  287. * method. Once this method is called, the behavior of the Inflater
  288. * object is undefined.
  289. */
  290. public synchronized void end() {
  291. if (strm != 0) {
  292. end(strm);
  293. strm = 0;
  294. }
  295. }
  296. /**
  297. * Closes the decompressor when garbage is collected.
  298. */
  299. protected void finalize() {
  300. end();
  301. }
  302. private void ensureOpen () {
  303. if (strm == 0)
  304. throw new NullPointerException();
  305. }
  306. private native static void initIDs();
  307. private native static long init(boolean nowrap);
  308. private native static void setDictionary(long strm, byte[] b, int off,
  309. int len);
  310. private native int inflateBytes(byte[] b, int off, int len)
  311. throws DataFormatException;
  312. private native static int getAdler(long strm);
  313. private native static long getBytesRead(long strm);
  314. private native static long getBytesWritten(long strm);
  315. private native static void reset(long strm);
  316. private native static void end(long strm);
  317. }