1 /* 2 * Copyright (C) 2003, 2004, 2005, 2007, 2009 Apple Inc. All rights reserved. 3 * Copyright 2010, 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 * 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. 13 * 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. 25 */ 26 27 #include "config.h" 28 #include "JavaFieldJSC.h" 29 30 #if ENABLE(JAVA_BRIDGE) 31 32 #include "JNIUtilityPrivate.h" 33 #include "JavaArrayJSC.h" 34 #include "Logging.h" 35 #include "runtime_array.h" 36 #include "runtime_object.h" 37 #include <runtime/Error.h> 38 39 using namespace JSC; 40 using namespace JSC::Bindings; 41 using namespace WebCore; 42 43 JavaField::JavaField(JNIEnv* env, jobject aField) 44 { 45 // Get field type name 46 jstring fieldTypeName = 0; 47 jclass fieldType = static_cast<jclass>(callJNIMethod<jobject>(aField, "getType", "()Ljava/lang/Class;")); 48 if (fieldType) 49 fieldTypeName = static_cast<jstring>(callJNIMethod<jobject>(fieldType, "getName", "()Ljava/lang/String;")); 50 if (!fieldTypeName) 51 fieldTypeName = env->NewStringUTF("<Unknown>"); 52 m_typeClassName = JavaString(env, fieldTypeName); 53 54 m_type = javaTypeFromClassName(m_typeClassName.utf8()); 55 env->DeleteLocalRef(fieldType); 56 env->DeleteLocalRef(fieldTypeName); 57 58 // Get field name 59 jstring fieldName = static_cast<jstring>(callJNIMethod<jobject>(aField, "getName", "()Ljava/lang/String;")); 60 if (!fieldName) 61 fieldName = env->NewStringUTF("<Unknown>"); 62 m_name = JavaString(env, fieldName); 63 env->DeleteLocalRef(fieldName); 64 65 m_field = new JobjectWrapper(aField); 66 } 67 68 jvalue JavaField::dispatchValueFromInstance(ExecState* exec, const JavaInstance* instance, const char* name, const char* sig, JavaType returnType) const 69 { 70 jobject jinstance = instance->javaInstance(); 71 jobject fieldJInstance = m_field->m_instance; 72 JNIEnv* env = getJNIEnv(); 73 jvalue result; 74 75 memset(&result, 0, sizeof(jvalue)); 76 jclass cls = env->GetObjectClass(fieldJInstance); 77 if (cls) { 78 jmethodID mid = env->GetMethodID(cls, name, sig); 79 if (mid) { 80 RootObject* rootObject = instance->rootObject(); 81 if (rootObject && rootObject->nativeHandle()) { 82 JSValue exceptionDescription; 83 jvalue args[1]; 84 85 args[0].l = jinstance; 86 dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, returnType, mid, args, result, 0, exceptionDescription); 87 if (exceptionDescription) 88 throwError(exec, createError(exec, exceptionDescription.toString(exec))); 89 } 90 } 91 } 92 return result; 93 } 94 95 JSValue JavaField::valueFromInstance(ExecState* exec, const Instance* i) const 96 { 97 const JavaInstance* instance = static_cast<const JavaInstance*>(i); 98 99 JSValue jsresult = jsUndefined(); 100 101 switch (m_type) { 102 case JavaTypeArray: 103 case JavaTypeObject: 104 { 105 jvalue result = dispatchValueFromInstance(exec, instance, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", JavaTypeObject); 106 jobject anObject = result.l; 107 108 if (!anObject) 109 return jsNull(); 110 111 const char* arrayType = typeClassName(); 112 if (arrayType[0] == '[') 113 jsresult = JavaArray::convertJObjectToArray(exec, anObject, arrayType, instance->rootObject()); 114 else if (anObject) 115 jsresult = JavaInstance::create(anObject, instance->rootObject())->createRuntimeObject(exec); 116 } 117 break; 118 119 case JavaTypeBoolean: 120 jsresult = jsBoolean(dispatchValueFromInstance(exec, instance, "getBoolean", "(Ljava/lang/Object;)Z", JavaTypeBoolean).z); 121 break; 122 123 case JavaTypeByte: 124 case JavaTypeChar: 125 case JavaTypeShort: 126 127 case JavaTypeInt: 128 { 129 jint value; 130 jvalue result = dispatchValueFromInstance(exec, instance, "getInt", "(Ljava/lang/Object;)I", JavaTypeInt); 131 value = result.i; 132 jsresult = jsNumber(static_cast<int>(value)); 133 } 134 break; 135 136 case JavaTypeLong: 137 case JavaTypeFloat: 138 case JavaTypeDouble: 139 { 140 jdouble value; 141 jvalue result = dispatchValueFromInstance(exec, instance, "getDouble", "(Ljava/lang/Object;)D", JavaTypeDouble); 142 value = result.i; 143 jsresult = jsNumber(static_cast<double>(value)); 144 } 145 break; 146 default: 147 break; 148 } 149 150 LOG(LiveConnect, "JavaField::valueFromInstance getting %s = %s", UString(name().impl()).utf8().data(), jsresult.toString(exec).ascii().data()); 151 152 return jsresult; 153 } 154 155 void JavaField::dispatchSetValueToInstance(ExecState* exec, const JavaInstance* instance, jvalue javaValue, const char* name, const char* sig) const 156 { 157 jobject jinstance = instance->javaInstance(); 158 jobject fieldJInstance = m_field->m_instance; 159 JNIEnv* env = getJNIEnv(); 160 161 jclass cls = env->GetObjectClass(fieldJInstance); 162 if (cls) { 163 jmethodID mid = env->GetMethodID(cls, name, sig); 164 if (mid) { 165 RootObject* rootObject = instance->rootObject(); 166 if (rootObject && rootObject->nativeHandle()) { 167 JSValue exceptionDescription; 168 jvalue args[2]; 169 jvalue result; 170 171 args[0].l = jinstance; 172 args[1] = javaValue; 173 dispatchJNICall(exec, rootObject->nativeHandle(), fieldJInstance, false, JavaTypeVoid, mid, args, result, 0, exceptionDescription); 174 if (exceptionDescription) 175 throwError(exec, createError(exec, exceptionDescription.toString(exec))); 176 } 177 } 178 } 179 } 180 181 void JavaField::setValueToInstance(ExecState* exec, const Instance* i, JSValue aValue) const 182 { 183 const JavaInstance* instance = static_cast<const JavaInstance*>(i); 184 jvalue javaValue = convertValueToJValue(exec, i->rootObject(), aValue, m_type, typeClassName()); 185 186 LOG(LiveConnect, "JavaField::setValueToInstance setting value %s to %s", UString(name().impl()).utf8().data(), aValue.toString(exec).ascii().data()); 187 188 switch (m_type) { 189 case JavaTypeArray: 190 case JavaTypeObject: 191 { 192 dispatchSetValueToInstance(exec, instance, javaValue, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V"); 193 } 194 break; 195 196 case JavaTypeBoolean: 197 { 198 dispatchSetValueToInstance(exec, instance, javaValue, "setBoolean", "(Ljava/lang/Object;Z)V"); 199 } 200 break; 201 202 case JavaTypeByte: 203 { 204 dispatchSetValueToInstance(exec, instance, javaValue, "setByte", "(Ljava/lang/Object;B)V"); 205 } 206 break; 207 208 case JavaTypeChar: 209 { 210 dispatchSetValueToInstance(exec, instance, javaValue, "setChar", "(Ljava/lang/Object;C)V"); 211 } 212 break; 213 214 case JavaTypeShort: 215 { 216 dispatchSetValueToInstance(exec, instance, javaValue, "setShort", "(Ljava/lang/Object;S)V"); 217 } 218 break; 219 220 case JavaTypeInt: 221 { 222 dispatchSetValueToInstance(exec, instance, javaValue, "setInt", "(Ljava/lang/Object;I)V"); 223 } 224 break; 225 226 case JavaTypeLong: 227 { 228 dispatchSetValueToInstance(exec, instance, javaValue, "setLong", "(Ljava/lang/Object;J)V"); 229 } 230 break; 231 232 case JavaTypeFloat: 233 { 234 dispatchSetValueToInstance(exec, instance, javaValue, "setFloat", "(Ljava/lang/Object;F)V"); 235 } 236 break; 237 238 case JavaTypeDouble: 239 { 240 dispatchSetValueToInstance(exec, instance, javaValue, "setDouble", "(Ljava/lang/Object;D)V"); 241 } 242 break; 243 default: 244 break; 245 } 246 } 247 248 #endif // ENABLE(JAVA_BRIDGE) 249