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