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 39 namespace JSC { 40 41 namespace Bindings { 42 43 const char* getCharactersFromJString(jstring); 44 void releaseCharactersForJString(jstring, const char*); 45 46 const char* getCharactersFromJStringInEnv(JNIEnv*, jstring); 47 void releaseCharactersForJStringInEnv(JNIEnv*, jstring, const char*); 48 const jchar* getUCharactersFromJStringInEnv(JNIEnv*, jstring); 49 void releaseUCharactersForJStringInEnv(JNIEnv*, jstring, const jchar*); 50 51 JavaType javaTypeFromClassName(const char* name); 52 JavaType javaTypeFromPrimitiveType(char type); 53 const char* signatureFromJavaType(JavaType); 54 55 jvalue getJNIField(jobject, JavaType, const char* name, const char* signature); 56 jvalue callJNIMethod(jobject, JavaType returnType, const char* name, const char* signature, jvalue* args); 57 58 jmethodID getMethodID(jobject, const char* name, const char* sig); 59 JNIEnv* getJNIEnv(); 60 JavaVM* getJavaVM(); 61 void setJavaVM(JavaVM*); 62 63 64 template <typename T> struct JNICaller; 65 66 template<> 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 77 template<> 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 88 template<> 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 103 template<> 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 114 template<> 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 125 template<> 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 136 template<> 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 147 template<> 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 158 template<> 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 169 template<> 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 180 template<typename T> T callJNIMethodIDA(jobject obj, jmethodID mid, jvalue *args) 181 { 182 return JNICaller<T>::callA(obj, mid, args); 183 } 184 185 template<typename T> 186 static 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 213 template<typename T> 214 T 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 226 template<typename T> 227 T 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