1. /*
  2. * @(#)Deflater.java 1.34 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 compression using the
  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 Inflater
  20. * @version 1.34, 02/02/00
  21. * @author David Connelly
  22. */
  23. public
  24. class Deflater {
  25. private long strm;
  26. private byte[] buf = new byte[0];
  27. private int off, len;
  28. private int level, strategy;
  29. private boolean setParams;
  30. private boolean finish, finished;
  31. /**
  32. * Compression method for the deflate algorithm (the only one currently
  33. * supported).
  34. */
  35. public static final int DEFLATED = 8;
  36. /**
  37. * Compression level for no compression.
  38. */
  39. public static final int NO_COMPRESSION = 0;
  40. /**
  41. * Compression level for fastest compression.
  42. */
  43. public static final int BEST_SPEED = 1;
  44. /**
  45. * Compression level for best compression.
  46. */
  47. public static final int BEST_COMPRESSION = 9;
  48. /**
  49. * Default compression level.
  50. */
  51. public static final int DEFAULT_COMPRESSION = -1;
  52. /**
  53. * Compression strategy best used for data consisting mostly of small
  54. * values with a somewhat random distribution. Forces more Huffman coding
  55. * and less string matching.
  56. */
  57. public static final int FILTERED = 1;
  58. /**
  59. * Compression strategy for Huffman coding only.
  60. */
  61. public static final int HUFFMAN_ONLY = 2;
  62. /**
  63. * Default compression strategy.
  64. */
  65. public static final int DEFAULT_STRATEGY = 0;
  66. /*
  67. * Loads the ZLIB library.
  68. */
  69. static {
  70. java.security.AccessController.doPrivileged(
  71. new sun.security.action.LoadLibraryAction("zip"));
  72. initIDs();
  73. }
  74. /**
  75. * Creates a new compressor using the specified compression level.
  76. * If 'nowrap' is true then the ZLIB header and checksum fields will
  77. * not be used in order to support the compression format used in
  78. * both GZIP and PKZIP.
  79. * @param level the compression level (0-9)
  80. * @param nowrap if true then use GZIP compatible compression
  81. */
  82. public Deflater(int level, boolean nowrap) {
  83. this.level = level;
  84. this.strategy = DEFAULT_STRATEGY;
  85. strm = init(level, DEFAULT_STRATEGY, nowrap);
  86. }
  87. /**
  88. * Creates a new compressor using the specified compression level.
  89. * Compressed data will be generated in ZLIB format.
  90. * @param level the compression level (0-9)
  91. */
  92. public Deflater(int level) {
  93. this(level, false);
  94. }
  95. /**
  96. * Creates a new compressor with the default compression level.
  97. * Compressed data will be generated in ZLIB format.
  98. */
  99. public Deflater() {
  100. this(DEFAULT_COMPRESSION, false);
  101. }
  102. /**
  103. * Sets input data for compression. This should be called whenever
  104. * needsInput() returns true indicating that more input data is required.
  105. * @param b the input data bytes
  106. * @param off the start offset of the data
  107. * @param len the length of the data
  108. * @see Deflater#needsInput
  109. */
  110. public synchronized void setInput(byte[] b, int off, int len) {
  111. if (b== null) {
  112. throw new NullPointerException();
  113. }
  114. if (off < 0 || len < 0 || off + len > b.length) {
  115. throw new ArrayIndexOutOfBoundsException();
  116. }
  117. this.buf = b;
  118. this.off = off;
  119. this.len = len;
  120. }
  121. /**
  122. * Sets input data for compression. This should be called whenever
  123. * needsInput() returns true indicating that more input data is required.
  124. * @param b the input data bytes
  125. * @see Deflater#needsInput
  126. */
  127. public void setInput(byte[] b) {
  128. setInput(b, 0, b.length);
  129. }
  130. /**
  131. * Sets preset dictionary for compression. A preset dictionary is used
  132. * when the history buffer can be predetermined. When the data is later
  133. * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
  134. * in order to get the Adler-32 value of the dictionary required for
  135. * decompression.
  136. * @param b the dictionary data bytes
  137. * @param off the start offset of the data
  138. * @param len the length of the data
  139. * @see Inflater#inflate
  140. * @see Inflater#getAdler
  141. */
  142. public synchronized void setDictionary(byte[] b, int off, int len) {
  143. if (strm == 0 || b == null) {
  144. throw new NullPointerException();
  145. }
  146. if (off < 0 || len < 0 || off + len > b.length) {
  147. throw new ArrayIndexOutOfBoundsException();
  148. }
  149. setDictionary(strm, b, off, len);
  150. }
  151. /**
  152. * Sets preset dictionary for compression. A preset dictionary is used
  153. * when the history buffer can be predetermined. When the data is later
  154. * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
  155. * in order to get the Adler-32 value of the dictionary required for
  156. * decompression.
  157. * @param b the dictionary data bytes
  158. * @see Inflater#inflate
  159. * @see Inflater#getAdler
  160. */
  161. public void setDictionary(byte[] b) {
  162. setDictionary(b, 0, b.length);
  163. }
  164. /**
  165. * Sets the compression strategy to the specified value.
  166. * @param strategy the new compression strategy
  167. * @exception IllegalArgumentException if the compression strategy is
  168. * invalid
  169. */
  170. public synchronized void setStrategy(int strategy) {
  171. switch (strategy) {
  172. case DEFAULT_STRATEGY:
  173. case FILTERED:
  174. case HUFFMAN_ONLY:
  175. break;
  176. default:
  177. throw new IllegalArgumentException();
  178. }
  179. if (this.strategy != strategy) {
  180. this.strategy = strategy;
  181. setParams = true;
  182. }
  183. }
  184. /**
  185. * Sets the current compression level to the specified value.
  186. * @param level the new compression level (0-9)
  187. * @exception IllegalArgumentException if the compression level is invalid
  188. */
  189. public synchronized void setLevel(int level) {
  190. if ((level < 0 || level > 9) && level != DEFAULT_COMPRESSION) {
  191. throw new IllegalArgumentException("invalid compression level");
  192. }
  193. if (this.level != level) {
  194. this.level = level;
  195. setParams = true;
  196. }
  197. }
  198. /**
  199. * Returns true if the input data buffer is empty and setInput()
  200. * should be called in order to provide more input.
  201. * @return true if the input data buffer is empty and setInput()
  202. * should be called in order to provide more input
  203. */
  204. public boolean needsInput() {
  205. return len <= 0;
  206. }
  207. /**
  208. * When called, indicates that compression should end with the current
  209. * contents of the input buffer.
  210. */
  211. public synchronized void finish() {
  212. finish = true;
  213. }
  214. /**
  215. * Returns true if the end of the compressed data output stream has
  216. * been reached.
  217. * @return true if the end of the compressed data output stream has
  218. * been reached
  219. */
  220. public synchronized boolean finished() {
  221. return finished;
  222. }
  223. /**
  224. * Fills specified buffer with compressed data. Returns actual number
  225. * of bytes of compressed data. A return value of 0 indicates that
  226. * needsInput() should be called in order to determine if more input
  227. * data is required.
  228. * @param b the buffer for the compressed data
  229. * @param off the start offset of the data
  230. * @param len the maximum number of bytes of compressed data
  231. * @return the actual number of bytes of compressed data
  232. */
  233. public synchronized int deflate(byte[] b, int off, int len) {
  234. if (b == null) {
  235. throw new NullPointerException();
  236. }
  237. if (off < 0 || len < 0 || off + len > b.length) {
  238. throw new ArrayIndexOutOfBoundsException();
  239. }
  240. return deflateBytes(b, off, len);
  241. }
  242. /**
  243. * Fills specified buffer with compressed data. Returns actual number
  244. * of bytes of compressed data. A return value of 0 indicates that
  245. * needsInput() should be called in order to determine if more input
  246. * data is required.
  247. * @param b the buffer for the compressed data
  248. * @return the actual number of bytes of compressed data
  249. */
  250. public int deflate(byte[] b) {
  251. return deflate(b, 0, b.length);
  252. }
  253. /**
  254. * Returns the ADLER-32 value of the uncompressed data.
  255. * @return the ADLER-32 value of the uncompressed data
  256. */
  257. public synchronized int getAdler() {
  258. if (strm == 0) {
  259. throw new NullPointerException();
  260. }
  261. return getAdler(strm);
  262. }
  263. /**
  264. * Returns the total number of bytes input so far.
  265. * @return the total number of bytes input so far
  266. */
  267. public synchronized int getTotalIn() {
  268. if (strm == 0) {
  269. throw new NullPointerException();
  270. }
  271. return getTotalIn(strm);
  272. }
  273. /**
  274. * Returns the total number of bytes output so far.
  275. * @return the total number of bytes output so far
  276. */
  277. public synchronized int getTotalOut() {
  278. if (strm == 0) {
  279. throw new NullPointerException();
  280. }
  281. return getTotalOut(strm);
  282. }
  283. /**
  284. * Resets deflater so that a new set of input data can be processed.
  285. * Keeps current compression level and strategy settings.
  286. */
  287. public synchronized void reset() {
  288. if (strm == 0) {
  289. throw new NullPointerException();
  290. }
  291. reset(strm);
  292. finish = false;
  293. finished = false;
  294. off = len = 0;
  295. }
  296. /**
  297. * Closes the compressor and discards any unprocessed input.
  298. * This method should be called when the compressor is no longer
  299. * being used, but will also be called automatically by the
  300. * finalize() method. Once this method is called, the behavior
  301. * of the Deflater object is undefined.
  302. */
  303. public synchronized void end() {
  304. if (strm != 0) {
  305. end(strm);
  306. strm = 0;
  307. }
  308. }
  309. /**
  310. * Closes the compressor when garbage is collected.
  311. */
  312. protected void finalize() {
  313. end();
  314. }
  315. private static native void initIDs();
  316. private native static long init(int level, int strategy, boolean nowrap);
  317. private native static void setDictionary(long strm, byte[] b, int off,
  318. int len);
  319. private native int deflateBytes(byte[] b, int off, int len);
  320. private native static int getAdler(long strm);
  321. private native static int getTotalIn(long strm);
  322. private native static int getTotalOut(long strm);
  323. private native static void reset(long strm);
  324. private native static void end(long strm);
  325. }