1/*
2 * Copyright (C) 2003, 2004, 2005, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#ifndef JNIUtility_h
27#define JNIUtility_h
28
29#if ENABLE(JAVA_BRIDGE)
30
31#include "JavaType.h"
32
33#if OS(MAC_OS_X)
34#include <JavaVM/jni.h>
35#else
36#include <jni.h>
37#endif
38
39namespace JSC {
40
41namespace Bindings {
42
43const char* getCharactersFromJString(jstring);
44void releaseCharactersForJString(jstring, const char*);
45
46const char* getCharactersFromJStringInEnv(JNIEnv*, jstring);
47void releaseCharactersForJStringInEnv(JNIEnv*, jstring, const char*);
48const jchar* getUCharactersFromJStringInEnv(JNIEnv*, jstring);
49void releaseUCharactersForJStringInEnv(JNIEnv*, jstring, const jchar*);
50
51JavaType javaTypeFromClassName(const char* name);
52JavaType javaTypeFromPrimitiveType(char type);
53const char* signatureFromJavaType(JavaType);
54
55jvalue getJNIField(jobject, JavaType, const char* name, const char* signature);
56jvalue callJNIMethod(jobject, JavaType returnType, const char* name, const char* signature, jvalue* args);
57
58jmethodID getMethodID(jobject, const char* name, const char* sig);
59JNIEnv* getJNIEnv();
60JavaVM* getJavaVM();
61void setJavaVM(JavaVM*);
62
63
64template <typename T> struct JNICaller;
65
66template<> struct JNICaller<void> {
67    static void callA(jobject obj, jmethodID mid, jvalue* args)
68    {
69        getJNIEnv()->CallVoidMethodA(obj, mid, args);
70    }
71    static void callV(jobject obj, jmethodID mid, va_list args)
72    {
73        getJNIEnv()->CallVoidMethodV(obj, mid, args);
74    }
75};
76
77template<> struct JNICaller<jobject> {
78    static jobject callA(jobject obj, jmethodID mid, jvalue* args)
79    {
80        return getJNIEnv()->CallObjectMethodA(obj, mid, args);
81    }
82    static jobject callV(jobject obj, jmethodID mid, va_list args)
83    {
84        return getJNIEnv()->CallObjectMethodV(obj, mid, args);
85    }
86};
87
88template<> struct JNICaller<jboolean> {
89    static jboolean callA(jobject obj, jmethodID mid, jvalue* args)
90    {
91        return getJNIEnv()->CallBooleanMethodA(obj, mid, args);
92    }
93    static jboolean callV(jobject obj, jmethodID mid, va_list args)
94    {
95        return getJNIEnv()->CallBooleanMethodV(obj, mid, args);
96    }
97    static jboolean callStaticV(jclass cls, jmethodID mid, va_list args)
98    {
99        return getJNIEnv()->CallStaticBooleanMethod(cls, mid, args);
100    }
101};
102
103template<> struct JNICaller<jbyte> {
104    static jbyte callA(jobject obj, jmethodID mid, jvalue* args)
105    {
106        return getJNIEnv()->CallByteMethodA(obj, mid, args);
107    }
108    static jbyte callV(jobject obj, jmethodID mid, va_list args)
109    {
110        return getJNIEnv()->CallByteMethodV(obj, mid, args);
111    }
112};
113
114template<> struct JNICaller<jchar> {
115    static jchar callA(jobject obj, jmethodID mid, jvalue* args)
116    {
117        return getJNIEnv()->CallCharMethodA(obj, mid, args);
118    }
119    static jchar callV(jobject obj, jmethodID mid, va_list args)
120    {
121        return getJNIEnv()->CallCharMethodV(obj, mid, args);
122    }
123};
124
125template<> struct JNICaller<jshort> {
126    static jshort callA(jobject obj, jmethodID mid, jvalue* args)
127    {
128        return getJNIEnv()->CallShortMethodA(obj, mid, args);
129    }
130    static jshort callV(jobject obj, jmethodID mid, va_list args)
131    {
132        return getJNIEnv()->CallShortMethodV(obj, mid, args);
133    }
134};
135
136template<> struct JNICaller<jint> {
137    static jint callA(jobject obj, jmethodID mid, jvalue* args)
138    {
139        return getJNIEnv()->CallIntMethodA(obj, mid, args);
140    }
141    static jint callV(jobject obj, jmethodID mid, va_list args)
142    {
143        return getJNIEnv()->CallIntMethodV(obj, mid, args);
144    }
145};
146
147template<> struct JNICaller<jlong> {
148    static jlong callA(jobject obj, jmethodID mid, jvalue* args)
149    {
150        return getJNIEnv()->CallLongMethodA(obj, mid, args);
151    }
152    static jlong callV(jobject obj, jmethodID mid, va_list args)
153    {
154        return getJNIEnv()->CallLongMethodV(obj, mid, args);
155    }
156};
157
158template<> struct JNICaller<jfloat> {
159    static jfloat callA(jobject obj, jmethodID mid, jvalue* args)
160    {
161        return getJNIEnv()->CallFloatMethodA(obj, mid, args);
162    }
163    static jfloat callV(jobject obj, jmethodID mid, va_list args)
164    {
165        return getJNIEnv()->CallFloatMethodV(obj, mid, args);
166    }
167};
168
169template<> struct JNICaller<jdouble> {
170    static jdouble callA(jobject obj, jmethodID mid, jvalue* args)
171    {
172        return getJNIEnv()->CallDoubleMethodA(obj, mid, args);
173    }
174    static jdouble callV(jobject obj, jmethodID mid, va_list args)
175    {
176        return getJNIEnv()->CallDoubleMethodV(obj, mid, args);
177    }
178};
179
180template<typename T> T callJNIMethodIDA(jobject obj, jmethodID mid, jvalue *args)
181{
182    return JNICaller<T>::callA(obj, mid, args);
183}
184
185template<typename T>
186static T callJNIMethodV(jobject obj, const char* name, const char* sig, va_list args)
187{
188    JavaVM* jvm = getJavaVM();
189    JNIEnv* env = getJNIEnv();
190
191    if (obj && jvm && env) {
192        jclass cls = env->GetObjectClass(obj);
193        if (cls) {
194            jmethodID mid = env->GetMethodID(cls, name, sig);
195            if (mid) {
196                // Avoids references to cls without popping the local frame.
197                env->DeleteLocalRef(cls);
198                return JNICaller<T>::callV(obj, mid, args);
199            }
200            LOG_ERROR("Could not find method: %s for %p", name, obj);
201            env->ExceptionDescribe();
202            env->ExceptionClear();
203            fprintf(stderr, "\n");
204
205            env->DeleteLocalRef(cls);
206        } else
207            LOG_ERROR("Could not find class for %p", obj);
208    }
209
210    return 0;
211}
212
213template<typename T>
214T callJNIMethod(jobject obj, const char* methodName, const char* methodSignature, ...)
215{
216    va_list args;
217    va_start(args, methodSignature);
218
219    T result = callJNIMethodV<T>(obj, methodName, methodSignature, args);
220
221    va_end(args);
222
223    return result;
224}
225
226template<typename T>
227T callJNIStaticMethod(jclass cls, const char* methodName, const char* methodSignature, ...)
228{
229    JavaVM* jvm = getJavaVM();
230    JNIEnv* env = getJNIEnv();
231    va_list args;
232
233    va_start(args, methodSignature);
234
235    T result = 0;
236
237    if (cls && jvm && env) {
238        jmethodID mid = env->GetStaticMethodID(cls, methodName, methodSignature);
239        if (mid)
240            result = JNICaller<T>::callStaticV(cls, mid, args);
241        else {
242            LOG_ERROR("Could not find method: %s for %p", methodName, cls);
243            env->ExceptionDescribe();
244            env->ExceptionClear();
245            fprintf(stderr, "\n");
246        }
247    }
248
249    va_end(args);
250
251    return result;
252}
253
254} // namespace Bindings
255
256} // namespace JSC
257
258#endif // ENABLE(JAVA_BRIDGE)
259
260#endif // JNIUtility_h
261