Projects
Mega:24.03:SP1:Everything
openjdk-1.8.0
_service:tar_scm:KAE-zip-support-streaming-data...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:KAE-zip-support-streaming-data-decompression.patch of Package openjdk-1.8.0
--- jdk/make/mapfiles/libzip/mapfile-vers | 5 +- .../share/classes/java/util/zip/Deflater.java | 36 +++++-- .../java/util/zip/GZIPInputStream.java | 73 +++++++++++--- .../java/util/zip/GZIPOutputStream.java | 44 +++++---- .../share/classes/java/util/zip/Inflater.java | 37 +++++--- .../java/util/zip/InflaterInputStream.java | 25 +++++ jdk/src/share/lib/security/java.policy | 2 + jdk/src/share/native/java/util/zip/Deflater.c | 9 +- jdk/src/share/native/java/util/zip/Inflater.c | 73 +------------- .../java/util/zip/GZIP/TestAvailable.java | 94 +++++++++++++++++++ 10 files changed, 272 insertions(+), 126 deletions(-) create mode 100644 jdk/test/java/util/zip/GZIP/TestAvailable.java diff --git a/jdk/make/mapfiles/libzip/mapfile-vers b/jdk/make/mapfiles/libzip/mapfile-vers index 5c6d27d0d..79ef59e5f 100644 --- a/jdk/make/mapfiles/libzip/mapfile-vers +++ b/jdk/make/mapfiles/libzip/mapfile-vers @@ -38,16 +38,15 @@ SUNWprivate_1.1 { Java_java_util_zip_Deflater_end; Java_java_util_zip_Deflater_getAdler; Java_java_util_zip_Deflater_init; - Java_java_util_zip_Deflater_initKae; + Java_java_util_zip_Deflater_initKAE; Java_java_util_zip_Deflater_initIDs; Java_java_util_zip_Deflater_reset; Java_java_util_zip_Deflater_setDictionary; Java_java_util_zip_Inflater_end; Java_java_util_zip_Inflater_getAdler; Java_java_util_zip_Inflater_inflateBytes; - Java_java_util_zip_Inflater_inflateBytesKAE; Java_java_util_zip_Inflater_init; - Java_java_util_zip_Inflater_initKae; + Java_java_util_zip_Inflater_initKAE; Java_java_util_zip_Inflater_initIDs; Java_java_util_zip_Inflater_reset; Java_java_util_zip_Inflater_setDictionary; diff --git a/jdk/src/share/classes/java/util/zip/Deflater.java b/jdk/src/share/classes/java/util/zip/Deflater.java index a4ea40cf8..509808349 100644 --- a/jdk/src/share/classes/java/util/zip/Deflater.java +++ b/jdk/src/share/classes/java/util/zip/Deflater.java @@ -81,7 +81,6 @@ class Deflater { private boolean finish, finished; private long bytesRead; private long bytesWritten; - private boolean defalterUseKae; /** * Compression method for the deflate algorithm (the only one currently @@ -169,13 +168,20 @@ class Deflater { public Deflater(int level, boolean nowrap) { this.level = level; this.strategy = DEFAULT_STRATEGY; - if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) && - ("aarch64".equals(System.getProperty("os.arch")))) { - this.defalterUseKae = true; - } - this.zsRef = defalterUseKae ? - new ZStreamRef(initKae(level, DEFAULT_STRATEGY)) : - new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap)); + this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap)); + } + + /** + * Creates a new compressor using the specified compression level + * and windowBits. + * This method is mainly used to support the KAE-zip feature. + * @param level the compression level (0-9) + * @param windowBits compression format (-15~31) + */ + public Deflater(int level, int windowBits) { + this.level = level; + this.strategy = DEFAULT_STRATEGY; + this.zsRef = new ZStreamRef(initKAE(level, DEFAULT_STRATEGY, windowBits)); } /** @@ -535,6 +541,18 @@ class Deflater { } } + /** + * Resets deflater so that a new set of input data can be processed. + * Java fields are not initialized. + * This method is mainly used to support the KAE-zip feature. + */ + public void resetKAE() { + synchronized (zsRef) { + ensureOpen(); + reset(zsRef.address()); + } + } + /** * Closes the compressor and discards any unprocessed input. * This method should be called when the compressor is no longer @@ -578,7 +596,7 @@ class Deflater { private static native void initIDs(); private native static long init(int level, int strategy, boolean nowrap); - private native static long initKae(int level, int strategy); + private native static long initKAE(int level, int strategy, int windowBits); private native static void setDictionary(long addr, byte[] b, int off, int len); private native int deflateBytes(long addr, byte[] b, int off, int len, int flush); diff --git a/jdk/src/share/classes/java/util/zip/GZIPInputStream.java b/jdk/src/share/classes/java/util/zip/GZIPInputStream.java index 7fb753729..10d044caf 100644 --- a/jdk/src/share/classes/java/util/zip/GZIPInputStream.java +++ b/jdk/src/share/classes/java/util/zip/GZIPInputStream.java @@ -54,10 +54,22 @@ class GZIPInputStream extends InflaterInputStream { private boolean closed = false; - /* - * GZIP use KAE. + /** + * The field is mainly used to support the KAE-zip feature. */ - private boolean gzipUseKae = false; + private static boolean GZIP_USE_KAE = false; + + private static int WINDOWBITS = 31; + + private static int FLUSHKAE = 2; + + static { + if ("aarch64".equals(System.getProperty("os.arch"))) { + GZIP_USE_KAE = Boolean.parseBoolean(System.getProperty("GZIP_USE_KAE", "false")); + WINDOWBITS = Integer.parseInt(System.getProperty("WINDOWBITS", "31")); + FLUSHKAE = Integer.parseInt(System.getProperty("FLUSHKAE", "2")); + } + } /** * Check to make sure that this stream has not been closed @@ -79,14 +91,13 @@ class GZIPInputStream extends InflaterInputStream { * @exception IllegalArgumentException if {@code size <= 0} */ public GZIPInputStream(InputStream in, int size) throws IOException { - super(in, new Inflater(true), size); + super(in, GZIP_USE_KAE ? new Inflater(WINDOWBITS, FLUSHKAE) : new Inflater(true), size); usesDefaultInflater = true; - if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) && - ("aarch64".equals(System.getProperty("os.arch")))) { - gzipUseKae = true; - } - // file header will be readed by kae zlib when use kae - if (gzipUseKae) return; + + // When GZIP_USE_KAE is true, the header of the file is readed + // through the native zlib library, not in java code. + if (GZIP_USE_KAE) return; + readHeader(in); } @@ -127,13 +138,16 @@ class GZIPInputStream extends InflaterInputStream { } int n = super.read(buf, off, len); if (n == -1) { - if (readTrailer()) + if (GZIP_USE_KAE ? readTrailerKAE() : readTrailer()) eos = true; else return this.read(buf, off, len); } else { crc.update(buf, off, n); } + if (GZIP_USE_KAE && inf.finished()) { + if (readTrailerKAE()) eos = true; + } return n; } @@ -220,9 +234,7 @@ class GZIPInputStream extends InflaterInputStream { * data set) */ private boolean readTrailer() throws IOException { - // file trailer will be readed by kae zlib when use kae - if (gzipUseKae) return true; - + if (GZIP_USE_KAE) return true; InputStream in = this.in; int n = inf.getRemaining(); if (n > 0) { @@ -251,6 +263,39 @@ class GZIPInputStream extends InflaterInputStream { return false; } + /* + * Reads GZIP member trailer and returns true if the eos + * reached, false if there are more (concatenated gzip + * data set) + * + * This method is mainly used to support the KAE-zip feature. + */ + private boolean readTrailerKAE() throws IOException { + InputStream in = this.in; + int n = inf.getRemaining(); + if (n > 0) { + in = new SequenceInputStream( + new ByteArrayInputStream(buf, len - n, n), + new FilterInputStream(in) { + public void close() throws IOException {} + }); + } + // If there are more bytes available in "in" or the leftover in the "inf" is > 18 bytes: + // next.header.min(10) + next.trailer(8), try concatenated case + + if (n > 18) { + inf.reset(); + inf.setInput(buf, len - n, n); + } else { + try { + fillKAE(n); + } catch (IOException e) { + return true; + } + } + return false; + } + /* * Reads unsigned integer in Intel byte order. */ diff --git a/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java b/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java index 0f0be98bb..8eae40739 100644 --- a/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java +++ b/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java @@ -52,10 +52,19 @@ class GZIPOutputStream extends DeflaterOutputStream { */ private final static int TRAILER_SIZE = 8; - /* - * GZIP use KAE. + /** + * The field is mainly used to support the KAE-zip feature. */ - private boolean gzipUseKae = false; + private static boolean GZIP_USE_KAE = false; + + private static int WINDOWBITS = 31; + + static { + if ("aarch64".equals(System.getProperty("os.arch"))) { + GZIP_USE_KAE = Boolean.parseBoolean(System.getProperty("GZIP_USE_KAE", "false")); + WINDOWBITS = Integer.parseInt(System.getProperty("WINDOWBITS", "31")); + } + } /** * Creates a new output stream with the specified buffer size. @@ -92,16 +101,15 @@ class GZIPOutputStream extends DeflaterOutputStream { public GZIPOutputStream(OutputStream out, int size, boolean syncFlush) throws IOException { - super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true), + super(out, GZIP_USE_KAE ? new Deflater(Deflater.DEFAULT_COMPRESSION, WINDOWBITS) : + new Deflater(Deflater.DEFAULT_COMPRESSION, true), size, syncFlush); usesDefaultDeflater = true; - if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) && - ("aarch64".equals(System.getProperty("os.arch")))) { - gzipUseKae = true; - } - // file header will be writed by kae zlib when use kae - if (gzipUseKae) return; + + // When GZIP_USE_KAE is true, the header of the file is written + // through the native zlib library, not in java code. + if (GZIP_USE_KAE) return; writeHeader(); crc.reset(); } @@ -171,9 +179,11 @@ class GZIPOutputStream extends DeflaterOutputStream { int len = def.deflate(buf, 0, buf.length); if (def.finished() && len <= buf.length - TRAILER_SIZE) { // last deflater buffer. Fit trailer at the end - // file trailer will be writed by kae zlib when use kae - if (gzipUseKae) { + // When GZIP_USE_KAE is true, the trailer of the file is written + // through the native zlib library, not in java code. + if (GZIP_USE_KAE) { out.write(buf, 0, len); + def.resetKAE(); return; } writeTrailer(buf, len); @@ -184,12 +194,14 @@ class GZIPOutputStream extends DeflaterOutputStream { if (len > 0) out.write(buf, 0, len); } - // file trailer will be writed by kae zlib when use kae - if (gzipUseKae) { - return; - } // if we can't fit the trailer at the end of the last // deflater buffer, we write it separately + // When GZIP_USE_KAE is true, the trailer of the file is written + // through the native zlib library, not in java code. + if (GZIP_USE_KAE) { + def.resetKAE(); + return; + } byte[] trailer = new byte[TRAILER_SIZE]; writeTrailer(trailer, 0); out.write(trailer); diff --git a/jdk/src/share/classes/java/util/zip/Inflater.java b/jdk/src/share/classes/java/util/zip/Inflater.java index 42e90f525..d1074cd8d 100644 --- a/jdk/src/share/classes/java/util/zip/Inflater.java +++ b/jdk/src/share/classes/java/util/zip/Inflater.java @@ -80,7 +80,6 @@ class Inflater { private boolean needDict; private long bytesRead; private long bytesWritten; - private boolean inflaterUseKae; private static final byte[] defaultBuf = new byte[0]; @@ -101,11 +100,18 @@ class Inflater { * @param nowrap if true then support GZIP compatible compression */ public Inflater(boolean nowrap) { - if (("true".equals(System.getProperty("GZIP_USE_KAE", "false"))) && - ("aarch64".equals(System.getProperty("os.arch")))) { - inflaterUseKae = true; - } - zsRef = inflaterUseKae ? new ZStreamRef(initKae()): new ZStreamRef(init(nowrap)); + zsRef = new ZStreamRef(init(nowrap)); + } + + /** + * Creates a new decompressor. + * This method is mainly used to support the KAE-zip feature. + * + * @param windowBits compression format (-15~31) + * @param flushKAE inflate flush type (0~6) + */ + public Inflater(int windowBits, int flushKAE) { + this.zsRef = new ZStreamRef(initKAE(windowBits, flushKAE)); } /** @@ -261,9 +267,7 @@ class Inflater { synchronized (zsRef) { ensureOpen(); int thisLen = this.len; - int n = this.inflaterUseKae ? - inflateBytesKAE(zsRef.address(), b, off, len) : - inflateBytes(zsRef.address(), b, off, len); + int n = inflateBytes(zsRef.address(), b, off, len); bytesWritten += n; bytesRead += (thisLen - this.len); return n; @@ -365,6 +369,17 @@ class Inflater { } } + /** + * Resets inflater so that a new set of input data can be processed. + * This method is mainly used to support the KAE-zip feature. + */ + public void resetKAE() { + synchronized (zsRef) { + ensureOpen(); + reset(zsRef.address()); + } + } + /** * Closes the decompressor and discards any unprocessed input. * This method should be called when the decompressor is no longer @@ -404,13 +419,11 @@ class Inflater { private native static void initIDs(); private native static long init(boolean nowrap); - private native static long initKae(); + private native static long initKAE(int windowBits, int flushKAE); private native static void setDictionary(long addr, byte[] b, int off, int len); private native int inflateBytes(long addr, byte[] b, int off, int len) throws DataFormatException; - private native int inflateBytesKAE(long addr, byte[] b, int off, int len) - throws DataFormatException; private native static int getAdler(long addr); private native static void reset(long addr); private native static void end(long addr); diff --git a/jdk/src/share/classes/java/util/zip/InflaterInputStream.java b/jdk/src/share/classes/java/util/zip/InflaterInputStream.java index 163f619c1..b0ac7dd26 100644 --- a/jdk/src/share/classes/java/util/zip/InflaterInputStream.java +++ b/jdk/src/share/classes/java/util/zip/InflaterInputStream.java @@ -179,6 +179,10 @@ class InflaterInputStream extends FilterInputStream { ensureOpen(); if (reachEOF) { return 0; + } else if (inf.finished()) { + // the end of the compressed data stream has been reached + reachEOF = true; + return 0; } else { return 1; } @@ -242,6 +246,27 @@ class InflaterInputStream extends FilterInputStream { inf.setInput(buf, 0, len); } + /** + * Fills input buffer with more data to decompress. + * This method is mainly used to support the KAE-zip feature. + * @param n Maximum Read Bytes + * @throws IOException if an I/O error has occurred + */ + protected void fillKAE(int n) throws IOException { + ensureOpen(); + byte[] buftmp = new byte[buf.length]; + if (n != 0) { + System.arraycopy(buf, buf.length - n, buftmp, 0, n); + } + int kaelen = in.read(buftmp, n, buf.length - n); + if (kaelen == -1) { + throw new EOFException("Unexpected end of ZLIB input stream"); + } + System.arraycopy(buftmp, 0, buf, buf.length - n - kaelen, n + kaelen); + inf.reset(); + inf.setInput(buf, buf.length - n - kaelen, n + kaelen); + } + /** * Tests if this input stream supports the <code>mark</code> and * <code>reset</code> methods. The <code>markSupported</code> diff --git a/jdk/src/share/lib/security/java.policy b/jdk/src/share/lib/security/java.policy index baec2ea15..284e3e334 100644 --- a/jdk/src/share/lib/security/java.policy +++ b/jdk/src/share/lib/security/java.policy @@ -50,5 +50,7 @@ grant { permission java.util.PropertyPermission "sun.security.pkcs11.disableKeyExtraction", "read"; permission java.util.PropertyPermission "GZIP_USE_KAE", "read"; + permission java.util.PropertyPermission "WINDOWBITS", "read"; + permission java.util.PropertyPermission "FLUSHKAE", "read"; }; diff --git a/jdk/src/share/native/java/util/zip/Deflater.c b/jdk/src/share/native/java/util/zip/Deflater.c index 1b048e4f5..b26eb1392 100644 --- a/jdk/src/share/native/java/util/zip/Deflater.c +++ b/jdk/src/share/native/java/util/zip/Deflater.c @@ -37,7 +37,6 @@ #include "java_util_zip_Deflater.h" #define DEF_MEM_LEVEL 8 -#define KAE_DEFLATER_WindowBit 31 static jfieldID levelID; static jfieldID strategyID; @@ -106,8 +105,8 @@ Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level, } JNIEXPORT jlong JNICALL -Java_java_util_zip_Deflater_initKae(JNIEnv *env, jclass cls, jint level, - jint strategy) +Java_java_util_zip_Deflater_initKAE(JNIEnv *env, jclass cls, jint level, + jint strategy, jint windowBits) { z_stream *strm = calloc(1, sizeof(z_stream)); @@ -116,7 +115,9 @@ Java_java_util_zip_Deflater_initKae(JNIEnv *env, jclass cls, jint level, return jlong_zero; } else { const char *msg; - int ret = deflateInit2(strm, level, Z_DEFLATED, KAE_DEFLATER_WindowBit, DEF_MEM_LEVEL, strategy); + int ret = deflateInit2(strm, level, Z_DEFLATED, + windowBits, + DEF_MEM_LEVEL, strategy); switch (ret) { case Z_OK: return ptr_to_jlong(strm); diff --git a/jdk/src/share/native/java/util/zip/Inflater.c b/jdk/src/share/native/java/util/zip/Inflater.c index fca207215..8317267ff 100644 --- a/jdk/src/share/native/java/util/zip/Inflater.c +++ b/jdk/src/share/native/java/util/zip/Inflater.c @@ -41,11 +41,11 @@ #define ThrowDataFormatException(env, msg) \ JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg) -#define KAE_INFLATER_WindowBit 31 static jfieldID needDictID; static jfieldID finishedID; static jfieldID bufID, offID, lenID; +static jint inflaterFlushType = Z_PARTIAL_FLUSH; JNIEXPORT void JNICALL Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls) @@ -96,16 +96,17 @@ Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap) } JNIEXPORT jlong JNICALL -Java_java_util_zip_Inflater_initKae(JNIEnv *env, jclass cls) +Java_java_util_zip_Inflater_initKAE(JNIEnv *env, jclass cls, jint windowBits, jint flushKAE) { z_stream *strm = calloc(1, sizeof(z_stream)); + inflaterFlushType = flushKAE; if (strm == NULL) { JNU_ThrowOutOfMemoryError(env, 0); return jlong_zero; } else { const char *msg; - int ret = inflateInit2(strm, KAE_INFLATER_WindowBit); + int ret = inflateInit2(strm, windowBits); switch (ret) { case Z_OK: return ptr_to_jlong(strm); @@ -181,71 +182,7 @@ Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr, strm->next_out = (Bytef *) (out_buf + off); strm->avail_in = this_len; strm->avail_out = len; - ret = inflate(strm, Z_PARTIAL_FLUSH); - (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0); - (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); - - switch (ret) { - case Z_STREAM_END: - (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE); - /* fall through */ - case Z_OK: - this_off += this_len - strm->avail_in; - (*env)->SetIntField(env, this, offID, this_off); - (*env)->SetIntField(env, this, lenID, strm->avail_in); - return (jint) (len - strm->avail_out); - case Z_NEED_DICT: - (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE); - /* Might have consumed some input here! */ - this_off += this_len - strm->avail_in; - (*env)->SetIntField(env, this, offID, this_off); - (*env)->SetIntField(env, this, lenID, strm->avail_in); - return 0; - case Z_BUF_ERROR: - return 0; - case Z_DATA_ERROR: - ThrowDataFormatException(env, strm->msg); - return 0; - case Z_MEM_ERROR: - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - default: - JNU_ThrowInternalError(env, strm->msg); - return 0; - } -} - -JNIEXPORT jint JNICALL -Java_java_util_zip_Inflater_inflateBytesKAE(JNIEnv *env, jobject this, jlong addr, - jarray b, jint off, jint len) -{ - z_stream *strm = jlong_to_ptr(addr); - jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID); - jint this_off = (*env)->GetIntField(env, this, offID); - jint this_len = (*env)->GetIntField(env, this, lenID); - - jbyte *in_buf; - jbyte *out_buf; - int ret; - - in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0); - if (in_buf == NULL) { - if (this_len != 0 && (*env)->ExceptionOccurred(env) == NULL) - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - } - out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); - if (out_buf == NULL) { - (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); - if (len != 0 && (*env)->ExceptionOccurred(env) == NULL) - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - } - strm->next_in = (Bytef *) (in_buf + this_off); - strm->next_out = (Bytef *) (out_buf + off); - strm->avail_in = this_len; - strm->avail_out = len; - ret = inflate(strm, Z_SYNC_FLUSH); + ret = inflate(strm, inflaterFlushType); (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0); (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); diff --git a/jdk/test/java/util/zip/GZIP/TestAvailable.java b/jdk/test/java/util/zip/GZIP/TestAvailable.java new file mode 100644 index 000000000..3dc9b3445 --- /dev/null +++ b/jdk/test/java/util/zip/GZIP/TestAvailable.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @library /lib/testlibrary/ + * @build jdk.testlibrary.* + * @run main TestAvailable + * @bug 7031075 + * @summary Make sure that available() method behaves as expected. + * @key randomness + */ + +import java.io.*; +import java.util.Random; +import java.util.zip.*; +import jdk.testlibrary.RandomFactory; + +public class TestAvailable { + + public static void main(String args[]) throws Throwable { + Random r = RandomFactory.getRandom(); + for (int n = 0; n < 10; n++) { + byte[] src = new byte[r.nextInt(100)]; + r.nextBytes(src); + + // test InflaterInputStream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (DeflaterOutputStream dos = new DeflaterOutputStream(baos)) { + dos.write(src); + } + try (InflaterInputStream iis = new InflaterInputStream( + new ByteArrayInputStream(baos.toByteArray()))) { + test(iis, src); + } + + // test GZIPInputStream + baos = new ByteArrayOutputStream(); + try (GZIPOutputStream dos = new GZIPOutputStream(baos)) { + dos.write(src); + } + try (GZIPInputStream gis = new GZIPInputStream( + new ByteArrayInputStream(baos.toByteArray()))) { + test(gis, src); + } + } + } + + private static void test(InputStream is, byte[] expected) throws IOException { + int cnt = 0; + do { + int available = is.available(); + if (available > 0) { + int b = is.read(); + if (b == -1) { + throw new RuntimeException("available() > 0, read() == -1 : failed!"); + } + if (expected[cnt++] != (byte)b) { + throw new RuntimeException("read() : failed!"); + } + } else if (available == 0) { + if (is.read() != -1) { + throw new RuntimeException("available() == 0, read() != -1 : failed!"); + } + break; + } else { + throw new RuntimeException("available() < 0 : failed!"); + } + } while (true); + if (cnt != expected.length) { + throw new RuntimeException("read : failed!"); + } + } + +} \ No newline at end of file -- 2.19.1
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2