Home | History | Annotate | Download | only in jsc
      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