Home | History | Annotate | Download | only in jni
      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