1 /* 2 * Copyright (C) 2003, 2010 Apple, Inc. All rights reserved. 3 * Copyright 2009, The Android Open Source Project 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "JNIUtilityPrivate.h" 29 30 #if ENABLE(JAVA_BRIDGE) 31 32 #include "JavaRuntimeObject.h" 33 #include "JNIBridgeJSC.h" 34 #include "jni_jsobject.h" 35 #include "runtime_array.h" 36 #include "runtime_object.h" 37 #include <runtime/JSArray.h> 38 #include <runtime/JSLock.h> 39 40 namespace JSC { 41 42 namespace Bindings { 43 44 static jobject convertArrayInstanceToJavaArray(ExecState* exec, JSArray* jsArray, const char* javaClassName) 45 { 46 JNIEnv* env = getJNIEnv(); 47 // As JS Arrays can contain a mixture of objects, assume we can convert to 48 // the requested Java Array type requested, unless the array type is some object array 49 // other than a string. 50 unsigned length = jsArray->length(); 51 jobjectArray jarray = 0; 52 53 // Build the correct array type 54 switch (JNITypeFromPrimitiveType(javaClassName[1])) { 55 case object_type: 56 { 57 // Only support string object types 58 if (!strcmp("[Ljava.lang.String;", javaClassName)) { 59 jarray = (jobjectArray)env->NewObjectArray(length, 60 env->FindClass("java/lang/String"), 61 env->NewStringUTF("")); 62 for (unsigned i = 0; i < length; i++) { 63 JSValue item = jsArray->get(exec, i); 64 UString stringValue = item.toString(exec); 65 env->SetObjectArrayElement(jarray, i, 66 env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size())); 67 } 68 } 69 break; 70 } 71 72 case boolean_type: 73 { 74 jarray = (jobjectArray)env->NewBooleanArray(length); 75 for (unsigned i = 0; i < length; i++) { 76 JSValue item = jsArray->get(exec, i); 77 jboolean value = (jboolean)item.toNumber(exec); 78 env->SetBooleanArrayRegion((jbooleanArray)jarray, (jsize)i, (jsize)1, &value); 79 } 80 break; 81 } 82 83 case byte_type: 84 { 85 jarray = (jobjectArray)env->NewByteArray(length); 86 for (unsigned i = 0; i < length; i++) { 87 JSValue item = jsArray->get(exec, i); 88 jbyte value = (jbyte)item.toNumber(exec); 89 env->SetByteArrayRegion((jbyteArray)jarray, (jsize)i, (jsize)1, &value); 90 } 91 break; 92 } 93 94 case char_type: 95 { 96 jarray = (jobjectArray)env->NewCharArray(length); 97 for (unsigned i = 0; i < length; i++) { 98 JSValue item = jsArray->get(exec, i); 99 UString stringValue = item.toString(exec); 100 jchar value = 0; 101 if (stringValue.size() > 0) 102 value = ((const jchar*)stringValue.data())[0]; 103 env->SetCharArrayRegion((jcharArray)jarray, (jsize)i, (jsize)1, &value); 104 } 105 break; 106 } 107 108 case short_type: 109 { 110 jarray = (jobjectArray)env->NewShortArray(length); 111 for (unsigned i = 0; i < length; i++) { 112 JSValue item = jsArray->get(exec, i); 113 jshort value = (jshort)item.toNumber(exec); 114 env->SetShortArrayRegion((jshortArray)jarray, (jsize)i, (jsize)1, &value); 115 } 116 break; 117 } 118 119 case int_type: 120 { 121 jarray = (jobjectArray)env->NewIntArray(length); 122 for (unsigned i = 0; i < length; i++) { 123 JSValue item = jsArray->get(exec, i); 124 jint value = (jint)item.toNumber(exec); 125 env->SetIntArrayRegion((jintArray)jarray, (jsize)i, (jsize)1, &value); 126 } 127 break; 128 } 129 130 case long_type: 131 { 132 jarray = (jobjectArray)env->NewLongArray(length); 133 for (unsigned i = 0; i < length; i++) { 134 JSValue item = jsArray->get(exec, i); 135 jlong value = (jlong)item.toNumber(exec); 136 env->SetLongArrayRegion((jlongArray)jarray, (jsize)i, (jsize)1, &value); 137 } 138 break; 139 } 140 141 case float_type: 142 { 143 jarray = (jobjectArray)env->NewFloatArray(length); 144 for (unsigned i = 0; i < length; i++) { 145 JSValue item = jsArray->get(exec, i); 146 jfloat value = (jfloat)item.toNumber(exec); 147 env->SetFloatArrayRegion((jfloatArray)jarray, (jsize)i, (jsize)1, &value); 148 } 149 break; 150 } 151 152 case double_type: 153 { 154 jarray = (jobjectArray)env->NewDoubleArray(length); 155 for (unsigned i = 0; i < length; i++) { 156 JSValue item = jsArray->get(exec, i); 157 jdouble value = (jdouble)item.toNumber(exec); 158 env->SetDoubleArrayRegion((jdoubleArray)jarray, (jsize)i, (jsize)1, &value); 159 } 160 break; 161 } 162 163 case array_type: // don't handle embedded arrays 164 case void_type: // Don't expect arrays of void objects 165 case invalid_type: // Array of unknown objects 166 break; 167 } 168 169 // if it was not one of the cases handled, then null is returned 170 return jarray; 171 } 172 173 jvalue convertValueToJValue(ExecState* exec, RootObject* rootObject, JSValue value, JNIType jniType, const char* javaClassName) 174 { 175 JSLock lock(SilenceAssertionsOnly); 176 177 jvalue result; 178 memset(&result, 0, sizeof(jvalue)); 179 180 switch (jniType) { 181 case array_type: 182 case object_type: 183 { 184 // FIXME: JavaJSObject::convertValueToJObject functionality is almost exactly the same, 185 // these functions should use common code. 186 187 if (value.isObject()) { 188 JSObject* object = asObject(value); 189 if (object->inherits(&JavaRuntimeObject::s_info)) { 190 // Unwrap a Java instance. 191 JavaRuntimeObject* runtimeObject = static_cast<JavaRuntimeObject*>(object); 192 JavaInstance* instance = runtimeObject->getInternalJavaInstance(); 193 if (instance) 194 result.l = instance->javaInstance(); 195 #if 0 196 } else if (object->classInfo() == &RuntimeArray::s_info) { 197 // Input is a JavaScript Array that was originally created from a Java Array 198 RuntimeArray* imp = static_cast<RuntimeArray*>(object); 199 JavaArray* array = static_cast<JavaArray*>(imp->getConcreteArray()); 200 result.l = array->javaArray(); 201 } else if (object->classInfo() == &JSArray::info) { 202 // Input is a Javascript Array. We need to create it to a Java Array. 203 result.l = convertArrayInstanceToJavaArray(exec, asArray(value), javaClassName); 204 #endif 205 } else if (!result.l && (!strcmp(javaClassName, "java.lang.Object")) || (!strcmp(javaClassName, "netscape.javascript.JSObject"))) { 206 // Wrap objects in JSObject instances. 207 JNIEnv* env = getJNIEnv(); 208 // jclass jsObjectClass = env->FindClass("sun/plugin/javascript/webkit/JSObject"); 209 jclass jsObjectClass = env->FindClass("com/sun/webpane/platform/JSObject"); 210 jmethodID constructorID = env->GetMethodID(jsObjectClass, "<init>", "(J)V"); 211 if (constructorID) { 212 jlong nativeHandle = ptr_to_jlong(object); 213 if (rootObject) // ??? FIXME 214 rootObject->gcProtect(object); 215 result.l = env->NewObject(jsObjectClass, constructorID, nativeHandle); 216 } 217 } 218 } 219 220 // Create an appropriate Java object if target type is java.lang.Object. 221 if (!result.l && !strcmp(javaClassName, "java.lang.Object")) { 222 if (value.isString()) { 223 UString stringValue = asString(value)->value(exec); 224 JNIEnv* env = getJNIEnv(); 225 jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.data(), stringValue.size()); 226 result.l = javaString; 227 } else if (value.isNumber()) { 228 double doubleValue = value.uncheckedGetNumber(); 229 JNIEnv* env = getJNIEnv(); 230 jclass clazz = env->FindClass("java/lang/Double"); 231 jmethodID constructor = env->GetMethodID(clazz, "<init>", "(D)V"); 232 jobject javaDouble = env->functions->NewObject(env, clazz, constructor, doubleValue); 233 result.l = javaDouble; 234 } else if (value.isBoolean()) { 235 bool boolValue = value.getBoolean(); 236 JNIEnv* env = getJNIEnv(); 237 jclass clazz = env->FindClass("java/lang/Boolean"); 238 jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Z)V"); 239 jobject javaBoolean = env->functions->NewObject(env, clazz, constructor, boolValue); 240 result.l = javaBoolean; 241 } else if (value.isUndefined()) { 242 UString stringValue = "undefined"; 243 JNIEnv* env = getJNIEnv(); 244 jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.data(), stringValue.size()); 245 result.l = javaString; 246 } 247 } 248 249 // Convert value to a string if the target type is a java.lang.String, and we're not 250 // converting from a null. 251 if (!result.l && !strcmp(javaClassName, "java.lang.String")) { 252 if (!value.isNull()) { 253 UString stringValue = value.toString(exec); 254 JNIEnv* env = getJNIEnv(); 255 jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.data(), stringValue.size()); 256 result.l = javaString; 257 } 258 } 259 } 260 break; 261 262 case boolean_type: 263 { 264 result.z = (jboolean)value.toNumber(exec); 265 } 266 break; 267 268 case byte_type: 269 { 270 result.b = (jbyte)value.toNumber(exec); 271 } 272 break; 273 274 case char_type: 275 { 276 result.c = (jchar)value.toNumber(exec); 277 } 278 break; 279 280 case short_type: 281 { 282 result.s = (jshort)value.toNumber(exec); 283 } 284 break; 285 286 case int_type: 287 { 288 result.i = (jint)value.toNumber(exec); 289 } 290 break; 291 292 case long_type: 293 { 294 result.j = (jlong)value.toNumber(exec); 295 } 296 break; 297 298 case float_type: 299 { 300 result.f = (jfloat)value.toNumber(exec); 301 } 302 break; 303 304 case double_type: 305 { 306 result.d = (jdouble)value.toNumber(exec); 307 } 308 break; 309 310 case invalid_type: 311 case void_type: 312 break; 313 } 314 return result; 315 } 316 317 } // end of namespace Bindings 318 319 } // end of namespace JSC 320 321 #endif // ENABLE(JAVA_BRIDGE) --- EOF ---