• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
JavaField(JNIEnv * env,jobject aField)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 
dispatchValueFromInstance(ExecState * exec,const JavaInstance * instance,const char * name,const char * sig,JavaType returnType) const68 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 
valueFromInstance(ExecState * exec,const Instance * i) const95 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 
dispatchSetValueToInstance(ExecState * exec,const JavaInstance * instance,jvalue javaValue,const char * name,const char * sig) const155 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 
setValueToInstance(ExecState * exec,const Instance * i,JSValue aValue) const181 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