00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00034 #ifndef JAVA_VOID_METHOD_CALLER
00035 #define JAVA_VOID_METHOD_CALLER
00036
00037
00038 #if _MSC_VER >= 1400
00039 #define _SCL_SECURE_NO_DEPRECATE 1
00040 #endif
00041
00042 #include <jni.h>
00043 #include <vector>
00044 #include <algorithm>
00045 #include "String.h"
00046 #include "TypeList.h"
00047 #include "CompileTimeCheck.h"
00048
00049 namespace lm
00050 {
00067 class JavaVoidMethodCaller
00068 {
00069 public:
00070
00071
00072
00073
00074
00075
00084 JavaVoidMethodCaller(JNIEnv *env, jclass java_class, jobject java_object, bool swallow_java_exceptions = true) :
00085 jni_env(env),
00086 target_class(java_class),
00087 object(java_object),
00088 swallow_exceptions(swallow_java_exceptions)
00089 {
00090 }
00091
00094 ~JavaVoidMethodCaller(void)
00095 {
00096 }
00097
00107 bool Call(const char *method_name, const char *method_signature)
00108 {
00109 jmethodID method_id = jni_env->GetMethodID(target_class, method_name, method_signature);
00110
00111 if (!method_id)
00112 {
00113 return false;
00114 }
00115
00116 jni_env->CallVoidMethod(object, method_id);
00117
00118 if (jni_env->ExceptionCheck())
00119 {
00120 if (swallow_exceptions)
00121 {
00122 jni_env->ExceptionClear();
00123 }
00124 return false;
00125 }
00126
00127 return true;
00128 }
00129
00142 template< typename T1 >
00143 bool Call(const char *method_name, const char *method_signature, T1 param_1)
00144 {
00145 const int type_index = ::tl::IndexOf< JavaTypes, T1 >::value;
00146
00147 COMPILE_TIME_CHECK(type_index >= 0, Parameter_type_is_not_supported);
00148
00149 jmethodID method_id = jni_env->GetMethodID(target_class, method_name, method_signature);
00150
00151 if (!method_id)
00152 {
00153 return false;
00154 }
00155
00156 jni_env->CallVoidMethod(object, method_id, param_1);
00157
00158 if (jni_env->ExceptionCheck())
00159 {
00160 if (swallow_exceptions)
00161 {
00162 jni_env->ExceptionClear();
00163 }
00164 return false;
00165 }
00166
00167 return true;
00168 }
00169
00185 template< typename T1, typename T2 >
00186 bool Call(const char *method_name, const char *method_signature, T1 param_1, T2 param_2)
00187 {
00188 const int type_index_1 = ::tl::IndexOf< JavaTypes, T1 >::value;
00189 const int type_index_2 = ::tl::IndexOf< JavaTypes, T2 >::value;
00190
00191 COMPILE_TIME_CHECK(type_index_1 >= 0, First_parameters_type_is_not_supported);
00192 COMPILE_TIME_CHECK(type_index_2 >= 0, Second_parameters_type_is_not_supported);
00193
00194 jmethodID method_id = jni_env->GetMethodID(target_class, method_name, method_signature);
00195
00196 if (!method_id)
00197 {
00198 return false;
00199 }
00200
00201 jni_env->CallVoidMethod(object, method_id, param_1, param_2);
00202
00203 if (jni_env->ExceptionCheck())
00204 {
00205 if (swallow_exceptions)
00206 {
00207 jni_env->ExceptionClear();
00208 }
00209 return false;
00210 }
00211
00212 return true;
00213 }
00214
00227 template< typename T1 >
00228 bool Call(const char *method_name,
00229 const char *method_signature,
00230 const std::vector< T1 > ¶m_1)
00231 {
00232 const int type_index = ::tl::IndexOf< JavaTypes, T1 >::value;
00233
00234
00235 COMPILE_TIME_CHECK(type_index >= 1, Parameter_type_is_not_supported);
00236
00237 jmethodID method_id = jni_env->GetMethodID(target_class, method_name, method_signature);
00238
00239 if (!method_id)
00240 {
00241 return false;
00242 }
00243
00244 typedef typename ::tl::Get< ArrayMethodAdapters, type_index >::Result AdapterType;
00245
00246 bool result = true;
00247 AdapterType adapter(jni_env);
00248
00249 typename AdapterType::JavaType java_array = adapter.NewArray(static_cast< jsize >(param_1.size()));
00250
00251
00252 T1 *array_data = new T1[param_1.size()];
00253
00254 std::copy(param_1.begin(), param_1.end(), array_data);
00255
00256 adapter.SetArrayRegion(java_array, 0, static_cast< jsize >(param_1.size()), array_data);
00257
00258 jni_env->CallVoidMethod(object, method_id, java_array);
00259
00260 if (jni_env->ExceptionCheck())
00261 {
00262 if (swallow_exceptions)
00263 {
00264 jni_env->ExceptionClear();
00265 }
00266 result = false;
00267 }
00268
00269 adapter.DeleteArray(java_array, array_data);
00270
00271
00272 return result;
00273 }
00274
00290 template< typename T1, typename T2 >
00291 bool Call(const char *method_name,
00292 const char *method_signature,
00293 const std::vector< T1 > ¶m_1,
00294 const std::vector< T2 > ¶m_2)
00295 {
00296 const int type_index_1 = ::tl::IndexOf< JavaTypes, T1 >::value;
00297 const int type_index_2 = ::tl::IndexOf< JavaTypes, T2 >::value;
00298
00299 COMPILE_TIME_CHECK(type_index_1 >= 1, Parameter_type_is_not_supported);
00300 COMPILE_TIME_CHECK(type_index_2 >= 1, Parameter_type_is_not_supported);
00301
00302 jmethodID method_id = jni_env->GetMethodID(target_class, method_name, method_signature);
00303
00304 if (!method_id)
00305 {
00306 return false;
00307 }
00308
00309 typedef typename ::tl::Get< ArrayMethodAdapters, type_index_1 >::Result AdapterType_1;
00310 typedef typename ::tl::Get< ArrayMethodAdapters, type_index_2 >::Result AdapterType_2;
00311
00312 bool result = true;
00313
00314 AdapterType_1 adapter_1(jni_env);
00315 AdapterType_2 adapter_2(jni_env);
00316
00317 typename AdapterType_1::JavaType java_array_1 = adapter_1.NewArray(static_cast< jsize >(param_1.size()));
00318 typename AdapterType_2::JavaType java_array_2 = adapter_2.NewArray(static_cast< jsize >(param_2.size()));
00319
00320
00321 T1 *array_data_1 = new T1[param_1.size()];
00322
00323 std::copy(param_1.begin(), param_1.end(), array_data_1);
00324 adapter_1.SetArrayRegion(java_array_1, 0, static_cast< jsize >(param_1.size()), array_data_1);
00325
00326
00327 T2 *array_data_2 = new T2[param_1.size()];
00328
00329 std::copy(param_2.begin(), param_2.end(), array_data_2);
00330 adapter_2.SetArrayRegion(java_array_2, 0, static_cast< jsize >(param_2.size()), array_data_2);
00331
00332 jni_env->CallVoidMethod(object, method_id, java_array_1, java_array_2);
00333
00334 if (jni_env->ExceptionCheck())
00335 {
00336 if (swallow_exceptions)
00337 {
00338 jni_env->ExceptionClear();
00339 }
00340 result = false;
00341 }
00342
00343 adapter_1.DeleteArray(java_array_1, array_data_1);
00344
00345
00346 adapter_2.DeleteArray(java_array_2, array_data_2);
00347
00348
00349 return result;
00350 }
00351
00357 bool GetSwallowExceptions(void)
00358 {
00359 return swallow_exceptions;
00360 }
00361
00369 bool SetSwallowException(bool se)
00370 {
00371 bool ose = swallow_exceptions;
00372
00373 swallow_exceptions = se;
00374
00375 return ose;
00376 }
00377
00378 private:
00380 JNIEnv *jni_env;
00381
00383 jclass target_class;
00384
00386 jobject object;
00387
00389 bool swallow_exceptions;
00390
00395 typedef CREATE_TYPE_LIST_09(void,
00396 jboolean,
00397 jbyte,
00398 jchar,
00399 jshort,
00400 jint,
00401 jlong,
00402 jfloat,
00403 jdouble) JavaTypes;
00404
00409 typedef CREATE_TYPE_LIST_09(void,
00410 jbooleanArray,
00411 jbyteArray,
00412 jcharArray,
00413 jshortArray,
00414 jintArray,
00415 jlongArray,
00416 jfloatArray,
00417 jdoubleArray) JavaArrayTypes;
00418
00419
00422 #define CREATE_ARRAY_METHOD_ADAPTER_CLASS(NativeType_, middle_name) \
00423 class ArrayMethodAdapter_##middle_name \
00424 { \
00425 public: \
00426 typedef NativeType_ NativeType; \
00427 typedef ::tl::Get< JavaArrayTypes, ::tl::IndexOf< JavaTypes, NativeType >::value >::Result JavaType; \
00428 ArrayMethodAdapter_##middle_name(JNIEnv *env) : \
00429 jni_env(env) \
00430 { \
00431 } \
00432 ~ArrayMethodAdapter_##middle_name(void) \
00433 { \
00434 } \
00435 JavaType NewArray(jsize size) \
00436 { \
00437 return jni_env->New##middle_name##Array(size); \
00438 } \
00439 void DeleteArray(JavaType java_array, NativeType *elements) \
00440 { \
00441 jni_env->Release##middle_name##ArrayElements(java_array, elements, 0); \
00442 } \
00443 void GetArrayRegion(JavaType java_array, jsize start, jsize len, NativeType *buffer) \
00444 { \
00445 jni_env->Get##middle_name##ArrayRegion(java_array, start, len, buffer); \
00446 } \
00447 void SetArrayRegion(JavaType java_array, jsize start, jsize len, NativeType *buffer) \
00448 { \
00449 jni_env->Set##middle_name##ArrayRegion(java_array, start, len, buffer); \
00450 } \
00451 NativeType *GetArrayElements(JavaType java_array) \
00452 { \
00453 return jni_env->Get##middle_name##ArrayElements(java_array, NULL); \
00454 } \
00455 size_t GetArrayLength(jarray java_array) \
00456 { \
00457 return jni_env->GetArrayLength(java_array); \
00458 } \
00459 private: \
00460 JNIEnv *jni_env; \
00461 };
00462
00467 class ArrayMethodAdapter_String
00468 {
00469 public:
00471 typedef jobjectArray JavaType;
00472
00474 typedef jstring NativeType;
00475
00480 ArrayMethodAdapter_String(JNIEnv *env) :
00481 jni_env(env)
00482 {
00483
00484 string_class = jni_env->FindClass("java/lang/String");
00485 }
00486
00489 ~ArrayMethodAdapter_String(void)
00490 {
00491 }
00492
00499 jobjectArray NewArray(jsize size)
00500 {
00501 return jni_env->NewObjectArray(size, string_class, NULL);
00502 }
00503
00510 void SetElement(jobjectArray java_array, size_t index, const String &value)
00511 {
00512 #ifdef WIN32
00513
00514 jstring new_value = jni_env->NewString((jchar *) value.c_str(), static_cast< jsize >(value.length()));
00515 #else
00516
00517 jstring new_value = jni_env->NewStringUTF(value.c_str());
00518 #endif
00519
00520 jni_env->SetObjectArrayElement(java_array, static_cast< jsize >(index), new_value);
00521 }
00522
00529 size_t GetArrayLength(jarray java_array)
00530 {
00531 return jni_env->GetArrayLength(java_array);
00532 }
00533
00534 private:
00535 JNIEnv *jni_env;
00536 jclass string_class;
00537 };
00538
00541 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jboolean, Boolean)
00542
00543
00545 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jbyte, Byte)
00546
00549 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jchar, Char)
00550
00553 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jshort, Short)
00554
00557 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jint, Int)
00558
00561 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jlong, Long)
00562
00565 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jfloat, Float)
00566
00569 CREATE_ARRAY_METHOD_ADAPTER_CLASS(jdouble, Double)
00570
00576 typedef CREATE_TYPE_LIST_09(void,
00577 ArrayMethodAdapter_Boolean,
00578 ArrayMethodAdapter_Byte,
00579 ArrayMethodAdapter_Char,
00580 ArrayMethodAdapter_Short,
00581 ArrayMethodAdapter_Int,
00582 ArrayMethodAdapter_Long,
00583 ArrayMethodAdapter_Float,
00584 ArrayMethodAdapter_Double) ArrayMethodAdapters;
00585 };
00586
00601 template< >
00602 bool JavaVoidMethodCaller::Call< String >(const char *method_name, const char *method_signature, String param_1)
00603 {
00604 jmethodID method_id = jni_env->GetMethodID(target_class, method_name, method_signature);
00605
00606 if (!method_id)
00607 {
00608 return false;
00609 }
00610
00611 #ifdef WIN32
00612 jstring str_param = jni_env->NewString((jchar *) param_1.c_str(), static_cast< jsize >(param_1.length()));
00613 #else
00614 jstring str_param = jni_env->NewStringUTF(param_1.c_str());
00615 #endif
00616
00617 jni_env->CallVoidMethod(object, method_id, str_param);
00618
00619 if (jni_env->ExceptionCheck())
00620 {
00621 if (swallow_exceptions)
00622 {
00623 jni_env->ExceptionClear();
00624 }
00625 return false;
00626 }
00627
00628 return true;
00629 }
00630
00646 template< >
00647 bool JavaVoidMethodCaller::Call< String >(const char *method_name,
00648 const char *method_signature,
00649 const std::vector< String > ¶m_1)
00650 {
00651 jmethodID method_id = jni_env->GetMethodID(target_class, method_name, method_signature);
00652
00653 if (!method_id)
00654 {
00655 return false;
00656 }
00657
00658 ArrayMethodAdapter_String adapter(jni_env);
00659
00660
00661
00662
00663
00664 ArrayMethodAdapter_String::JavaType java_array = adapter.NewArray(static_cast< jsize >(param_1.size()));
00665
00666 for (size_t i = 0; i < param_1.size(); ++i)
00667 {
00668 adapter.SetElement(java_array, i, param_1[i]);
00669 }
00670
00671 jni_env->CallVoidMethod(object, method_id, java_array);
00672
00673 if (jni_env->ExceptionCheck())
00674 {
00675 if (swallow_exceptions)
00676 {
00677 jni_env->ExceptionClear();
00678 }
00679 return false;
00680 }
00681
00682 return true;
00683 }
00684
00685 }
00686
00687 #endif