From dd255be667c2027ddef452771e7e7d9f4eb1aff1 Mon Sep 17 00:00:00 2001 From: Adam Murdoch Date: Sun, 9 Sep 2012 16:29:42 +1000 Subject: [PATCH] - Changed PosixFileFunctions to pass Strings to JNI methods, and use java_to_char() to encode as C char string. - Don't need to pass system encoding back up to Java as part of system info. --- src/main/cpp/generic.cpp | 2 +- src/main/cpp/posix.cpp | 71 ++++++++++--------- .../platform/internal/DefaultPosixFile.java | 33 ++------- .../platform/internal/DefaultSystemInfo.java | 4 -- .../platform/internal/MutableSystemInfo.java | 1 - .../internal/jni/NativeLibraryFunctions.java | 2 +- .../internal/jni/PosixFileFunctions.java | 8 +-- 7 files changed, 49 insertions(+), 72 deletions(-) diff --git a/src/main/cpp/generic.cpp b/src/main/cpp/generic.cpp index 74d8d04..c59ba9e 100755 --- a/src/main/cpp/generic.cpp +++ b/src/main/cpp/generic.cpp @@ -17,5 +17,5 @@ void mark_failed_with_code(JNIEnv *env, const char* message, int error_code, job JNIEXPORT jint JNICALL Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getVersion(JNIEnv *env, jclass target) { - return 8; + return 9; } diff --git a/src/main/cpp/posix.cpp b/src/main/cpp/posix.cpp index 94798ff..9add443 100755 --- a/src/main/cpp/posix.cpp +++ b/src/main/cpp/posix.cpp @@ -25,6 +25,7 @@ void mark_failed_with_errno(JNIEnv *env, const char* message, jobject result) { char* java_to_char(JNIEnv *env, jstring string, jobject result) { // TODO - share this code with nnn_getSystemInfo() below + // Empty string means load locale from environment. locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL); if (locale == NULL) { mark_failed_with_message(env, "could not create locale", result); @@ -47,6 +48,7 @@ char* java_to_char(JNIEnv *env, jstring string, jobject result) { jstring char_to_java(JNIEnv* env, const char* chars, jobject result) { // TODO - share this code with nnn_getSystemInfo() below + // Empty string means load locale from environment. locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL); if (locale == NULL) { mark_failed_with_message(env, "could not create locale", result); @@ -69,17 +71,6 @@ JNIEXPORT void JNICALL Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemInfo(JNIEnv *env, jclass target, jobject info, jobject result) { jclass infoClass = env->GetObjectClass(info); - // Empty string means load locale from environment. - locale_t locale = newlocale(LC_CTYPE_MASK, "", NULL); - if (locale == NULL) { - mark_failed_with_message(env, "could not create locale", result); - return; - } - - jfieldID characterEncodingField = env->GetFieldID(infoClass, "characterEncoding", "Ljava/lang/String;"); - env->SetObjectField(info, characterEncodingField, env->NewStringUTF(nl_langinfo_l(CODESET, locale))); - freelocale(locale); - struct utsname machine_info; if (uname(&machine_info) != 0) { mark_failed_with_errno(env, "could not query machine details", result); @@ -99,21 +90,27 @@ Java_net_rubygrapefruit_platform_internal_jni_NativeLibraryFunctions_getSystemIn */ JNIEXPORT void JNICALL -Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jbyteArray path, jint mode, jobject result) { - jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL); - int retval = chmod((const char*)pathUtf8, mode); - env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); +Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_chmod(JNIEnv *env, jclass target, jstring path, jint mode, jobject result) { + char* pathStr = java_to_char(env, path, result); + if (pathStr == NULL) { + return; + } + int retval = chmod(pathStr, mode); + free(pathStr); if (retval != 0) { mark_failed_with_errno(env, "could not chmod file", result); } } JNIEXPORT void JNICALL -Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jbyteArray path, jobject dest, jobject result) { +Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *env, jclass target, jstring path, jobject dest, jobject result) { struct stat fileInfo; - jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL); - int retval = stat((const char*)pathUtf8, &fileInfo); - env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); + char* pathStr = java_to_char(env, path, result); + if (pathStr == NULL) { + return; + } + int retval = stat(pathStr, &fileInfo); + free(pathStr); if (retval != 0) { mark_failed_with_errno(env, "could not stat file", result); return; @@ -124,37 +121,47 @@ Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_stat(JNIEnv *en } JNIEXPORT void JNICALL -Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv *env, jclass target, jbyteArray path, jbyteArray contents, jobject result) { - jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL); - jbyte* contentsUtf8 = env->GetByteArrayElements(contents, NULL); - int retval = symlink((const char*)contentsUtf8, (const char*)pathUtf8); - env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); - env->ReleaseByteArrayElements(contents, contentsUtf8, JNI_ABORT); +Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_symlink(JNIEnv *env, jclass target, jstring path, jstring contents, jobject result) { + char* pathStr = java_to_char(env, path, result); + if (pathStr == NULL) { + return; + } + char* contentStr = java_to_char(env, contents, result); + if (contentStr == NULL) { + free(pathStr); + return; + } + int retval = symlink(contentStr, pathStr); + free(contentStr); + free(pathStr); if (retval != 0) { mark_failed_with_errno(env, "could not symlink", result); } } JNIEXPORT jstring JNICALL -Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jbyteArray path, jobject result) { +Java_net_rubygrapefruit_platform_internal_jni_PosixFileFunctions_readlink(JNIEnv *env, jclass target, jstring path, jobject result) { struct stat link_info; - jbyte* pathUtf8 = env->GetByteArrayElements(path, NULL); - int retval = lstat((const char*)pathUtf8, &link_info); + char* pathStr = java_to_char(env, path, result); + if (pathStr == NULL) { + return NULL; + } + int retval = lstat(pathStr, &link_info); if (retval != 0) { - env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); + free(pathStr); mark_failed_with_errno(env, "could not lstat file", result); return NULL; } char* contents = (char*)malloc(link_info.st_size + 1); if (contents == NULL) { - env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); + free(pathStr); mark_failed_with_message(env, "could not create array", result); return NULL; } - retval = readlink((const char*)pathUtf8, contents, link_info.st_size); - env->ReleaseByteArrayElements(path, pathUtf8, JNI_ABORT); + retval = readlink(pathStr, contents, link_info.st_size); + free(pathStr); if (retval < 0) { free(contents); mark_failed_with_errno(env, "could not readlink", result); diff --git a/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java b/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java index 4ef6be1..dc37735 100755 --- a/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/DefaultPosixFile.java @@ -5,19 +5,11 @@ import net.rubygrapefruit.platform.PosixFile; import net.rubygrapefruit.platform.internal.jni.PosixFileFunctions; import java.io.File; -import java.io.UnsupportedEncodingException; public class DefaultPosixFile implements PosixFile { - private final String characterEncoding; - - public DefaultPosixFile() { - DefaultSystemInfo systemInfo = new DefaultSystemInfo(); - this.characterEncoding = systemInfo.getCharacterEncoding(); - } - public void setMode(File file, int perms) { FunctionResult result = new FunctionResult(); - PosixFileFunctions.chmod(encode(file), perms, result); + PosixFileFunctions.chmod(file.getPath(), perms, result); if (result.isFailed()) { throw new NativeException(String.format("Could not set UNIX mode on %s: %s", file, result.getMessage())); } @@ -26,7 +18,7 @@ public class DefaultPosixFile implements PosixFile { public int getMode(File file) { FunctionResult result = new FunctionResult(); FileStat stat = new FileStat(); - PosixFileFunctions.stat(encode(file), stat, result); + PosixFileFunctions.stat(file.getPath(), stat, result); if (result.isFailed()) { throw new NativeException(String.format("Could not get UNIX mode on %s: %s", file, result.getMessage())); } @@ -36,7 +28,7 @@ public class DefaultPosixFile implements PosixFile { @Override public String readLink(File link) throws NativeException { FunctionResult result = new FunctionResult(); - String contents = PosixFileFunctions.readlink(encode(link), result); + String contents = PosixFileFunctions.readlink(link.getPath(), result); if (result.isFailed()) { throw new NativeException(String.format("Could not read symlink %s: %s", link, result.getMessage())); } @@ -46,26 +38,9 @@ public class DefaultPosixFile implements PosixFile { @Override public void symlink(File link, String contents) throws NativeException { FunctionResult result = new FunctionResult(); - PosixFileFunctions.symlink(encode(link), encode(contents), result); + PosixFileFunctions.symlink(link.getPath(), contents, result); if (result.isFailed()) { throw new NativeException(String.format("Could not create symlink %s: %s", link, result.getMessage())); } } - - private byte[] encode(File file) { - return encode(file.getPath()); - } - - private byte[] encode(String path) { - byte[] encodedName; - try { - encodedName = path.getBytes(characterEncoding); - } catch (UnsupportedEncodingException e) { - throw new NativeException(String.format("Could not encode path '%s' using encoding %s.", path, characterEncoding), e); - } - byte[] buffer = new byte[encodedName.length + 1]; - System.arraycopy(encodedName, 0, buffer, 0, encodedName.length); - buffer[buffer.length - 1] = 0; - return buffer; - } } diff --git a/src/main/java/net/rubygrapefruit/platform/internal/DefaultSystemInfo.java b/src/main/java/net/rubygrapefruit/platform/internal/DefaultSystemInfo.java index 33c935f..0d328aa 100644 --- a/src/main/java/net/rubygrapefruit/platform/internal/DefaultSystemInfo.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/DefaultSystemInfo.java @@ -30,8 +30,4 @@ public class DefaultSystemInfo implements SystemInfo { public String getMachineArchitecture() { return systemInfo.getMachineArchitecture(); } - - public String getCharacterEncoding() { - return systemInfo.characterEncoding; - } } diff --git a/src/main/java/net/rubygrapefruit/platform/internal/MutableSystemInfo.java b/src/main/java/net/rubygrapefruit/platform/internal/MutableSystemInfo.java index c8582b8..85a227d 100644 --- a/src/main/java/net/rubygrapefruit/platform/internal/MutableSystemInfo.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/MutableSystemInfo.java @@ -5,7 +5,6 @@ import net.rubygrapefruit.platform.SystemInfo; public class MutableSystemInfo implements SystemInfo { public String osName; public String osVersion; - public String characterEncoding; public String machineArchitecture; public String getKernelName() { diff --git a/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java b/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java index 3ffed44..bf57fa1 100755 --- a/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/jni/NativeLibraryFunctions.java @@ -4,7 +4,7 @@ import net.rubygrapefruit.platform.internal.FunctionResult; import net.rubygrapefruit.platform.internal.MutableSystemInfo; public class NativeLibraryFunctions { - public static final int VERSION = 8; + public static final int VERSION = 9; public static native int getVersion(); diff --git a/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java b/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java index c8a1c47..0ffe41f 100755 --- a/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java +++ b/src/main/java/net/rubygrapefruit/platform/internal/jni/PosixFileFunctions.java @@ -4,11 +4,11 @@ import net.rubygrapefruit.platform.internal.FileStat; import net.rubygrapefruit.platform.internal.FunctionResult; public class PosixFileFunctions { - public static native void chmod(byte[] file, int perms, FunctionResult result); + public static native void chmod(String file, int perms, FunctionResult result); - public static native void stat(byte[] file, FileStat stat, FunctionResult result); + public static native void stat(String file, FileStat stat, FunctionResult result); - public static native void symlink(byte[] file, byte[] content, FunctionResult result); + public static native void symlink(String file, String content, FunctionResult result); - public static native String readlink(byte[] file, FunctionResult result); + public static native String readlink(String file, FunctionResult result); }