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