2 * Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
3 * Copyright 2010, The Android Open Source Project
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. 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.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
28 #include "JNIBridgeJSC.h"
30 #if ENABLE(JAVA_BRIDGE)
32 #include "JNIUtilityPrivate.h"
34 #include "runtime_array.h"
35 #include "runtime_object.h"
36 #include <runtime/Error.h>
39 using namespace JSC::Bindings;
40 using namespace WebCore;
42 JavaField::JavaField(JNIEnv* env, jobject aField)
44 // Get field type name
45 jstring fieldTypeName = 0;
46 if (jobject fieldType = callJNIMethod<jobject>(aField, "getType", "()Ljava/lang/Class;"))
47 fieldTypeName = static_cast<jstring>(callJNIMethod<jobject>(fieldType, "getName", "()Ljava/lang/String;"));
49 fieldTypeName = env->NewStringUTF("<Unknown>");
50 m_type = JavaString(env, fieldTypeName);
52 m_JNIType = JNITypeFromClassName(m_type.utf8());
55 jstring fieldName = static_cast<jstring>(callJNIMethod<jobject>(aField, "getName", "()Ljava/lang/String;"));
57 fieldName = env->NewStringUTF("<Unknown>");
58 m_name = JavaString(env, fieldName);
60 m_field = new JObjectWrapper(aField);
63 JSValue JavaArray::convertJObjectToArray(ExecState* exec, jobject anObject, const char* type, PassRefPtr<RootObject> rootObject)
68 return new (exec) RuntimeArray(exec, new JavaArray(anObject, type, rootObject));
71 jvalue JavaField::dispatchValueFromInstance(ExecState* exec, const JavaInstance* instance, const char* name, const char* sig, JNIType returnType) const
73 jobject jinstance = instance->javaInstance();
74 jobject fieldJInstance = m_field->m_instance;
75 JNIEnv* env = getJNIEnv();
78 memset(&result, 0, sizeof(jvalue));
79 jclass cls = env->GetObjectClass(fieldJInstance);
81 jmethodID mid = env->GetMethodID(cls, name, sig);
83 RootObject* rootObject = instance->rootObject();
84 if (rootObject && rootObject->nativeHandle()) {
85 JSValue exceptionDescription;
88 args[0].l = jinstance;
89 dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription);
90 if (exceptionDescription)
91 throwError(exec, createError(exec, exceptionDescription.toString(exec)));
98 JSValue JavaField::valueFromInstance(ExecState* exec, const Instance* i) const
100 const JavaInstance* instance = static_cast<const JavaInstance*>(i);
102 JSValue jsresult = jsUndefined();
108 jvalue result = dispatchValueFromInstance(exec, instance, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", object_type);
109 jobject anObject = result.l;
114 const char* arrayType = type();
115 if (arrayType[0] == '[')
116 jsresult = JavaArray::convertJObjectToArray(exec, anObject, arrayType, instance->rootObject());
118 jsresult = JavaInstance::create(anObject, instance->rootObject())->createRuntimeObject(exec);
123 jsresult = jsBoolean(dispatchValueFromInstance(exec, instance, "getBoolean", "(Ljava/lang/Object;)Z", boolean_type).z);
133 jvalue result = dispatchValueFromInstance(exec, instance, "getInt", "(Ljava/lang/Object;)I", int_type);
135 jsresult = jsNumber(exec, static_cast<int>(value));
144 jvalue result = dispatchValueFromInstance(exec, instance, "getDouble", "(Ljava/lang/Object;)D", double_type);
146 jsresult = jsNumber(exec, static_cast<double>(value));
153 LOG(LiveConnect, "JavaField::valueFromInstance getting %s = %s", UString(name()).utf8().data(), jsresult.toString(exec).ascii().data());
158 void JavaField::dispatchSetValueToInstance(ExecState* exec, const JavaInstance* instance, jvalue javaValue, const char* name, const char* sig) const
160 jobject jinstance = instance->javaInstance();
161 jobject fieldJInstance = m_field->m_instance;
162 JNIEnv* env = getJNIEnv();
164 jclass cls = env->GetObjectClass(fieldJInstance);
166 jmethodID mid = env->GetMethodID(cls, name, sig);
168 RootObject* rootObject = instance->rootObject();
169 if (rootObject && rootObject->nativeHandle()) {
170 JSValue exceptionDescription;
174 args[0].l = jinstance;
176 dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, void_type, mid, args, result, 0, exceptionDescription);
177 if (exceptionDescription)
178 throwError(exec, createError(exec, exceptionDescription.toString(exec)));
184 void JavaField::setValueToInstance(ExecState* exec, const Instance* i, JSValue aValue) const
186 const JavaInstance* instance = static_cast<const JavaInstance*>(i);
187 jvalue javaValue = convertValueToJValue(exec, i->rootObject(), aValue, m_JNIType, type());
189 LOG(LiveConnect, "JavaField::setValueToInstance setting value %s to %s", UString(name()).utf8().data(), aValue.toString(exec).ascii().data());
195 dispatchSetValueToInstance(exec, instance, javaValue, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V");
201 dispatchSetValueToInstance(exec, instance, javaValue, "setBoolean", "(Ljava/lang/Object;Z)V");
207 dispatchSetValueToInstance(exec, instance, javaValue, "setByte", "(Ljava/lang/Object;B)V");
213 dispatchSetValueToInstance(exec, instance, javaValue, "setChar", "(Ljava/lang/Object;C)V");
219 dispatchSetValueToInstance(exec, instance, javaValue, "setShort", "(Ljava/lang/Object;S)V");
225 dispatchSetValueToInstance(exec, instance, javaValue, "setInt", "(Ljava/lang/Object;I)V");
231 dispatchSetValueToInstance(exec, instance, javaValue, "setLong", "(Ljava/lang/Object;J)V");
237 dispatchSetValueToInstance(exec, instance, javaValue, "setFloat", "(Ljava/lang/Object;F)V");
243 dispatchSetValueToInstance(exec, instance, javaValue, "setDouble", "(Ljava/lang/Object;D)V");
251 JavaArray::JavaArray(jobject array, const char* type, PassRefPtr<RootObject> rootObject)
254 m_array = new JObjectWrapper(array);
255 // Java array are fixed length, so we can cache length.
256 JNIEnv* env = getJNIEnv();
257 m_length = env->GetArrayLength(static_cast<jarray>(m_array->m_instance));
258 m_type = strdup(type);
261 JavaArray::~JavaArray()
263 free(const_cast<char*>(m_type));
266 RootObject* JavaArray::rootObject() const
268 return m_rootObject && m_rootObject->isValid() ? m_rootObject.get() : 0;
271 void JavaArray::setValueAt(ExecState* exec, unsigned index, JSValue aValue) const
273 JNIEnv* env = getJNIEnv();
274 char* javaClassName = 0;
276 JNIType arrayType = JNITypeFromPrimitiveType(m_type[1]);
277 if (m_type[1] == 'L') {
278 // The type of the array will be something like:
279 // "[Ljava.lang.string;". This is guaranteed, so no need
280 // for extra sanity checks.
281 javaClassName = strdup(&m_type[2]);
282 javaClassName[strchr(javaClassName, ';')-javaClassName] = 0;
284 jvalue aJValue = convertValueToJValue(exec, m_rootObject.get(), aValue, arrayType, javaClassName);
289 env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray()), index, aJValue.l);
295 env->SetBooleanArrayRegion(static_cast<jbooleanArray>(javaArray()), index, 1, &aJValue.z);
301 env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray()), index, 1, &aJValue.b);
307 env->SetCharArrayRegion(static_cast<jcharArray>(javaArray()), index, 1, &aJValue.c);
313 env->SetShortArrayRegion(static_cast<jshortArray>(javaArray()), index, 1, &aJValue.s);
319 env->SetIntArrayRegion(static_cast<jintArray>(javaArray()), index, 1, &aJValue.i);
325 env->SetLongArrayRegion(static_cast<jlongArray>(javaArray()), index, 1, &aJValue.j);
330 env->SetFloatArrayRegion(static_cast<jfloatArray>(javaArray()), index, 1, &aJValue.f);
336 env->SetDoubleArrayRegion(static_cast<jdoubleArray>(javaArray()), index, 1, &aJValue.d);
344 free(const_cast<char*>(javaClassName));
348 JSValue JavaArray::valueAt(ExecState* exec, unsigned index) const
350 JNIEnv* env = getJNIEnv();
351 JNIType arrayType = JNITypeFromPrimitiveType(m_type[1]);
355 jobjectArray objectArray = static_cast<jobjectArray>(javaArray());
357 anObject = env->GetObjectArrayElement(objectArray, index);
364 if (m_type[1] == '[')
365 return JavaArray::convertJObjectToArray(exec, anObject, m_type + 1, rootObject());
366 // or array of other object type?
367 return JavaInstance::create(anObject, rootObject())->createRuntimeObject(exec);
372 jbooleanArray booleanArray = static_cast<jbooleanArray>(javaArray());
374 env->GetBooleanArrayRegion(booleanArray, index, 1, &aBoolean);
375 return jsBoolean(aBoolean);
380 jbyteArray byteArray = static_cast<jbyteArray>(javaArray());
382 env->GetByteArrayRegion(byteArray, index, 1, &aByte);
383 return jsNumber(exec, aByte);
388 jcharArray charArray = static_cast<jcharArray>(javaArray());
390 env->GetCharArrayRegion(charArray, index, 1, &aChar);
391 return jsNumber(exec, aChar);
397 jshortArray shortArray = static_cast<jshortArray>(javaArray());
399 env->GetShortArrayRegion(shortArray, index, 1, &aShort);
400 return jsNumber(exec, aShort);
405 jintArray intArray = static_cast<jintArray>(javaArray());
407 env->GetIntArrayRegion(intArray, index, 1, &anInt);
408 return jsNumber(exec, anInt);
413 jlongArray longArray = static_cast<jlongArray>(javaArray());
415 env->GetLongArrayRegion(longArray, index, 1, &aLong);
416 return jsNumber(exec, aLong);
421 jfloatArray floatArray = static_cast<jfloatArray>(javaArray());
423 env->GetFloatArrayRegion(floatArray, index, 1, &aFloat);
424 return jsNumber(exec, aFloat);
429 jdoubleArray doubleArray = static_cast<jdoubleArray>(javaArray());
431 env->GetDoubleArrayRegion(doubleArray, index, 1, &aDouble);
432 return jsNumber(exec, aDouble);
437 return jsUndefined();
440 unsigned int JavaArray::getLength() const
445 #endif // ENABLE(JAVA_BRIDGE)