diff options
Diffstat (limited to 'WebCore/bridge/jni/JNIUtility.cpp')
| -rw-r--r-- | WebCore/bridge/jni/JNIUtility.cpp | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/WebCore/bridge/jni/JNIUtility.cpp b/WebCore/bridge/jni/JNIUtility.cpp new file mode 100644 index 0000000..ee45710 --- /dev/null +++ b/WebCore/bridge/jni/JNIUtility.cpp @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JNIUtility.h" + +#if ENABLE(MAC_JAVA_BRIDGE) + +#include <dlfcn.h> + +namespace JSC { + +namespace Bindings { + +static jint KJSGetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs) +{ + static void* javaVMFramework = 0; + if (!javaVMFramework) + javaVMFramework = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY); + if (!javaVMFramework) + return JNI_ERR; + + typedef jint(*FunctionPointerType)(JavaVM**, jsize, jsize*); + static FunctionPointerType functionPointer = 0; + if (!functionPointer) + functionPointer = reinterpret_cast<FunctionPointerType>(dlsym(javaVMFramework, "JNI_GetCreatedJavaVMs")); + if (!functionPointer) + return JNI_ERR; + return functionPointer(vmBuf, bufLen, nVMs); +} + +static JavaVM* jvm = 0; + +// Provide the ability for an outside component to specify the JavaVM to use +// If the jvm value is set, the getJavaVM function below will just return. +// In getJNIEnv(), if AttachCurrentThread is called to a VM that is already +// attached, the result is a no-op. +void setJavaVM(JavaVM* javaVM) +{ + jvm = javaVM; +} + +JavaVM* getJavaVM() +{ + if (jvm) + return jvm; + + JavaVM* jvmArray[1]; + jsize bufLen = 1; + jsize nJVMs = 0; + jint jniError = 0; + + // Assumes JVM is already running ..., one per process + jniError = KJSGetCreatedJavaVMs(jvmArray, bufLen, &nJVMs); + if (jniError == JNI_OK && nJVMs > 0) + jvm = jvmArray[0]; + else + fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, static_cast<long>(jniError)); + + return jvm; +} + +JNIEnv* getJNIEnv() +{ + union { + JNIEnv* env; + void* dummy; + } u; + jint jniError = 0; + + jniError = getJavaVM()->AttachCurrentThread(&u.dummy, 0); + if (jniError == JNI_OK) + return u.env; + fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, static_cast<long>(jniError)); + return 0; +} + +jmethodID getMethodID(jobject obj, const char* name, const char* sig) +{ + JNIEnv* env = getJNIEnv(); + jmethodID mid = 0; + + if (env) { + jclass cls = env->GetObjectClass(obj); + if (cls) { + mid = env->GetMethodID(cls, name, sig); + if (!mid) { + env->ExceptionClear(); + mid = env->GetStaticMethodID(cls, name, sig); + if (!mid) + env->ExceptionClear(); + } + } + env->DeleteLocalRef(cls); + } + return mid; +} + +const char* getCharactersFromJString(jstring aJString) +{ + return getCharactersFromJStringInEnv(getJNIEnv(), aJString); +} + +void releaseCharactersForJString(jstring aJString, const char* s) +{ + releaseCharactersForJStringInEnv(getJNIEnv(), aJString, s); +} + +const char* getCharactersFromJStringInEnv(JNIEnv* env, jstring aJString) +{ + jboolean isCopy; + const char* s = env->GetStringUTFChars(aJString, &isCopy); + if (!s) { + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf(stderr, "\n"); + } + return s; +} + +void releaseCharactersForJStringInEnv(JNIEnv* env, jstring aJString, const char* s) +{ + env->ReleaseStringUTFChars(aJString, s); +} + +const jchar* getUCharactersFromJStringInEnv(JNIEnv* env, jstring aJString) +{ + jboolean isCopy; + const jchar* s = env->GetStringChars(aJString, &isCopy); + if (!s) { + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf(stderr, "\n"); + } + return s; +} + +void releaseUCharactersForJStringInEnv(JNIEnv* env, jstring aJString, const jchar* s) +{ + env->ReleaseStringChars(aJString, s); +} + +JNIType JNITypeFromClassName(const char* name) +{ + JNIType type; + + if (!strcmp("byte", name)) + type = byte_type; + else if (!strcmp("short", name)) + type = short_type; + else if (!strcmp("int", name)) + type = int_type; + else if (!strcmp("long", name)) + type = long_type; + else if (!strcmp("float", name)) + type = float_type; + else if (!strcmp("double", name)) + type = double_type; + else if (!strcmp("char", name)) + type = char_type; + else if (!strcmp("boolean", name)) + type = boolean_type; + else if (!strcmp("void", name)) + type = void_type; + else if ('[' == name[0]) + type = array_type; + else + type = object_type; + + return type; +} + +const char* signatureFromPrimitiveType(JNIType type) +{ + switch (type) { + case void_type: + return "V"; + + case array_type: + return "["; + + case object_type: + return "L"; + + case boolean_type: + return "Z"; + + case byte_type: + return "B"; + + case char_type: + return "C"; + + case short_type: + return "S"; + + case int_type: + return "I"; + + case long_type: + return "J"; + + case float_type: + return "F"; + + case double_type: + return "D"; + + case invalid_type: + default: + break; + } + return ""; +} + +JNIType JNITypeFromPrimitiveType(char type) +{ + switch (type) { + case 'V': + return void_type; + + case 'L': + return object_type; + + case '[': + return array_type; + + case 'Z': + return boolean_type; + + case 'B': + return byte_type; + + case 'C': + return char_type; + + case 'S': + return short_type; + + case 'I': + return int_type; + + case 'J': + return long_type; + + case 'F': + return float_type; + + case 'D': + return double_type; + + default: + break; + } + return invalid_type; +} + +jvalue getJNIField(jobject obj, JNIType type, const char* name, const char* signature) +{ + JavaVM* jvm = getJavaVM(); + JNIEnv* env = getJNIEnv(); + jvalue result; + + bzero(&result, sizeof(jvalue)); + if (obj && jvm && env) { + jclass cls = env->GetObjectClass(obj); + if (cls) { + jfieldID field = env->GetFieldID(cls, name, signature); + if (field) { + switch (type) { + case array_type: + case object_type: + result.l = env->functions->GetObjectField(env, obj, field); + break; + case boolean_type: + result.z = env->functions->GetBooleanField(env, obj, field); + break; + case byte_type: + result.b = env->functions->GetByteField(env, obj, field); + break; + case char_type: + result.c = env->functions->GetCharField(env, obj, field); + break; + case short_type: + result.s = env->functions->GetShortField(env, obj, field); + break; + case int_type: + result.i = env->functions->GetIntField(env, obj, field); + break; + case long_type: + result.j = env->functions->GetLongField(env, obj, field); + break; + case float_type: + result.f = env->functions->GetFloatField(env, obj, field); + break; + case double_type: + result.d = env->functions->GetDoubleField(env, obj, field); + break; + default: + fprintf(stderr, "%s: invalid field type (%d)\n", __PRETTY_FUNCTION__, static_cast<int>(type)); + } + } else { + fprintf(stderr, "%s: Could not find field: %s\n", __PRETTY_FUNCTION__, name); + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf(stderr, "\n"); + } + + env->DeleteLocalRef(cls); + } else + fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__); + } + + return result; +} + +} // namespace Bindings + +} // namespace JSC + +#endif // ENABLE(MAC_JAVA_BRIDGE) |
