72 * byte[] result = new byte[100];
73 * int resultLength = decompresser.inflate(result);
74 * decompresser.end();
75 *
76 * // Decode the bytes into a String
77 * String outputString = new String(result, 0, resultLength, "UTF-8");
78 * } catch (java.io.UnsupportedEncodingException ex) {
79 * // handle
80 * } catch (java.util.zip.DataFormatException ex) {
81 * // handle
82 * }
83 * </pre></blockquote>
84 *
85 * @apiNote
86 * To release resources used by this {@code Deflater}, the {@link #end()} method
87 * should be called explicitly. Subclasses are responsible for the cleanup of resources
88 * acquired by the subclass. Subclasses that override {@link #finalize()} in order
89 * to perform cleanup should be modified to use alternative cleanup mechanisms such
90 * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
91 *
92 * @implSpec
93 * If this {@code Deflater} has been subclassed and the {@code end} method has been
94 * overridden, the {@code end} method will be called by the finalization when the
95 * deflater is unreachable. But the subclasses should not depend on this specific
96 * implementation; the finalization is not reliable and the {@code finalize} method
97 * is deprecated to be removed.
98 *
99 * @see Inflater
100 * @author David Connelly
101 * @since 1.1
102 */
103
104 public class Deflater {
105
106 private final DeflaterZStreamRef zsRef;
107 private ByteBuffer input = ZipUtils.defaultBuf;
108 private byte[] inputArray;
109 private int inputPos, inputLim;
110 private int level, strategy;
111 private boolean setParams;
112 private boolean finish, finished;
113 private long bytesRead;
114 private long bytesWritten;
115
116 /**
117 * Compression method for the deflate algorithm (the only one currently
118 * supported).
187 * Flush mode to use at the end of output. Can only be provided by the
188 * user by way of {@link #finish()}.
189 */
190 private static final int FINISH = 4;
191
192 static {
193 ZipUtils.loadLibrary();
194 }
195
196 /**
197 * Creates a new compressor using the specified compression level.
198 * If 'nowrap' is true then the ZLIB header and checksum fields will
199 * not be used in order to support the compression format used in
200 * both GZIP and PKZIP.
201 * @param level the compression level (0-9)
202 * @param nowrap if true then use GZIP compatible compression
203 */
204 public Deflater(int level, boolean nowrap) {
205 this.level = level;
206 this.strategy = DEFAULT_STRATEGY;
207 this.zsRef = DeflaterZStreamRef.get(this,
208 init(level, DEFAULT_STRATEGY, nowrap));
209 }
210
211 /**
212 * Creates a new compressor using the specified compression level.
213 * Compressed data will be generated in ZLIB format.
214 * @param level the compression level (0-9)
215 */
216 public Deflater(int level) {
217 this(level, false);
218 }
219
220 /**
221 * Creates a new compressor with the default compression level.
222 * Compressed data will be generated in ZLIB format.
223 */
224 public Deflater() {
225 this(DEFAULT_COMPRESSION, false);
226 }
227
884 input = ZipUtils.defaultBuf;
885 inputArray = null;
886 bytesRead = bytesWritten = 0;
887 }
888 }
889
890 /**
891 * Closes the compressor and discards any unprocessed input.
892 *
893 * This method should be called when the compressor is no longer
894 * being used. Once this method is called, the behavior of the
895 * Deflater object is undefined.
896 */
897 public void end() {
898 synchronized (zsRef) {
899 zsRef.clean();
900 input = ZipUtils.defaultBuf;
901 }
902 }
903
904 /**
905 * Closes the compressor when garbage is collected.
906 *
907 * @deprecated The {@code finalize} method has been deprecated and will be
908 * removed. It is implemented as a no-op. Subclasses that override
909 * {@code finalize} in order to perform cleanup should be modified to use
910 * alternative cleanup mechanisms and to remove the overriding {@code finalize}
911 * method. The recommended cleanup for compressor is to explicitly call
912 * {@code end} method when it is no longer in use. If the {@code end} is
913 * not invoked explicitly the resource of the compressor will be released
914 * when the instance becomes unreachable.
915 */
916 @Deprecated(since="9", forRemoval=true)
917 protected void finalize() {}
918
919 private void ensureOpen() {
920 assert Thread.holdsLock(zsRef);
921 if (zsRef.address() == 0)
922 throw new NullPointerException("Deflater has been closed");
923 }
924
925 private static native long init(int level, int strategy, boolean nowrap);
926 private static native void setDictionary(long addr, byte[] b, int off,
927 int len);
928 private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
929 private native long deflateBytesBytes(long addr,
930 byte[] inputArray, int inputOff, int inputLen,
931 byte[] outputArray, int outputOff, int outputLen,
932 int flush, int params);
933 private native long deflateBytesBuffer(long addr,
934 byte[] inputArray, int inputOff, int inputLen,
935 long outputAddress, int outputLen,
936 int flush, int params);
937 private native long deflateBufferBytes(long addr,
938 long inputAddress, int inputLen,
960 this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
961 this.address = addr;
962 }
963
964 long address() {
965 return address;
966 }
967
968 void clean() {
969 cleanable.clean();
970 }
971
972 public synchronized void run() {
973 long addr = address;
974 address = 0;
975 if (addr != 0) {
976 end(addr);
977 }
978 }
979
980 /*
981 * If {@code Deflater} has been subclassed and the {@code end} method is
982 * overridden, uses {@code finalizer} mechanism for resource cleanup. So
983 * {@code end} method can be called when the {@code Deflater} is unreachable.
984 * This mechanism will be removed when the {@code finalize} method is
985 * removed from {@code Deflater}.
986 */
987 static DeflaterZStreamRef get(Deflater owner, long addr) {
988 Class<?> clz = owner.getClass();
989 while (clz != Deflater.class) {
990 try {
991 clz.getDeclaredMethod("end");
992 return new FinalizableZStreamRef(owner, addr);
993 } catch (NoSuchMethodException nsme) {}
994 clz = clz.getSuperclass();
995 }
996 return new DeflaterZStreamRef(owner, addr);
997 }
998
999 private static class FinalizableZStreamRef extends DeflaterZStreamRef {
1000 final Deflater owner;
1001
1002 FinalizableZStreamRef (Deflater owner, long addr) {
1003 super(null, addr);
1004 this.owner = owner;
1005 }
1006
1007 @Override
1008 void clean() {
1009 run();
1010 }
1011
1012 @Override
1013 @SuppressWarnings("deprecation")
1014 protected void finalize() {
1015 owner.end();
1016 }
1017 }
1018 }
1019 }
|
72 * byte[] result = new byte[100];
73 * int resultLength = decompresser.inflate(result);
74 * decompresser.end();
75 *
76 * // Decode the bytes into a String
77 * String outputString = new String(result, 0, resultLength, "UTF-8");
78 * } catch (java.io.UnsupportedEncodingException ex) {
79 * // handle
80 * } catch (java.util.zip.DataFormatException ex) {
81 * // handle
82 * }
83 * </pre></blockquote>
84 *
85 * @apiNote
86 * To release resources used by this {@code Deflater}, the {@link #end()} method
87 * should be called explicitly. Subclasses are responsible for the cleanup of resources
88 * acquired by the subclass. Subclasses that override {@link #finalize()} in order
89 * to perform cleanup should be modified to use alternative cleanup mechanisms such
90 * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
91 *
92 * @see Inflater
93 * @author David Connelly
94 * @since 1.1
95 */
96
97 public class Deflater {
98
99 private final DeflaterZStreamRef zsRef;
100 private ByteBuffer input = ZipUtils.defaultBuf;
101 private byte[] inputArray;
102 private int inputPos, inputLim;
103 private int level, strategy;
104 private boolean setParams;
105 private boolean finish, finished;
106 private long bytesRead;
107 private long bytesWritten;
108
109 /**
110 * Compression method for the deflate algorithm (the only one currently
111 * supported).
180 * Flush mode to use at the end of output. Can only be provided by the
181 * user by way of {@link #finish()}.
182 */
183 private static final int FINISH = 4;
184
185 static {
186 ZipUtils.loadLibrary();
187 }
188
189 /**
190 * Creates a new compressor using the specified compression level.
191 * If 'nowrap' is true then the ZLIB header and checksum fields will
192 * not be used in order to support the compression format used in
193 * both GZIP and PKZIP.
194 * @param level the compression level (0-9)
195 * @param nowrap if true then use GZIP compatible compression
196 */
197 public Deflater(int level, boolean nowrap) {
198 this.level = level;
199 this.strategy = DEFAULT_STRATEGY;
200 this.zsRef = new DeflaterZStreamRef(this,
201 init(level, DEFAULT_STRATEGY, nowrap));
202 }
203
204 /**
205 * Creates a new compressor using the specified compression level.
206 * Compressed data will be generated in ZLIB format.
207 * @param level the compression level (0-9)
208 */
209 public Deflater(int level) {
210 this(level, false);
211 }
212
213 /**
214 * Creates a new compressor with the default compression level.
215 * Compressed data will be generated in ZLIB format.
216 */
217 public Deflater() {
218 this(DEFAULT_COMPRESSION, false);
219 }
220
877 input = ZipUtils.defaultBuf;
878 inputArray = null;
879 bytesRead = bytesWritten = 0;
880 }
881 }
882
883 /**
884 * Closes the compressor and discards any unprocessed input.
885 *
886 * This method should be called when the compressor is no longer
887 * being used. Once this method is called, the behavior of the
888 * Deflater object is undefined.
889 */
890 public void end() {
891 synchronized (zsRef) {
892 zsRef.clean();
893 input = ZipUtils.defaultBuf;
894 }
895 }
896
897 private void ensureOpen() {
898 assert Thread.holdsLock(zsRef);
899 if (zsRef.address() == 0)
900 throw new NullPointerException("Deflater has been closed");
901 }
902
903 private static native long init(int level, int strategy, boolean nowrap);
904 private static native void setDictionary(long addr, byte[] b, int off,
905 int len);
906 private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
907 private native long deflateBytesBytes(long addr,
908 byte[] inputArray, int inputOff, int inputLen,
909 byte[] outputArray, int outputOff, int outputLen,
910 int flush, int params);
911 private native long deflateBytesBuffer(long addr,
912 byte[] inputArray, int inputOff, int inputLen,
913 long outputAddress, int outputLen,
914 int flush, int params);
915 private native long deflateBufferBytes(long addr,
916 long inputAddress, int inputLen,
938 this.cleanable = (owner != null) ? CleanerFactory.cleaner().register(owner, this) : null;
939 this.address = addr;
940 }
941
942 long address() {
943 return address;
944 }
945
946 void clean() {
947 cleanable.clean();
948 }
949
950 public synchronized void run() {
951 long addr = address;
952 address = 0;
953 if (addr != 0) {
954 end(addr);
955 }
956 }
957
958 }
959 }
|