Reviewed by Jon.
[WebKit-https.git] / WebCore / bridge / jni / jni_utility.h
1 /*
2  * Copyright (C) 2003 Apple Computer, 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 #ifndef _JNI_UTILITY_H_
26 #define _JNI_UTILITY_H_
27
28 #include <JavaVM/jni.h>
29
30 // The order of these items can not be modified as they are tightly
31 // bound with the JVM on Mac OSX. If new types need to be added, they
32 // should be added to the end. It is used in jni_obc.mm when calling
33 // through to the JVM. Newly added items need to be made compatible
34 // in that file.
35 typedef enum {
36     invalid_type = 0,
37     void_type,
38     object_type,
39     boolean_type,
40     byte_type,
41     char_type,
42     short_type,
43     int_type,
44     long_type,
45     float_type,
46     double_type,
47     array_type
48 } JNIType;
49
50 namespace KJS {
51
52 class ExecState;
53 class JSObject;    
54 class JSValue;
55
56 namespace Bindings {
57
58 class JavaParameter;
59
60 const char *getCharactersFromJString(jstring aJString);
61 void releaseCharactersForJString(jstring aJString, const char *s);
62
63 const char *getCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
64 void releaseCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const char *s);
65 const jchar *getUCharactersFromJStringInEnv(JNIEnv *env, jstring aJString);
66 void releaseUCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const jchar *s);
67
68 JNIType JNITypeFromClassName(const char *name);
69 JNIType JNITypeFromPrimitiveType(char type);
70 const char *signatureFromPrimitiveType(JNIType type);
71
72 jvalue convertValueToJValue(ExecState *exec, JSValue *value, JNIType _JNIType, const char *javaClassName);
73
74 jvalue getJNIField(jobject obj, JNIType type, const char *name, const char *signature);
75
76 jmethodID getMethodID(jobject obj, const char *name, const char *sig);
77 JNIEnv* getJNIEnv();
78 JavaVM* getJavaVM();
79 void setJavaVM(JavaVM*);
80     
81     
82 template <typename T> struct JNICaller;
83
84 template<> struct JNICaller<void> {
85     static void callA(jobject obj, jmethodID mid, jvalue* args)
86     {
87         return getJNIEnv()->CallVoidMethodA(obj, mid, args);
88     }
89     static void callV(jobject obj, jmethodID mid, va_list args)
90     {
91         return getJNIEnv()->CallVoidMethodV(obj, mid, args);
92     }
93 };
94
95 template<> struct JNICaller<jobject> {
96     static jobject callA(jobject obj, jmethodID mid, jvalue* args)
97     {
98         return getJNIEnv()->CallObjectMethodA(obj, mid, args);
99     }
100     static jobject callV(jobject obj, jmethodID mid, va_list args)
101     {
102         return getJNIEnv()->CallObjectMethodV(obj, mid, args);
103     }    
104 };
105
106 template<> struct JNICaller<jboolean> {
107     static jboolean callA(jobject obj, jmethodID mid, jvalue* args)
108     {
109         return getJNIEnv()->CallBooleanMethodA(obj, mid, args);
110     }
111     static jboolean callV(jobject obj, jmethodID mid, va_list args)
112     {
113         return getJNIEnv()->CallBooleanMethodV(obj, mid, args);
114     }
115     static jboolean callStaticV(jclass cls, jmethodID mid, va_list args)
116     {
117         return getJNIEnv()->CallStaticBooleanMethod(cls, mid, args);
118     }
119     
120 };
121
122 template<> struct JNICaller<jbyte> {
123     static jbyte callA(jobject obj, jmethodID mid, jvalue* args)
124     {
125         return getJNIEnv()->CallByteMethodA(obj, mid, args);
126     }
127     static jbyte callV(jobject obj, jmethodID mid, va_list args)
128     {
129         return getJNIEnv()->CallByteMethodV(obj, mid, args);
130     }
131 };
132
133 template<> struct JNICaller<jchar> {
134     static jchar callA(jobject obj, jmethodID mid, jvalue* args)
135     {
136         return getJNIEnv()->CallCharMethodA(obj, mid, args);
137     }
138     static jchar callV(jobject obj, jmethodID mid, va_list args)
139     {
140         return getJNIEnv()->CallCharMethodV(obj, mid, args);
141     }    
142 };
143
144 template<> struct JNICaller<jshort> {
145     static jshort callA(jobject obj, jmethodID mid, jvalue* args)
146     {
147         return getJNIEnv()->CallShortMethodA(obj, mid, args);
148     }
149     static jshort callV(jobject obj, jmethodID mid, va_list args)
150     {
151         return getJNIEnv()->CallShortMethodV(obj, mid, args);
152     }
153 };
154
155 template<> struct JNICaller<jint> {
156     static jint callA(jobject obj, jmethodID mid, jvalue* args)
157     {
158         return getJNIEnv()->CallIntMethodA(obj, mid, args);
159     }
160     static jint callV(jobject obj, jmethodID mid, va_list args)
161     {
162         return getJNIEnv()->CallIntMethodV(obj, mid, args);
163     }
164 };
165
166 template<> struct JNICaller<jlong> {
167     static jlong callA(jobject obj, jmethodID mid, jvalue* args)
168     {
169         return getJNIEnv()->CallLongMethodA(obj, mid, args);
170     }
171     static jlong callV(jobject obj, jmethodID mid, va_list args)
172     {
173         return getJNIEnv()->CallLongMethodV(obj, mid, args);
174     }
175 };
176
177 template<> struct JNICaller<jfloat> {
178     static jfloat callA(jobject obj, jmethodID mid, jvalue* args)
179     {
180         return getJNIEnv()->CallFloatMethodA(obj, mid, args);
181     }
182     static jfloat callV(jobject obj, jmethodID mid, va_list args)
183     {
184         return getJNIEnv()->CallFloatMethodV(obj, mid, args);
185     }
186 };
187
188 template<> struct JNICaller<jdouble> {
189     static jdouble callA(jobject obj, jmethodID mid, jvalue* args)
190     {
191         return getJNIEnv()->CallDoubleMethodA(obj, mid, args);
192     }
193     static jdouble callV(jobject obj, jmethodID mid, va_list args)
194     {
195         return getJNIEnv()->CallDoubleMethodV(obj, mid, args);
196     }
197 };
198
199 template<typename T> T callJNIMethodIDA(jobject obj, jmethodID mid, jvalue *args)
200 {
201     return JNICaller<T>::callA(obj, mid, args);
202 }
203     
204 template<typename T>
205 static T callJNIMethodV(jobject obj, const char *name, const char *sig, va_list args)
206 {
207     JavaVM *jvm = getJavaVM();
208     JNIEnv *env = getJNIEnv();
209     
210     if ( obj != NULL && jvm != NULL && env != NULL) {
211         jclass cls = env->GetObjectClass(obj);
212         if ( cls != NULL ) {
213             jmethodID mid = env->GetMethodID(cls, name, sig);
214             if ( mid != NULL )
215             {
216                 return JNICaller<T>::callV(obj, mid, args);
217             }
218             else
219             {
220                 fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, obj);
221                 env->ExceptionDescribe();
222                 env->ExceptionClear();
223                 fprintf (stderr, "\n");
224             }
225
226             env->DeleteLocalRef(cls);
227         }
228         else {
229             fprintf(stderr, "%s: Could not find class for %p\n", __PRETTY_FUNCTION__, obj);
230         }
231     }
232
233     return 0;
234 }
235
236 template<typename T>
237 T callJNIMethod(jobject obj, const char* methodName, const char* methodSignature, ...)
238 {
239     va_list args;
240     va_start(args, methodSignature);
241     
242     T result= callJNIMethodV<T>(obj, methodName, methodSignature, args);
243     
244     va_end(args);
245     
246     return result;
247 }
248     
249 template<typename T>
250 T callJNIStaticMethod(jclass cls, const char* methodName, const char* methodSignature, ...)
251 {
252     JavaVM *jvm = getJavaVM();
253     JNIEnv *env = getJNIEnv();
254     va_list args;
255     
256     va_start(args, methodSignature);
257     
258     T result = 0;
259     
260     if (cls != NULL && jvm != NULL && env != NULL) {
261         jmethodID mid = env->GetStaticMethodID(cls, methodName, methodSignature);
262         if (mid != NULL) 
263             result = JNICaller<T>::callStaticV(cls, mid, args);
264         else {
265             fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, methodName, cls);
266             env->ExceptionDescribe();
267             env->ExceptionClear();
268             fprintf (stderr, "\n");
269         }
270     }
271     
272     va_end(args);
273     
274     return result;
275 }
276     
277 bool dispatchJNICall(const void *targetAppletView, jobject obj, bool isStatic, JNIType returnType, jmethodID methodID, jvalue *args, jvalue &result, const char *callingURL, JSValue *&exceptionDescription);
278
279 } // namespace Bindings
280
281 } // namespace KJS
282
283 #endif // _JNI_UTILITY_H_