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(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