diff --git a/pom.xml b/pom.xml
index da9f090..e30528a 100755
--- a/pom.xml
+++ b/pom.xml
@@ -232,5 +232,12 @@
jar
test
+
+ org.javassist
+ javassist
+ 3.14.0-GA
+ jar
+ test
+
diff --git a/src/main/java/org/xerial/snappy/Snappy.java b/src/main/java/org/xerial/snappy/Snappy.java
index d31c972..efebec4 100755
--- a/src/main/java/org/xerial/snappy/Snappy.java
+++ b/src/main/java/org/xerial/snappy/Snappy.java
@@ -24,6 +24,7 @@
//--------------------------------------
package org.xerial.snappy;
+import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
@@ -49,9 +50,9 @@ public class Snappy
* @param input
* the input data
* @return the compressed byte array
- * @throws SnappyException
+ * @throws IOException
*/
- public static byte[] compress(byte[] input) throws SnappyException {
+ public static byte[] compress(byte[] input) throws IOException {
return rawCompress(input, input.length);
}
@@ -65,11 +66,11 @@ public class Snappy
* @param output
* @param outputOffset
* @return byte size of the compressed data
- * @throws SnappyException
+ * @throws IOException
* when failed to access the input/output buffer
*/
public static int compress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)
- throws SnappyException {
+ throws IOException {
return rawCompress(input, inputOffset, inputLength, output, outputOffset);
}
@@ -87,7 +88,7 @@ public class Snappy
* @throws SnappyError
* when the input is not a direct buffer
*/
- public static int compress(ByteBuffer uncompressed, ByteBuffer compressed) throws SnappyException {
+ public static int compress(ByteBuffer uncompressed, ByteBuffer compressed) throws IOException {
if (!uncompressed.isDirect())
throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer");
@@ -131,7 +132,7 @@ public class Snappy
return rawCompress(input, input.length * 2); // short uses 2 bytes
}
- public static byte[] compress(String s) throws SnappyException {
+ public static byte[] compress(String s) throws IOException {
try {
return compress(s, "UTF-8");
}
@@ -140,7 +141,7 @@ public class Snappy
}
}
- public static byte[] compress(String s, String encoding) throws UnsupportedEncodingException, SnappyException {
+ public static byte[] compress(String s, String encoding) throws UnsupportedEncodingException, IOException {
byte[] data = s.getBytes(encoding);
return compress(data);
}
@@ -160,7 +161,7 @@ public class Snappy
* uncompressed data. Takes time proportional to the input length, but is
* usually at least a factor of four faster than actual decompression.
*/
- public static boolean isValidCompressedBuffer(byte[] input, int offset, int length) throws SnappyException {
+ public static boolean isValidCompressedBuffer(byte[] input, int offset, int length) throws IOException {
if (input == null)
throw new NullPointerException("input is null");
return SnappyNative.isValidCompressedBuffer(input, offset, length);
@@ -172,7 +173,7 @@ public class Snappy
* uncompressed data. Takes time proportional to the input length, but is
* usually at least a factor of four faster than actual decompression.
*/
- public static boolean isValidCompressedBuffer(byte[] input) throws SnappyException {
+ public static boolean isValidCompressedBuffer(byte[] input) throws IOException {
return isValidCompressedBuffer(input, 0, input.length);
}
@@ -182,7 +183,7 @@ public class Snappy
* Takes time proportional to the input length, but is usually at least a
* factor of four faster than actual decompression.
*/
- public static boolean isValidCompressedBuffer(ByteBuffer compressed) throws SnappyException {
+ public static boolean isValidCompressedBuffer(ByteBuffer compressed) throws IOException {
return SnappyNative.isValidCompressedBuffer(compressed, compressed.position(), compressed.remaining());
}
@@ -230,10 +231,10 @@ public class Snappy
* @param outputOffset
* byte offset at the output array
* @return byte size of the compressed data
- * @throws SnappyException
+ * @throws IOException
*/
public static int rawCompress(Object input, int inputOffset, int inputLength, byte[] output, int outputOffset)
- throws SnappyException {
+ throws IOException {
if (input == null || output == null)
throw new NullPointerException("input or output is null");
@@ -262,10 +263,10 @@ public class Snappy
* @param outputOffset
* byte offset
* @return the byte size of the uncompressed data
- * @throws SnappyException
+ * @throws IOException
*/
public static int rawUncompress(byte[] input, int inputOffset, int inputLength, Object output, int outputOffset)
- throws SnappyException {
+ throws IOException {
if (input == null || output == null)
throw new NullPointerException("input or output is null");
return SnappyNative.rawUncompress(input, inputOffset, inputLength, output, outputOffset);
@@ -276,9 +277,9 @@ public class Snappy
*
* @param input
* @return the uncompressed byte array
- * @throws SnappyException
+ * @throws IOException
*/
- public static byte[] uncompress(byte[] input) throws SnappyException {
+ public static byte[] uncompress(byte[] input) throws IOException {
byte[] result = new byte[Snappy.uncompressedLength(input)];
int byteSize = Snappy.uncompress(input, 0, input.length, result, 0);
return result;
@@ -300,10 +301,10 @@ public class Snappy
* @param output
* @param outputOffset
* @return the byte size of the uncompressed data
- * @throws SnappyException
+ * @throws IOException
*/
public static int uncompress(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset)
- throws SnappyException {
+ throws IOException {
return rawUncompress(input, inputOffset, inputLength, output, outputOffset);
}
@@ -323,12 +324,12 @@ public class Snappy
* output of the the uncompressed data. It uses buffer[pot()..]
* @return uncompressed data size
*
- * @throws SnappyException
+ * @throws IOException
* when failed to uncompress the given input
* @throws SnappyError
* when the input is not a direct buffer
*/
- public static int uncompress(ByteBuffer compressed, ByteBuffer uncompressed) throws SnappyException {
+ public static int uncompress(ByteBuffer compressed, ByteBuffer uncompressed) throws IOException {
if (!compressed.isDirect())
throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer");
@@ -347,18 +348,18 @@ public class Snappy
return decompressedSize;
}
- public static char[] uncompressCharArray(byte[] input) throws SnappyException {
+ public static char[] uncompressCharArray(byte[] input) throws IOException {
return uncompressCharArray(input, 0, input.length);
}
- public static char[] uncompressCharArray(byte[] input, int offset, int length) throws SnappyException {
+ public static char[] uncompressCharArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
char[] result = new char[uncompressedLength / 2];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
- public static double[] uncompressDoubleArray(byte[] input) throws SnappyException {
+ public static double[] uncompressDoubleArray(byte[] input) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, 0, input.length);
double[] result = new double[uncompressedLength / 8];
int byteSize = SnappyNative.rawUncompress(input, 0, input.length, result, 0);
@@ -371,11 +372,11 @@ public class Snappy
*
* @param input
* @return umcompressed byte size of the the given input data
- * @throws SnappyException
+ * @throws IOException
* when failed to uncompress the given input. The error code is
* {@link SnappyErrorCode#PARSING_ERROR}
*/
- public static int uncompressedLength(byte[] input) throws SnappyException {
+ public static int uncompressedLength(byte[] input) throws IOException {
return SnappyNative.uncompressedLength(input, 0, input.length);
}
@@ -387,11 +388,11 @@ public class Snappy
* @param offset
* @param length
* @return umcompressed byte size of the the given input data
- * @throws SnappyException
+ * @throws IOException
* when failed to uncompress the given input. The error code is
* {@link SnappyErrorCode#PARSING_ERROR}
*/
- public static int uncompressedLength(byte[] input, int offset, int length) throws SnappyException {
+ public static int uncompressedLength(byte[] input, int offset, int length) throws IOException {
if (input == null)
throw new NullPointerException("input is null");
@@ -409,8 +410,7 @@ public class Snappy
}
}
- public static CompressedDataLength getUncompressedLength(byte[] input, int offset, int limit)
- throws SnappyException {
+ public static CompressedDataLength getUncompressedLength(byte[] input, int offset, int limit) throws IOException {
if (input == null)
throw new NullPointerException("input is null");
@@ -463,64 +463,64 @@ public class Snappy
* @param compressed
* input data [pos() ... limit())
* @return uncompressed byte length of the given input
- * @throws SnappyException
+ * @throws IOException
* when failed to uncompress the given input. The error code is
* {@link SnappyErrorCode#PARSING_ERROR}
* @throws SnappyError
* when the input is not a direct buffer
*/
- public static int uncompressedLength(ByteBuffer compressed) throws SnappyException {
+ public static int uncompressedLength(ByteBuffer compressed) throws IOException {
if (!compressed.isDirect())
throw new SnappyError(SnappyErrorCode.NOT_A_DIRECT_BUFFER, "input is not a direct buffer");
return SnappyNative.uncompressedLength(compressed, compressed.position(), compressed.remaining());
}
- public static float[] uncompressFloatArray(byte[] input) throws SnappyException {
+ public static float[] uncompressFloatArray(byte[] input) throws IOException {
return uncompressFloatArray(input, 0, input.length);
}
- public static float[] uncompressFloatArray(byte[] input, int offset, int length) throws SnappyException {
+ public static float[] uncompressFloatArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
float[] result = new float[uncompressedLength / 4];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
- public static int[] uncompressIntArray(byte[] input) throws SnappyException {
+ public static int[] uncompressIntArray(byte[] input) throws IOException {
return uncompressIntArray(input, 0, input.length);
}
- public static int[] uncompressIntArray(byte[] input, int offset, int length) throws SnappyException {
+ public static int[] uncompressIntArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
int[] result = new int[uncompressedLength / 4];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
- public static long[] uncompressLongArray(byte[] input) throws SnappyException {
+ public static long[] uncompressLongArray(byte[] input) throws IOException {
return uncompressLongArray(input, 0, input.length);
}
- public static long[] uncompressLongArray(byte[] input, int offset, int length) throws SnappyException {
+ public static long[] uncompressLongArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
long[] result = new long[uncompressedLength / 8];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
- public static short[] uncompressShortArray(byte[] input) throws SnappyException {
+ public static short[] uncompressShortArray(byte[] input) throws IOException {
return uncompressShortArray(input, 0, input.length);
}
- public static short[] uncompressShortArray(byte[] input, int offset, int length) throws SnappyException {
+ public static short[] uncompressShortArray(byte[] input, int offset, int length) throws IOException {
int uncompressedLength = Snappy.uncompressedLength(input, offset, length);
short[] result = new short[uncompressedLength / 2];
int byteSize = SnappyNative.rawUncompress(input, offset, length, result, 0);
return result;
}
- public static String uncompressString(byte[] input) throws SnappyException {
+ public static String uncompressString(byte[] input) throws IOException {
try {
return uncompressString(input, "UTF-8");
}
@@ -529,7 +529,7 @@ public class Snappy
}
}
- public static String uncompressString(byte[] input, int offset, int length) throws SnappyException {
+ public static String uncompressString(byte[] input, int offset, int length) throws IOException {
try {
return uncompressString(input, offset, length, "UTF-8");
}
@@ -538,14 +538,14 @@ public class Snappy
}
}
- public static String uncompressString(byte[] input, int offset, int length, String encoding)
- throws SnappyException, UnsupportedEncodingException {
+ public static String uncompressString(byte[] input, int offset, int length, String encoding) throws IOException,
+ UnsupportedEncodingException {
byte[] uncompressed = new byte[uncompressedLength(input, offset, length)];
int compressedSize = uncompress(input, offset, length, uncompressed, 0);
return new String(uncompressed, encoding);
}
- public static String uncompressString(byte[] input, String encoding) throws SnappyException,
+ public static String uncompressString(byte[] input, String encoding) throws IOException,
UnsupportedEncodingException {
byte[] uncompressed = uncompress(input);
return new String(uncompressed, encoding);
diff --git a/src/main/java/org/xerial/snappy/SnappyErrorCode.java b/src/main/java/org/xerial/snappy/SnappyErrorCode.java
index efdddc4..187b059 100755
--- a/src/main/java/org/xerial/snappy/SnappyErrorCode.java
+++ b/src/main/java/org/xerial/snappy/SnappyErrorCode.java
@@ -45,4 +45,12 @@ public enum SnappyErrorCode {
private SnappyErrorCode(int id) {
this.id = id;
}
+
+ public static String getErrorMessage(int id) {
+ for (SnappyErrorCode code : SnappyErrorCode.values()) {
+ if (code.id == id)
+ return code.name();
+ }
+ return UNKNOWN.name();
+ }
}
diff --git a/src/main/java/org/xerial/snappy/SnappyInputStream.java b/src/main/java/org/xerial/snappy/SnappyInputStream.java
index c94e747..04ca9d4 100755
--- a/src/main/java/org/xerial/snappy/SnappyInputStream.java
+++ b/src/main/java/org/xerial/snappy/SnappyInputStream.java
@@ -95,16 +95,11 @@ public class SnappyInputStream extends InputStream
finishedReading = true;
// Uncompress
- try {
- int uncompressedLength = Snappy.uncompressedLength(compressed, 0, cursor);
- uncompressed = new byte[uncompressedLength];
- Snappy.uncompress(compressed, 0, cursor, uncompressed, 0);
- this.uncompressedCursor = 0;
- this.uncompressedLimit = uncompressedLength;
- }
- catch (SnappyException e) {
- throw new IOException(e.getMessage());
- }
+ int uncompressedLength = Snappy.uncompressedLength(compressed, 0, cursor);
+ uncompressed = new byte[uncompressedLength];
+ Snappy.uncompress(compressed, 0, cursor, uncompressed, 0);
+ this.uncompressedCursor = 0;
+ this.uncompressedLimit = uncompressedLength;
}
@@ -160,7 +155,7 @@ public class SnappyInputStream extends InputStream
}
uncompressedLimit = actualUncompressedLength;
}
- catch (SnappyException e) {
+ catch (IOException e) {
throw new IOException("failed to uncompress the chunk: " + e.getMessage());
}
diff --git a/src/main/java/org/xerial/snappy/SnappyLoader.java b/src/main/java/org/xerial/snappy/SnappyLoader.java
index 8ee6a9c..2c31e5b 100755
--- a/src/main/java/org/xerial/snappy/SnappyLoader.java
+++ b/src/main/java/org/xerial/snappy/SnappyLoader.java
@@ -35,6 +35,9 @@ import java.net.URL;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Properties;
/**
@@ -77,13 +80,97 @@ import java.util.Properties;
*/
public class SnappyLoader
{
- private static boolean isLoaded = false;
+ private static boolean isInitialized = false;
+ private static boolean isLoaded = false;
+
+ private static ClassLoader getSystemClassLoader() {
+ ClassLoader cl = SnappyLoader.class.getClassLoader();
+ while (cl.getParent() != null) {
+ cl = cl.getParent();
+ }
+ return cl;
+ }
+
+ private static byte[] getByteCode(String resourcePath) throws IOException {
+
+ InputStream in = SnappyLoader.class.getResourceAsStream(resourcePath);
+ assert (in != null);
+ byte[] buf = new byte[1024];
+ ByteArrayOutputStream byteCodeBuf = new ByteArrayOutputStream();
+ for (int readLength; (readLength = in.read(buf)) != -1;) {
+ byteCodeBuf.write(buf, 0, readLength);
+ }
+ in.close();
+
+ return byteCodeBuf.toByteArray();
+ }
+
+ public static void load() {
+
+ if (!isInitialized) {
+ final String nativeLoaderClassName = "org.xerial.snappy.SnappyNativeLoader";
+ final String[] preloadClass = new String[] { "org.xerial.snappy.SnappyNative",
+ "org.xerial.snappy.SnappyErrorCode" };
+
+ try {
+ Class.forName(nativeLoaderClassName);
+ // If this native loader class is already defined, it means that another class loader already loaded the native library of snappy
+ isInitialized = true;
+ return;
+ }
+ catch (ClassNotFoundException e) {
+ try {
+ // Load a byte code
+ byte[] byteCode = getByteCode("/org/xerial/snappy/SnappyNativeLoader.bytecode");
+ // In addition, load the SnappyNative and SnappyException class in the system class loader
+ List preloadClassByteCode = new ArrayList(preloadClass.length);
+ for (String each : preloadClass) {
+ preloadClassByteCode.add(getByteCode(String.format("/%s.class", each.replaceAll("\\.", "/"))));
+ }
+
+ // Create a new class to the system class loader
+ Class< ? > classLoader = Class.forName("java.lang.ClassLoader");
+ java.lang.reflect.Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] {
+ String.class, byte[].class, int.class, int.class, ProtectionDomain.class });
+
+ ClassLoader systemClassLoader = getSystemClassLoader();
+ defineClass.setAccessible(true);
+ try {
+ // Load SnappyNativeLoader
+ defineClass.invoke(systemClassLoader, nativeLoaderClassName, byteCode, 0, byteCode.length,
+ System.class.getProtectionDomain());
+
+ for (int i = 0; i < preloadClass.length; ++i) {
+ byte[] b = preloadClassByteCode.get(i);
+ defineClass.invoke(systemClassLoader, preloadClass[i], b, 0, b.length,
+ System.class.getProtectionDomain());
+ }
+ }
+ finally {
+ defineClass.setAccessible(false);
+ }
+
+ // Load the loader class
+ Class< ? > loaderClass = systemClassLoader.loadClass(nativeLoaderClassName);
+ if (loaderClass != null) {
+ java.lang.reflect.Method loadMethod = loaderClass.getDeclaredMethod("load",
+ new Class[] { String.class });
+ File nativeLib = findNativeLibrary();
+ loadMethod.invoke(null, nativeLib.getAbsolutePath());
+
+ for (String each : preloadClass) {
+ systemClassLoader.loadClass(each);
+ }
+
+ isInitialized = true;
+ }
+ }
+ catch (Exception e2) {
+ e.printStackTrace();
+ }
+ }
- public static boolean load() {
- if (!isLoaded) {
- loadSnappyNativeLibrary();
}
- return isLoaded;
}
public static final String KEY_SNAPPY_LIB_PATH = "org.xerial.snappy.lib.path";
@@ -101,7 +188,6 @@ public class SnappyLoader
*/
static String md5sum(InputStream input) throws IOException {
BufferedInputStream in = new BufferedInputStream(input);
-
try {
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
DigestInputStream digestInputStream = new DigestInputStream(in, digest);
@@ -128,8 +214,7 @@ public class SnappyLoader
* @param targetFolder
* @return
*/
- private static boolean extractAndLoadLibraryFile(String libFolderForCurrentOS, String libraryFileName,
- String targetFolder) {
+ private static File extractLibraryFile(String libFolderForCurrentOS, String libraryFileName, String targetFolder) {
String nativeLibraryFilePath = libFolderForCurrentOS + "/" + libraryFileName;
final String prefix = "snappy-" + getVersion() + "-";
String extractedLibFileName = prefix + libraryFileName;
@@ -142,7 +227,7 @@ public class SnappyLoader
String md5sum2 = md5sum(new FileInputStream(extractedLibFile));
if (md5sum1.equals(md5sum2)) {
- return loadNativeLibrary(targetFolder, extractedLibFileName);
+ return new File(targetFolder, extractedLibFileName);
}
else {
// remove old native library file
@@ -154,10 +239,10 @@ public class SnappyLoader
}
}
- // extract a native library file into the target directory
+ // Extract a native library file into the target directory
InputStream reader = SnappyLoader.class.getResourceAsStream(nativeLibraryFilePath);
FileOutputStream writer = new FileOutputStream(extractedLibFile);
- byte[] buffer = new byte[1024];
+ byte[] buffer = new byte[8192];
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) != -1) {
writer.write(buffer, 0, bytesRead);
@@ -175,52 +260,46 @@ public class SnappyLoader
catch (Throwable e) {}
}
- return loadNativeLibrary(targetFolder, extractedLibFileName);
+ return new File(targetFolder, extractedLibFileName);
}
catch (IOException e) {
- System.err.println(e.getMessage());
- return false;
+ e.printStackTrace(System.err);
+ return null;
}
-
}
- private static synchronized boolean loadNativeLibrary(String path, String name) {
- File libPath = new File(path, name);
+ private static synchronized boolean loadNativeLibrary(File libPath) {
if (libPath.exists()) {
-
try {
- System.load(new File(path, name).getAbsolutePath());
+ System.load(libPath.getAbsolutePath());
return true;
}
catch (UnsatisfiedLinkError e) {
throw new SnappyError(SnappyErrorCode.FAILED_TO_LOAD_NATIVE_LIBRARY, e);
}
-
}
else
return false;
}
- private static void loadSnappyNativeLibrary() {
- if (isLoaded)
- return;
+ static File findNativeLibrary() {
+ // Try to load the library from org.xerial.snappy.lib.path library path */
+ String snappyNativeLibraryPath = System.getProperty(KEY_SNAPPY_LIB_PATH);
+ String snappyNativeLibraryName = System.getProperty(KEY_SNAPPY_LIB_NAME);
if (System.getProperty(KEY_SNAPPY_DISABLE_BUNDLED_LIBS, "false").equals("false")) {
- // Try to load the library from org.xerial.snappy.lib.path library path */
- String snappyNativeLibraryPath = System.getProperty(KEY_SNAPPY_LIB_PATH);
- String snappyNativeLibraryName = System.getProperty(KEY_SNAPPY_LIB_NAME);
-
// Resolve the library file name with a suffix (e.g., dll, .so, etc.)
if (snappyNativeLibraryName == null)
snappyNativeLibraryName = System.mapLibraryName("snappyjava");
if (snappyNativeLibraryPath != null) {
- if (loadNativeLibrary(snappyNativeLibraryPath, snappyNativeLibraryName)) {
- isLoaded = true;
- return;
- }
+ File nativeLib = new File(snappyNativeLibraryPath, snappyNativeLibraryName);
+ if (nativeLib.exists())
+ return nativeLib;
}
+ }
+ {
// Load an OS-dependent native library inside a jar file
snappyNativeLibraryPath = "/org/xerial/snappy/native/" + OSInfo.getNativeLibFolderPathForCurrentOS();
@@ -230,10 +309,22 @@ public class SnappyLoader
System.getProperty("java.io.tmpdir"))).getAbsolutePath();
// Extract and load a native library inside the jar file
- if (extractAndLoadLibraryFile(snappyNativeLibraryPath, snappyNativeLibraryName, tempFolder)) {
- isLoaded = true;
- return;
- }
+ return extractLibraryFile(snappyNativeLibraryPath, snappyNativeLibraryName, tempFolder);
+ }
+ }
+
+ return null;
+ }
+
+ private static void loadSnappyNativeLibrary() {
+ if (isLoaded)
+ return;
+
+ File nativeLibrary = findNativeLibrary();
+ if (nativeLibrary != null) {
+ if (loadNativeLibrary(nativeLibrary)) {
+ isLoaded = true;
+ return;
}
}
diff --git a/src/main/java/org/xerial/snappy/SnappyNative.java b/src/main/java/org/xerial/snappy/SnappyNative.java
index cbe8a14..42e0882 100755
--- a/src/main/java/org/xerial/snappy/SnappyNative.java
+++ b/src/main/java/org/xerial/snappy/SnappyNative.java
@@ -24,6 +24,7 @@
//--------------------------------------
package org.xerial.snappy;
+import java.io.IOException;
import java.nio.ByteBuffer;
/**
@@ -35,37 +36,38 @@ import java.nio.ByteBuffer;
public class SnappyNative
{
- native static String nativeLibraryVersion();
+ public native static String nativeLibraryVersion();
// ------------------------------------------------------------------------
// Generic compression/decompression routines.
// ------------------------------------------------------------------------
- native static int rawCompress(ByteBuffer input, int inputOffset, int inputLength, ByteBuffer compressed,
- int outputOffset) throws SnappyException;
+ public native static int rawCompress(ByteBuffer input, int inputOffset, int inputLength, ByteBuffer compressed,
+ int outputOffset) throws IOException;
- native static int rawCompress(Object input, int inputOffset, int inputByteLength, Object output, int outputOffset);
+ public native static int rawCompress(Object input, int inputOffset, int inputByteLength, Object output,
+ int outputOffset);
- native static int rawUncompress(ByteBuffer compressed, int inputOffset, int inputLength, ByteBuffer uncompressed,
- int outputOffset) throws SnappyException;
+ public native static int rawUncompress(ByteBuffer compressed, int inputOffset, int inputLength,
+ ByteBuffer uncompressed, int outputOffset) throws IOException;
- native static int rawUncompress(Object input, int inputOffset, int inputLength, Object output, int outputOffset)
- throws SnappyException;
+ public native static int rawUncompress(Object input, int inputOffset, int inputLength, Object output,
+ int outputOffset) throws IOException;
// Returns the maximal size of the compressed representation of
// input data that is "source_bytes" bytes in length;
- native static int maxCompressedLength(int source_bytes);
+ public native static int maxCompressedLength(int source_bytes);
// This operation takes O(1) time.
- native static int uncompressedLength(ByteBuffer compressed, int offset, int len) throws SnappyException;
+ public native static int uncompressedLength(ByteBuffer compressed, int offset, int len) throws IOException;
- native static int uncompressedLength(Object input, int offset, int len) throws SnappyException;
+ public native static int uncompressedLength(Object input, int offset, int len) throws IOException;
- native static boolean isValidCompressedBuffer(ByteBuffer compressed, int offset, int len) throws SnappyException;
+ public native static boolean isValidCompressedBuffer(ByteBuffer compressed, int offset, int len) throws IOException;
- native static boolean isValidCompressedBuffer(Object input, int offset, int len) throws SnappyException;
+ public native static boolean isValidCompressedBuffer(Object input, int offset, int len) throws IOException;
- protected static void throw_error(int errorCode) throws SnappyException {
- throw new SnappyException(errorCode);
+ protected static void throw_error(int errorCode) throws IOException {
+ throw new IOException(SnappyErrorCode.getErrorMessage(errorCode));
}
}
diff --git a/src/main/java/org/xerial/snappy/SnappyNativeLoader.bytecode b/src/main/java/org/xerial/snappy/SnappyNativeLoader.bytecode
new file mode 100755
index 0000000..a66950e
Binary files /dev/null and b/src/main/java/org/xerial/snappy/SnappyNativeLoader.bytecode differ
diff --git a/src/main/java/org/xerial/snappy/SnappyOutputStream.java b/src/main/java/org/xerial/snappy/SnappyOutputStream.java
index 67af407..63407cf 100755
--- a/src/main/java/org/xerial/snappy/SnappyOutputStream.java
+++ b/src/main/java/org/xerial/snappy/SnappyOutputStream.java
@@ -121,15 +121,10 @@ public class SnappyOutputStream extends OutputStream
return; // no need to dump
// Compress and dump the buffer content
- try {
- int compressedSize = Snappy.compress(uncompressed, 0, cursor, compressed, 0);
- writeInt(out, compressedSize);
- out.write(compressed, 0, compressedSize);
- cursor = 0;
- }
- catch (SnappyException e) {
- throw new IOException(e.getMessage());
- }
+ int compressedSize = Snappy.compress(uncompressed, 0, cursor, compressed, 0);
+ writeInt(out, compressedSize);
+ out.write(compressed, 0, compressedSize);
+ cursor = 0;
}
@Override
diff --git a/src/test/java/org/xerial/snappy/SnappyLoaderTest.java b/src/test/java/org/xerial/snappy/SnappyLoaderTest.java
index db5583b..dab9fb4 100755
--- a/src/test/java/org/xerial/snappy/SnappyLoaderTest.java
+++ b/src/test/java/org/xerial/snappy/SnappyLoaderTest.java
@@ -24,8 +24,19 @@
//--------------------------------------
package org.xerial.snappy;
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.security.ProtectionDomain;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtNewMethod;
+
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.junit.Ignore;
import org.junit.Test;
import org.xerial.util.log.Logger;
@@ -33,6 +44,7 @@ public class SnappyLoaderTest
{
private static Logger _logger = Logger.getLogger(SnappyLoaderTest.class);
+ @Ignore
@Test
public void loadFromSytemClassLoader() throws Exception {
@@ -41,8 +53,53 @@ public class SnappyLoaderTest
ClassRealm L1 = cw.newRealm("l1", parent);
ClassRealm L2 = cw.newRealm("l2", parent);
+ File nativeLib = SnappyLoader.findNativeLibrary();
+ assertNotNull(nativeLib);
+
+ ClassPool pool = ClassPool.getDefault();
+ CtClass cl = pool.makeClass("org.xerial.snappy.SnappyNativeLoader");
+ cl.addField(CtField.make("static boolean isLoaded = false;", cl));
+ String body = "public static void load(String lib) {if(!isLoaded) { try { System.load(lib); isLoaded=true; } catch(Exception e) { e.printStackTrace(); } }}";
+ cl.addMethod(CtNewMethod.make(body, cl));
+
+ ProtectionDomain systemPD = System.class.getProtectionDomain();
+ byte[] bytecode = cl.toBytecode();
+ // FileOutputStream f = new FileOutputStream("src/main/java/org/xerial/snappy/SnappyNativeLoader.bytecode");
+ // f.write(bytecode);
+ // f.close();
+
+ //Class< ? > loaderClass = cl.toClass(parent, System.class.getProtectionDomain());
+ //_logger.info(cl.getName());
+ //Class< ? > loaderClass = cl.toClass();
+
+ Class< ? > classLoader = Class.forName("java.lang.ClassLoader");
+ java.lang.reflect.Method defineClass = classLoader.getDeclaredMethod("defineClass", new Class[] { String.class,
+ byte[].class, int.class, int.class, ProtectionDomain.class });
+
+ defineClass.setAccessible(true);
+ defineClass.invoke(parent, cl.getName(), bytecode, 0, bytecode.length, System.class.getProtectionDomain());
+
+ Class< ? > forName = parent.loadClass("org.xerial.snappy.SnappyNativeLoader");
+ _logger.info(forName.toString());
+
//Class< ? > snappyClass = L1.loadClass("org.xerial.snappy.Snappy"); // not found
//_logger.info(snappyClass.getName());
}
+
+ @Test
+ public void load() throws Exception {
+ //SnappyLoader.load();
+ // Class< ? > c1 = Class.forName("org.xerial.snappy.SnappyNative");
+ // Class< ? > c2 = Class.forName("org.xerial.snappy.Snappy");
+ // ClassLoader cl1 = c1.getClassLoader();
+ // ClassLoader cl2 = c2.getClassLoader();
+ // Method m = c1.getDeclaredMethod("nativeLibraryVersion");
+ // m.setAccessible(true);
+ // String version = (String) m.invoke(null);
+ // _logger.info(version);
+
+ //_logger.info(SnappyNative.nativeLibraryVersion());
+ _logger.info(Snappy.getNativeLibraryVersion());
+ }
}
diff --git a/src/test/java/org/xerial/snappy/SnappyTest.java b/src/test/java/org/xerial/snappy/SnappyTest.java
index dc8b0ab..b60982e 100755
--- a/src/test/java/org/xerial/snappy/SnappyTest.java
+++ b/src/test/java/org/xerial/snappy/SnappyTest.java
@@ -26,6 +26,7 @@ package org.xerial.snappy;
import static org.junit.Assert.*;
+import java.io.IOException;
import java.nio.ByteBuffer;
import org.junit.Assert;
@@ -294,9 +295,16 @@ public class SnappyTest
byte[] uncompressed = Snappy.uncompress(b);
fail("cannot reach here since the input is invalid data");
}
- catch (SnappyException e) {
- assertEquals(SnappyErrorCode.FAILED_TO_UNCOMPRESS, e.errorCode);
+ catch (IOException e) {
+ //assertEquals(SnappyErrorCode.FAILED_TO_UNCOMPRESS, e.errorCode);
}
+ // catch (Exception e) {
+ // Class< ? > c = e.getClass();
+ // ClassLoader cl = c.getClassLoader();
+ //
+ // ClassLoader cl2 = SnappyException.class.getClassLoader();
+ // _logger.error(e);
+ // }
}