diff options
Diffstat (limited to 'JavaScriptCore/bindings/jni/jni_utility.cpp')
-rw-r--r-- | JavaScriptCore/bindings/jni/jni_utility.cpp | 987 |
1 files changed, 987 insertions, 0 deletions
diff --git a/JavaScriptCore/bindings/jni/jni_utility.cpp b/JavaScriptCore/bindings/jni/jni_utility.cpp new file mode 100644 index 0000000..8a8c656 --- /dev/null +++ b/JavaScriptCore/bindings/jni/jni_utility.cpp @@ -0,0 +1,987 @@ +/* + * Copyright (C) 2003 Apple Computer, 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 "jni_utility.h" + +#include "list.h" +#include "jni_runtime.h" +#include "runtime_array.h" +#include "runtime_object.h" +#include <dlfcn.h> + +namespace KJS { + +namespace Bindings { + +static jint KJS_GetCreatedJavaVMs(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; + + static jint(*functionPointer)(JavaVM**, jsize, jsize *) = 0; + if (!functionPointer) + functionPointer = (jint(*)(JavaVM**, jsize, jsize *))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 = KJS_GetCreatedJavaVMs(jvmArray, bufLen, &nJVMs); + if ( jniError == JNI_OK && nJVMs > 0 ) { + jvm = jvmArray[0]; + } + else + fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError); + + return jvm; +} + +JNIEnv* getJNIEnv() +{ + union { + JNIEnv* env; + void* dummy; + } u; + jint jniError = 0; + + jniError = (getJavaVM())->AttachCurrentThread(&u.dummy, NULL); + if (jniError == JNI_OK) + return u.env; + else + fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError); + return NULL; +} + +static jvalue callJNIMethod (JNIType type, jobject obj, const char *name, const char *sig, va_list args) +{ + JavaVM *jvm = getJavaVM(); + JNIEnv *env = getJNIEnv(); + jvalue result; + + bzero (&result, sizeof(jvalue)); + if ( obj != NULL && jvm != NULL && env != NULL) { + jclass cls = env->GetObjectClass(obj); + if ( cls != NULL ) { + jmethodID mid = env->GetMethodID(cls, name, sig); + if ( mid != NULL ) + { + switch (type) { + case void_type: + env->functions->CallVoidMethodV(env, obj, mid, args); + break; + case array_type: + case object_type: + result.l = env->functions->CallObjectMethodV(env, obj, mid, args); + break; + case boolean_type: + result.z = env->functions->CallBooleanMethodV(env, obj, mid, args); + break; + case byte_type: + result.b = env->functions->CallByteMethodV(env, obj, mid, args); + break; + case char_type: + result.c = env->functions->CallCharMethodV(env, obj, mid, args); + break; + case short_type: + result.s = env->functions->CallShortMethodV(env, obj, mid, args); + break; + case int_type: + result.i = env->functions->CallIntMethodV(env, obj, mid, args); + break; + case long_type: + result.j = env->functions->CallLongMethodV(env, obj, mid, args); + break; + case float_type: + result.f = env->functions->CallFloatMethodV(env, obj, mid, args); + break; + case double_type: + result.d = env->functions->CallDoubleMethodV(env, obj, mid, args); + break; + default: + fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type); + } + } + else + { + fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, obj); + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf (stderr, "\n"); + } + + env->DeleteLocalRef(cls); + } + else { + fprintf(stderr, "%s: Could not find class for %p\n", __PRETTY_FUNCTION__, obj); + } + } + + return result; +} + +static jvalue callJNIStaticMethod (JNIType type, jclass cls, const char *name, const char *sig, va_list args) +{ + JavaVM *jvm = getJavaVM(); + JNIEnv *env = getJNIEnv(); + jvalue result; + + bzero (&result, sizeof(jvalue)); + if ( cls != NULL && jvm != NULL && env != NULL) { + jmethodID mid = env->GetStaticMethodID(cls, name, sig); + if ( mid != NULL ) + { + switch (type) { + case void_type: + env->functions->CallStaticVoidMethodV(env, cls, mid, args); + break; + case array_type: + case object_type: + result.l = env->functions->CallStaticObjectMethodV(env, cls, mid, args); + break; + case boolean_type: + result.z = env->functions->CallStaticBooleanMethodV(env, cls, mid, args); + break; + case byte_type: + result.b = env->functions->CallStaticByteMethodV(env, cls, mid, args); + break; + case char_type: + result.c = env->functions->CallStaticCharMethodV(env, cls, mid, args); + break; + case short_type: + result.s = env->functions->CallStaticShortMethodV(env, cls, mid, args); + break; + case int_type: + result.i = env->functions->CallStaticIntMethodV(env, cls, mid, args); + break; + case long_type: + result.j = env->functions->CallStaticLongMethodV(env, cls, mid, args); + break; + case float_type: + result.f = env->functions->CallStaticFloatMethodV(env, cls, mid, args); + break; + case double_type: + result.d = env->functions->CallStaticDoubleMethodV(env, cls, mid, args); + break; + default: + fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type); + } + } + else + { + fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, cls); + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf (stderr, "\n"); + } + } + + return result; +} + +static jvalue callJNIMethodIDA (JNIType type, jobject obj, jmethodID mid, jvalue *args) +{ + JNIEnv *env = getJNIEnv(); + jvalue result; + + bzero (&result, sizeof(jvalue)); + if ( obj != NULL && mid != NULL ) + { + switch (type) { + case void_type: + env->functions->CallVoidMethodA(env, obj, mid, args); + break; + case array_type: + case object_type: + result.l = env->functions->CallObjectMethodA(env, obj, mid, args); + break; + case boolean_type: + result.z = env->functions->CallBooleanMethodA(env, obj, mid, args); + break; + case byte_type: + result.b = env->functions->CallByteMethodA(env, obj, mid, args); + break; + case char_type: + result.c = env->functions->CallCharMethodA(env, obj, mid, args); + break; + case short_type: + result.s = env->functions->CallShortMethodA(env, obj, mid, args); + break; + case int_type: + result.i = env->functions->CallIntMethodA(env, obj, mid, args); + break; + case long_type: + result.j = env->functions->CallLongMethodA(env, obj, mid, args); + break; + case float_type: + result.f = env->functions->CallFloatMethodA(env, obj, mid, args); + break; + case double_type: + result.d = env->functions->CallDoubleMethodA(env, obj, mid, args); + break; + default: + fprintf(stderr, "%s: invalid function type (%d)\n", __PRETTY_FUNCTION__, (int)type); + } + } + + return result; +} + +static jvalue callJNIMethodA (JNIType type, jobject obj, const char *name, const char *sig, jvalue *args) +{ + JavaVM *jvm = getJavaVM(); + JNIEnv *env = getJNIEnv(); + jvalue result; + + bzero (&result, sizeof(jvalue)); + if ( obj != NULL && jvm != NULL && env != NULL) { + jclass cls = env->GetObjectClass(obj); + if ( cls != NULL ) { + jmethodID mid = env->GetMethodID(cls, name, sig); + if ( mid != NULL ) { + result = callJNIMethodIDA (type, obj, mid, args); + } + else { + fprintf(stderr, "%s: Could not find method: %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; +} + +jmethodID getMethodID (jobject obj, const char *name, const char *sig) +{ + JNIEnv *env = getJNIEnv(); + jmethodID mid = 0; + + if ( env != NULL) { + jclass cls = env->GetObjectClass(obj); + if ( cls != NULL ) { + 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; +} + + +#define CALL_JNI_METHOD(function_type,obj,name,sig) \ + va_list args;\ + va_start (args, sig);\ + \ + jvalue result = callJNIMethod(function_type, obj, name, sig, args);\ + \ + va_end (args); + +#define CALL_JNI_STATIC_METHOD(function_type,cls,name,sig) \ + va_list args;\ + va_start (args, sig);\ + \ + jvalue result = callJNIStaticMethod(function_type, cls, name, sig, args);\ + \ + va_end (args); + +void callJNIVoidMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (void_type, obj, name, sig); +} + +jobject callJNIObjectMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (object_type, obj, name, sig); + return result.l; +} + +jboolean callJNIBooleanMethod( jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (boolean_type, obj, name, sig); + return result.z; +} + +jboolean callJNIStaticBooleanMethod (jclass cls, const char *name, const char *sig, ... ) +{ + CALL_JNI_STATIC_METHOD (boolean_type, cls, name, sig); + return result.z; +} + +jbyte callJNIByteMethod( jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (byte_type, obj, name, sig); + return result.b; +} + +jchar callJNICharMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (char_type, obj, name, sig); + return result.c; +} + +jshort callJNIShortMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (short_type, obj, name, sig); + return result.s; +} + +jint callJNIIntMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (int_type, obj, name, sig); + return result.i; +} + +jlong callJNILongMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (long_type, obj, name, sig); + return result.j; +} + +jfloat callJNIFloatMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (float_type, obj, name, sig); + return result.f; +} + +jdouble callJNIDoubleMethod (jobject obj, const char *name, const char *sig, ... ) +{ + CALL_JNI_METHOD (double_type, obj, name, sig); + return result.d; +} + +void callJNIVoidMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (void_type, obj, name, sig, args); +} + +jobject callJNIObjectMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (object_type, obj, name, sig, args); + return result.l; +} + +jbyte callJNIByteMethodA ( jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (byte_type, obj, name, sig, args); + return result.b; +} + +jchar callJNICharMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (char_type, obj, name, sig, args); + return result.c; +} + +jshort callJNIShortMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (short_type, obj, name, sig, args); + return result.s; +} + +jint callJNIIntMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (int_type, obj, name, sig, args); + return result.i; +} + +jlong callJNILongMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (long_type, obj, name, sig, args); + return result.j; +} + +jfloat callJNIFloatMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (float_type, obj, name, sig, args); + return result.f; +} + +jdouble callJNIDoubleMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (double_type, obj, name, sig, args); + return result.d; +} + +jboolean callJNIBooleanMethodA (jobject obj, const char *name, const char *sig, jvalue *args) +{ + jvalue result = callJNIMethodA (boolean_type, obj, name, sig, args); + return result.z; +} + +void callJNIVoidMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (void_type, obj, methodID, args); +} + +jobject callJNIObjectMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (object_type, obj, methodID, args); + return result.l; +} + +jbyte callJNIByteMethodIDA ( jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (byte_type, obj, methodID, args); + return result.b; +} + +jchar callJNICharMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (char_type, obj, methodID, args); + return result.c; +} + +jshort callJNIShortMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (short_type, obj, methodID, args); + return result.s; +} + +jint callJNIIntMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (int_type, obj, methodID, args); + return result.i; +} + +jlong callJNILongMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (long_type, obj, methodID, args); + return result.j; +} + +jfloat callJNIFloatMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (float_type, obj, methodID, args); + return result.f; +} + +jdouble callJNIDoubleMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (double_type, obj, methodID, args); + return result.d; +} + +jboolean callJNIBooleanMethodIDA (jobject obj, jmethodID methodID, jvalue *args) +{ + jvalue result = callJNIMethodIDA (boolean_type, obj, methodID, args); + return result.z; +} + +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((jstring)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((jstring)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) == 0) + type = byte_type; + else if (strcmp("short",name) == 0) + type = short_type; + else if (strcmp("int",name) == 0) + type = int_type; + else if (strcmp("long",name) == 0) + type = long_type; + else if (strcmp("float",name) == 0) + type = float_type; + else if (strcmp("double",name) == 0) + type = double_type; + else if (strcmp("char",name) == 0) + type = char_type; + else if (strcmp("boolean",name) == 0) + type = boolean_type; + else if (strcmp("void",name) == 0) + 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 != NULL && jvm != NULL && env != NULL) { + jclass cls = env->GetObjectClass(obj); + if ( cls != NULL ) { + jfieldID field = env->GetFieldID(cls, name, signature); + if ( field != NULL ) { + 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__, (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; +} + +static jobject convertArrayInstanceToJavaArray(ExecState *exec, JSValue *value, const char *javaClassName) { + + ASSERT(JSLock::lockCount() > 0); + + JNIEnv *env = getJNIEnv(); + // As JS Arrays can contain a mixture of objects, assume we can convert to + // the requested Java Array type requested, unless the array type is some object array + // other than a string. + ArrayInstance *jsArray = static_cast<ArrayInstance *>(value); + unsigned length = jsArray->getLength(); + jobjectArray jarray = 0; + + // Build the correct array type + switch (JNITypeFromPrimitiveType(javaClassName[1])) { + case object_type: { + // Only support string object types + if (0 == strcmp("[Ljava.lang.String;", javaClassName)) { + jarray = (jobjectArray)env->NewObjectArray(length, + env->FindClass("java/lang/String"), + env->NewStringUTF("")); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + UString stringValue = item->toString(exec); + env->SetObjectArrayElement(jarray,i, + env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size())); + } + } + break; + } + + case boolean_type: { + jarray = (jobjectArray)env->NewBooleanArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + jboolean value = (jboolean)item->toNumber(exec); + env->SetBooleanArrayRegion((jbooleanArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case byte_type: { + jarray = (jobjectArray)env->NewByteArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + jbyte value = (jbyte)item->toNumber(exec); + env->SetByteArrayRegion((jbyteArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case char_type: { + jarray = (jobjectArray)env->NewCharArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + UString stringValue = item->toString(exec); + jchar value = 0; + if (stringValue.size() > 0) + value = ((const jchar*)stringValue.data())[0]; + env->SetCharArrayRegion((jcharArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case short_type: { + jarray = (jobjectArray)env->NewShortArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + jshort value = (jshort)item->toNumber(exec); + env->SetShortArrayRegion((jshortArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case int_type: { + jarray = (jobjectArray)env->NewIntArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + jint value = (jint)item->toNumber(exec); + env->SetIntArrayRegion((jintArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case long_type: { + jarray = (jobjectArray)env->NewLongArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + jlong value = (jlong)item->toNumber(exec); + env->SetLongArrayRegion((jlongArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case float_type: { + jarray = (jobjectArray)env->NewFloatArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + jfloat value = (jfloat)item->toNumber(exec); + env->SetFloatArrayRegion((jfloatArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case double_type: { + jarray = (jobjectArray)env->NewDoubleArray(length); + for(unsigned i = 0; i < length; i++) { + JSValue* item = jsArray->getItem(i); + jdouble value = (jdouble)item->toNumber(exec); + env->SetDoubleArrayRegion((jdoubleArray)jarray, (jsize)i, (jsize)1, &value); + } + break; + } + + case array_type: // don't handle embedded arrays + case void_type: // Don't expect arrays of void objects + case invalid_type: // Array of unknown objects + break; + } + + // if it was not one of the cases handled, then null is returned + return jarray; +} + + +jvalue convertValueToJValue (ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName) +{ + JSLock lock; + + jvalue result; + + switch (_JNIType){ + case array_type: + case object_type: { + result.l = (jobject)0; + + // First see if we have a Java instance. + if (value->isObject()){ + JSObject *objectImp = static_cast<JSObject*>(value); + if (objectImp->classInfo() == &RuntimeObjectImp::info) { + RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(value); + JavaInstance *instance = static_cast<JavaInstance*>(imp->getInternalInstance()); + if (instance) + result.l = instance->javaInstance(); + } + else if (objectImp->classInfo() == &RuntimeArray::info) { + // Input is a JavaScript Array that was originally created from a Java Array + RuntimeArray *imp = static_cast<RuntimeArray *>(value); + JavaArray *array = static_cast<JavaArray*>(imp->getConcreteArray()); + result.l = array->javaArray(); + } + else if (objectImp->classInfo() == &ArrayInstance::info) { + // Input is a Javascript Array. We need to create it to a Java Array. + result.l = convertArrayInstanceToJavaArray(exec, value, javaClassName); + } + } + + // Now convert value to a string if the target type is a java.lang.string, and we're not + // converting from a Null. + if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0) { +#ifdef CONVERT_NULL_TO_EMPTY_STRING + if (value->isNull()) { + JNIEnv *env = getJNIEnv(); + jchar buf[2]; + jobject javaString = env->functions->NewString (env, buf, 0); + result.l = javaString; + } + else +#else + if (!value->isNull()) +#endif + { + UString stringValue = value->toString(exec); + JNIEnv *env = getJNIEnv(); + jobject javaString = env->functions->NewString (env, (const jchar *)stringValue.data(), stringValue.size()); + result.l = javaString; + } + } else if (result.l == 0) + bzero (&result, sizeof(jvalue)); // Handle it the same as a void case + } + break; + + case boolean_type: { + result.z = (jboolean)value->toNumber(exec); + } + break; + + case byte_type: { + result.b = (jbyte)value->toNumber(exec); + } + break; + + case char_type: { + result.c = (jchar)value->toNumber(exec); + } + break; + + case short_type: { + result.s = (jshort)value->toNumber(exec); + } + break; + + case int_type: { + result.i = (jint)value->toNumber(exec); + } + break; + + case long_type: { + result.j = (jlong)value->toNumber(exec); + } + break; + + case float_type: { + result.f = (jfloat)value->toNumber(exec); + } + break; + + case double_type: { + result.d = (jdouble)value->toNumber(exec); + } + break; + + break; + + case invalid_type: + default: + case void_type: { + bzero (&result, sizeof(jvalue)); + } + break; + } + return result; +} + +} // end of namespace Bindings + +} // end of namespace KJS |