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