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