]>
git.saurik.com Git - apple/javascriptcore.git/blob - bindings/jni/jni_instance.cpp
f97da15a40b4885acb5fb4385def8e5408cfb734
2 * Copyright (C) 2003 Apple Computer, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if ENABLE(JAVA_BINDINGS)
30 #include "jni_class.h"
31 #include "jni_instance.h"
32 #include "jni_runtime.h"
33 #include "jni_utility.h"
34 #include "runtime_object.h"
35 #include "runtime_root.h"
38 #define JS_LOG(formatAndArgs...) ((void)0)
40 #define JS_LOG(formatAndArgs...) { \
41 fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \
42 fprintf(stderr, formatAndArgs); \
46 using namespace KJS::Bindings
;
49 JavaInstance::JavaInstance (jobject instance
, PassRefPtr
<RootObject
> rootObject
)
50 : Instance(rootObject
)
52 _instance
= new JObjectWrapper (instance
);
56 JavaInstance::~JavaInstance ()
61 #define NUM_LOCAL_REFS 64
63 void JavaInstance::begin()
65 getJNIEnv()->PushLocalFrame (NUM_LOCAL_REFS
);
68 void JavaInstance::end()
70 getJNIEnv()->PopLocalFrame (NULL
);
73 Class
*JavaInstance::getClass() const
76 _class
= new JavaClass (_instance
->_instance
);
80 JSValue
*JavaInstance::stringValue() const
84 jstring stringValue
= (jstring
)callJNIObjectMethod (_instance
->_instance
, "toString", "()Ljava/lang/String;");
85 JNIEnv
*env
= getJNIEnv();
86 const jchar
*c
= getUCharactersFromJStringInEnv(env
, stringValue
);
87 UString
u((const UChar
*)c
, (int)env
->GetStringLength(stringValue
));
88 releaseUCharactersForJStringInEnv(env
, stringValue
, c
);
92 JSValue
*JavaInstance::numberValue() const
94 jdouble doubleValue
= callJNIDoubleMethod (_instance
->_instance
, "doubleValue", "()D");
95 return jsNumber(doubleValue
);
98 JSValue
*JavaInstance::booleanValue() const
100 jboolean booleanValue
= callJNIBooleanMethod (_instance
->_instance
, "booleanValue", "()Z");
101 return jsBoolean(booleanValue
);
104 JSValue
*JavaInstance::invokeMethod (ExecState
*exec
, const MethodList
&methodList
, const List
&args
)
106 int i
, count
= args
.size();
108 JSValue
*resultValue
;
110 size_t numMethods
= methodList
.size();
112 // Try to find a good match for the overloaded method. The
113 // fundamental problem is that JavaScript doesn have the
114 // notion of method overloading and Java does. We could
115 // get a bit more sophisticated and attempt to does some
116 // type checking as we as checking the number of parameters.
118 for (size_t methodIndex
= 0; methodIndex
< numMethods
; methodIndex
++) {
119 aMethod
= methodList
[methodIndex
];
120 if (aMethod
->numParameters() == count
) {
126 JS_LOG ("unable to find an appropiate method\n");
127 return jsUndefined();
130 const JavaMethod
*jMethod
= static_cast<const JavaMethod
*>(method
);
131 JS_LOG ("call %s %s on %p\n", method
->name(), jMethod
->signature(), _instance
->_instance
);
134 jArgs
= (jvalue
*)malloc (count
* sizeof(jvalue
));
139 for (i
= 0; i
< count
; i
++) {
140 JavaParameter
* aParameter
= jMethod
->parameterAt(i
);
141 jArgs
[i
] = convertValueToJValue (exec
, args
.at(i
), aParameter
->getJNIType(), aParameter
->type());
142 JS_LOG("arg[%d] = %s\n", i
, args
.at(i
)->toString(exec
).ascii());
147 // Try to use the JNI abstraction first, otherwise fall back to
148 // nornmal JNI. The JNI dispatch abstraction allows the Java plugin
149 // to dispatch the call on the appropriate internal VM thread.
150 RootObject
* rootObject
= this->rootObject();
152 return jsUndefined();
154 bool handled
= false;
155 if (rootObject
->nativeHandle()) {
156 jobject obj
= _instance
->_instance
;
157 JSValue
*exceptionDescription
= NULL
;
158 const char *callingURL
= 0; // FIXME, need to propagate calling URL to Java
159 handled
= dispatchJNICall(rootObject
->nativeHandle(), obj
, jMethod
->isStatic(), jMethod
->JNIReturnType(), jMethod
->methodID(obj
), jArgs
, result
, callingURL
, exceptionDescription
);
160 if (exceptionDescription
) {
161 throwError(exec
, GeneralError
, exceptionDescription
->toString(exec
));
163 return jsUndefined();
167 // The following code can be conditionally removed once we have a Tiger update that
168 // contains the new Java plugin. It is needed for builds prior to Tiger.
170 jobject obj
= _instance
->_instance
;
171 switch (jMethod
->JNIReturnType()){
173 callJNIVoidMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
178 result
.l
= callJNIObjectMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
183 result
.z
= callJNIBooleanMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
188 result
.b
= callJNIByteMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
193 result
.c
= callJNICharMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
198 result
.s
= callJNIShortMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
203 result
.i
= callJNIIntMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
208 result
.j
= callJNILongMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
213 result
.f
= callJNIFloatMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
218 result
.d
= callJNIDoubleMethodIDA (obj
, jMethod
->methodID(obj
), jArgs
);
229 switch (jMethod
->JNIReturnType()){
231 resultValue
= jsUndefined();
237 const char *arrayType
= jMethod
->returnType();
238 if (arrayType
[0] == '[') {
239 resultValue
= JavaArray::convertJObjectToArray(exec
, result
.l
, arrayType
, rootObject
);
242 resultValue
= Instance::createRuntimeObject(Instance::JavaLanguage
, result
.l
, rootObject
);
246 resultValue
= jsUndefined();
252 resultValue
= jsBoolean(result
.z
);
257 resultValue
= jsNumber(result
.b
);
262 resultValue
= jsNumber(result
.c
);
267 resultValue
= jsNumber(result
.s
);
272 resultValue
= jsNumber(result
.i
);
277 resultValue
= jsNumber(result
.j
);
282 resultValue
= jsNumber(result
.f
);
287 resultValue
= jsNumber(result
.d
);
293 resultValue
= jsUndefined();
303 JSValue
*JavaInstance::defaultValue (JSType hint
) const
305 if (hint
== StringType
) {
306 return stringValue();
308 else if (hint
== NumberType
) {
309 return numberValue();
311 else if (hint
== BooleanType
) {
312 return booleanValue();
314 else if (hint
== UnspecifiedType
) {
315 JavaClass
*aClass
= static_cast<JavaClass
*>(getClass());
316 if (aClass
->isStringClass()) {
317 return stringValue();
319 else if (aClass
->isNumberClass()) {
320 return numberValue();
322 else if (aClass
->isBooleanClass()) {
323 return booleanValue();
330 JSValue
*JavaInstance::valueOf() const
332 return stringValue();
335 JObjectWrapper::JObjectWrapper(jobject instance
)
338 assert (instance
!= 0);
340 // Cache the JNIEnv used to get the global ref for this java instanace.
341 // It'll be used to delete the reference.
344 _instance
= _env
->NewGlobalRef (instance
);
346 JS_LOG ("new global ref %p for %p\n", _instance
, instance
);
348 if (_instance
== NULL
) {
349 fprintf (stderr
, "%s: could not get GlobalRef for %p\n", __PRETTY_FUNCTION__
, instance
);
353 JObjectWrapper::~JObjectWrapper() {
354 JS_LOG ("deleting global ref %p\n", _instance
);
355 _env
->DeleteGlobalRef (_instance
);
358 #endif // ENABLE(JAVA_BINDINGS)