From d7d995948a4de13241cfd1e680b640d4969d4bab Mon Sep 17 00:00:00 2001 From: Andrei Vasiliu Date: Wed, 3 Feb 2016 18:24:03 +0200 Subject: jni: Implemented getObject* functions and added defensive checks Signed-off-by: Andrei Vasiliu --- java/BluetoothManager.java | 14 ++++- java/jni/BluetoothAdapter.cxx | 10 +-- java/jni/BluetoothDevice.cxx | 24 ++------ java/jni/BluetoothGattCharacteristic.cxx | 7 ++- java/jni/BluetoothGattDescriptor.cxx | 7 ++- java/jni/BluetoothManager.cxx | 101 +++++++++++++++++++++++++------ java/jni/BluetoothObject.cxx | 4 ++ java/jni/helper.cxx | 67 +++++++++++++++++--- java/jni/helper.hpp | 9 ++- 9 files changed, 189 insertions(+), 54 deletions(-) diff --git a/java/BluetoothManager.java b/java/BluetoothManager.java index 1e3d06d7..9de5a84c 100644 --- a/java/BluetoothManager.java +++ b/java/BluetoothManager.java @@ -41,9 +41,19 @@ public class BluetoothManager } public native BluetoothType getBluetoothType(); - public native BluetoothObject getObject(BluetoothType type, String name, + + public BluetoothObject getObject(BluetoothType type, String name, + String identifier, BluetoothObject parent) { + return getObject(type.ordinal(), name, identifier, parent); + } + private native BluetoothObject getObject(int type, String name, String identifier, BluetoothObject parent); - public native List getObjects(BluetoothType type, String name, + + public List getObjects(BluetoothType type, String name, + String identifier, BluetoothObject parent) { + return getObjects(type.ordinal(), name, identifier, parent); + } + private native List getObjects(int type, String name, String identifier, BluetoothObject parent); /** Returns a list of BluetoothAdapters available in the system diff --git a/java/jni/BluetoothAdapter.cxx b/java/jni/BluetoothAdapter.cxx index 82e01cc2..c8bf58bd 100644 --- a/java/jni/BluetoothAdapter.cxx +++ b/java/jni/BluetoothAdapter.cxx @@ -96,11 +96,7 @@ void Java_tinyb_BluetoothAdapter_setAlias(JNIEnv *env, jobject obj, jstring str) { BluetoothAdapter *obj_adapter = getInstance(env, obj); - jboolean is_copy = JNI_TRUE; - const char *str_chars = (char *)env->GetStringUTFChars(str, &is_copy); - const std::string string_to_write = std::string(str_chars); - - env->ReleaseStringUTFChars(str, str_chars); + const std::string string_to_write = from_jstring_to_string(env, str); obj_adapter->set_alias(string_to_write); } @@ -208,6 +204,10 @@ jobjectArray Java_tinyb_BluetoothAdapter_getUuids(JNIEnv *env, jobject obj) jclass string_class = search_class(env, "Ljava/lang/String;"); jobjectArray result = env->NewObjectArray(uuids_size, string_class, 0); + if (!result) + { + throw std::runtime_error("NewObjectArray cannot create instance\n"); + } for (unsigned int i = 0; i < uuids_size; ++i) { diff --git a/java/jni/BluetoothDevice.cxx b/java/jni/BluetoothDevice.cxx index 033e53cf..21ffac0b 100644 --- a/java/jni/BluetoothDevice.cxx +++ b/java/jni/BluetoothDevice.cxx @@ -63,26 +63,18 @@ jboolean Java_tinyb_BluetoothDevice_connectProfile(JNIEnv *env, jobject obj, jst { BluetoothDevice *obj_device = getInstance(env, obj); - jboolean is_copy = JNI_TRUE; - const char *str_chars = (char *)env->GetStringUTFChars(str, &is_copy); - const std::string string_to_write = std::string(str_chars); + const std::string string_to_write = from_jstring_to_string(env, str); - env->ReleaseStringUTFChars(str, str_chars); - - return obj_device->connect_profile(string_to_write); + return obj_device->connect_profile(string_to_write) ? JNI_TRUE : JNI_FALSE; } jboolean Java_tinyb_BluetoothDevice_disconnectProfile(JNIEnv *env, jobject obj, jstring str) { BluetoothDevice *obj_device = getInstance(env, obj); - jboolean is_copy = JNI_TRUE; - const char *str_chars = (char *)env->GetStringUTFChars(str, &is_copy); - const std::string string_to_write = std::string(str_chars); - - env->ReleaseStringUTFChars(str, str_chars); + const std::string string_to_write = from_jstring_to_string(env, str); - return obj_device->disconnect_profile(string_to_write); + return obj_device->disconnect_profile(string_to_write) ? JNI_TRUE : JNI_FALSE; } jboolean Java_tinyb_BluetoothDevice_pair(JNIEnv *env, jobject obj) @@ -137,11 +129,7 @@ void Java_tinyb_BluetoothDevice_setAlias(JNIEnv *env, jobject obj, jstring str) { BluetoothDevice *obj_device = getInstance(env, obj); - jboolean is_copy = JNI_TRUE; - const char *str_chars = (char *)env->GetStringUTFChars(str, &is_copy); - const std::string string_to_write = std::string(str_chars); - - env->ReleaseStringUTFChars(str, str_chars); + const std::string string_to_write = from_jstring_to_string(env, str); obj_device->set_alias(string_to_write); } @@ -262,7 +250,7 @@ jobject Java_tinyb_BluetoothDevice_getAdapter(JNIEnv *env, jobject obj) jmethodID b_adapter_ctor = search_method(env, b_adapter_class, "", "(J)V", false); jobject result = env->NewObject(b_adapter_class, b_adapter_ctor, (jlong)obj_adapter); - if (result == NULL) + if (!result) { throw std::runtime_error("cannot create instance of class\n"); } diff --git a/java/jni/BluetoothGattCharacteristic.cxx b/java/jni/BluetoothGattCharacteristic.cxx index f99f08fe..6d21e0e6 100644 --- a/java/jni/BluetoothGattCharacteristic.cxx +++ b/java/jni/BluetoothGattCharacteristic.cxx @@ -60,6 +60,11 @@ jbyteArray Java_tinyb_BluetoothGattCharacteristic_readValue(JNIEnv *env, jobject jboolean Java_tinyb_BluetoothGattCharacteristic_writeValue(JNIEnv *env, jobject obj, jbyteArray argValue) { + if (!argValue) + { + throw std::invalid_argument("byte array argument is null\n"); + } + BluetoothGattCharacteristic *obj_gatt_char = getInstance(env, obj); @@ -73,7 +78,7 @@ jboolean Java_tinyb_BluetoothGattCharacteristic_writeValue(JNIEnv *env, jobject array.push_back(native_array[i]); } - return obj_gatt_char->write_value(array); + return obj_gatt_char->write_value(array) ? JNI_TRUE : JNI_FALSE; } jboolean Java_tinyb_BluetoothGattCharacteristic_startNotify(JNIEnv *env, jobject obj) diff --git a/java/jni/BluetoothGattDescriptor.cxx b/java/jni/BluetoothGattDescriptor.cxx index 2fb4da25..091e0be9 100644 --- a/java/jni/BluetoothGattDescriptor.cxx +++ b/java/jni/BluetoothGattDescriptor.cxx @@ -58,6 +58,11 @@ jbyteArray Java_tinyb_BluetoothGattDescriptor_readValue(JNIEnv *env, jobject obj jboolean Java_tinyb_BluetoothGattDescriptor_writeValue(JNIEnv *env, jobject obj, jbyteArray argValue) { + if (!argValue) + { + throw std::invalid_argument("byte array argument is null\n"); + } + BluetoothGattDescriptor *obj_gatt_desc = getInstance(env, obj); jboolean is_copy = false; @@ -70,7 +75,7 @@ jboolean Java_tinyb_BluetoothGattDescriptor_writeValue(JNIEnv *env, jobject obj, array.push_back(native_array[i]); } - return obj_gatt_desc->write_value(array); + return obj_gatt_desc->write_value(array) ? JNI_TRUE : JNI_FALSE; } jstring Java_tinyb_BluetoothGattDescriptor_getUuid(JNIEnv *env, jobject obj) diff --git a/java/jni/BluetoothManager.cxx b/java/jni/BluetoothManager.cxx index 6788f2c1..917961c4 100644 --- a/java/jni/BluetoothManager.cxx +++ b/java/jni/BluetoothManager.cxx @@ -40,30 +40,91 @@ jobject Java_tinyb_BluetoothManager_getBluetoothType(JNIEnv *env, jobject obj) return get_bluetooth_type(env, "NONE"); } -jobject Java_tinyb_BluetoothManager_getObject(JNIEnv *env, jobject obj, jobject type, - jstring name, jstring identifier, jobject parent) +static void getObject_setter(JNIEnv *env, + jstring name, std::string **name_to_write, + jstring identifier, std::string **identifier_to_write, + jobject parent, BluetoothObject **b_parent) { - (void)env; - (void)obj; - (void)type; - (void)name; - (void)identifier; - (void)parent; - - return nullptr; + if (!parent) + { + *b_parent = nullptr; + } + else + { + *b_parent = getInstance(env, parent); + } + + if (!name) + { + *name_to_write = nullptr; + } + else + { + **name_to_write = from_jstring_to_string(env, name); + } + + if (!identifier) + { + *identifier_to_write = nullptr; + } + else + { + **identifier_to_write = from_jstring_to_string(env, identifier); + } } -jobject Java_tinyb_BluetoothManager_getObjects(JNIEnv *env, jobject obj, jobject type, +jobject Java_tinyb_BluetoothManager_getObject(JNIEnv *env, jobject obj, jint type, jstring name, jstring identifier, jobject parent) { - (void)env; - (void)obj; - (void)type; - (void)name; - (void)identifier; - (void)parent; + BluetoothManager *manager = getInstance(env, obj); + BluetoothObject *b_parent; + BluetoothType b_type; + std::string *name_to_write; + std::string *identifier_to_write; + + getObject_setter(env, + name, &name_to_write, + identifier, &identifier_to_write, + parent, &b_parent); + + b_type = from_int_to_btype((int)type); + std::unique_ptr b_object = manager->get_object(b_type, name_to_write, + identifier_to_write, + b_parent); + + BluetoothObject *b_object_naked = b_object.release(); + if (!b_object_naked) + { + return nullptr; + } + jclass clazz = search_class(env, *b_object_naked); + jmethodID clazz_ctor = search_method(env, clazz, "", "(J)V", false); + + jobject result = env->NewObject(clazz, clazz_ctor, (long)b_object_naked); + return result; +} - return nullptr; +jobject Java_tinyb_BluetoothManager_getObjects(JNIEnv *env, jobject obj, jint type, + jstring name, jstring identifier, jobject parent) +{ + BluetoothManager *manager = getInstance(env, obj); + BluetoothObject *b_parent; + BluetoothType b_type; + std::string *name_to_write; + std::string *identifier_to_write; + + getObject_setter(env, + name, &name_to_write, + identifier, &identifier_to_write, + parent, &b_parent); + + b_type = from_int_to_btype((int)type); + std::vector> array = manager->get_objects(b_type, + name_to_write, + identifier_to_write, + b_parent); + jobject result = convert_vector_to_jobject(env, array, "(J)V"); + return result; } jobject Java_tinyb_BluetoothManager_getAdapters(JNIEnv *env, jobject obj) @@ -99,6 +160,10 @@ jobject Java_tinyb_BluetoothManager_getServices(JNIEnv *env, jobject obj) jboolean Java_tinyb_BluetoothManager_setDefaultAdapter(JNIEnv *env, jobject obj, jobject adapter) { + if (!adapter) + { + throw std::invalid_argument("adapter argument is null\n"); + } BluetoothManager *manager = getInstance(env, obj); BluetoothAdapter *b_adapter = getInstance(env, adapter); diff --git a/java/jni/BluetoothObject.cxx b/java/jni/BluetoothObject.cxx index 03029cca..9c2a8f3c 100644 --- a/java/jni/BluetoothObject.cxx +++ b/java/jni/BluetoothObject.cxx @@ -51,6 +51,10 @@ void Java_tinyb_BluetoothObject_delete(JNIEnv *env, jobject obj) jboolean Java_tinyb_BluetoothObject_operatorEqual(JNIEnv *env, jobject obj, jobject other) { + if (!other) + { + return JNI_FALSE; + } BluetoothObject *obj_b = getInstance(env, obj); BluetoothObject *obj_other = getInstance(env, other); diff --git a/java/jni/helper.cxx b/java/jni/helper.cxx index 2fd70fab..c701b931 100644 --- a/java/jni/helper.cxx +++ b/java/jni/helper.cxx @@ -44,7 +44,7 @@ jclass search_class(JNIEnv *env, tinyb::BluetoothObject &object) jclass search_class(JNIEnv *env, const char *clazz_name) { jclass clazz = env->FindClass(clazz_name); - if (clazz == NULL) + if (!clazz) { std::string error = "no class found: "; error += clazz_name; throw std::runtime_error(error); @@ -56,7 +56,7 @@ jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name, const char *prototype, bool is_static) { jmethodID method; - if(is_static) + if (is_static) { method = env->GetStaticMethodID(clazz, method_name, prototype); } @@ -65,7 +65,7 @@ jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name, method = env->GetMethodID(clazz, method_name, prototype); } - if(method == NULL) + if (!method) { throw std::runtime_error("no method found\n"); } @@ -77,7 +77,7 @@ jfieldID search_field(JNIEnv *env, jclass clazz, const char *field_name, const char *type, bool is_static) { jfieldID field; - if(is_static) + if (is_static) { field = env->GetStaticFieldID(clazz, field_name, type); } @@ -86,7 +86,7 @@ jfieldID search_field(JNIEnv *env, jclass clazz, const char *field_name, field = env->GetFieldID(clazz, field_name, type); } - if(field == NULL) + if (!field) { throw std::runtime_error("no method found\n"); } @@ -117,6 +117,60 @@ bool from_jboolean_to_bool(jboolean val) return result; } +std::string from_jstring_to_string(JNIEnv *env, jstring str) +{ + jboolean is_copy = JNI_TRUE; + const char *str_chars = (char *)env->GetStringUTFChars(str, &is_copy); + if (!str_chars) + { + throw std::runtime_error("GetStringUTFChars returned NULL\n"); + } + const std::string string_to_write = std::string(str_chars); + + env->ReleaseStringUTFChars(str, str_chars); + + return string_to_write; +} + +tinyb::BluetoothType from_int_to_btype(int type) +{ + tinyb::BluetoothType result = tinyb::BluetoothType::NONE; + + switch (type) + { + case 0: + result = tinyb::BluetoothType::NONE; + break; + + case 1: + result = tinyb::BluetoothType::ADAPTER; + break; + + case 2: + result = tinyb::BluetoothType::DEVICE; + break; + + case 3: + result = tinyb::BluetoothType::GATT_SERVICE; + break; + + case 4: + result = tinyb::BluetoothType::GATT_CHARACTERISTIC; + break; + + case 5: + result = tinyb::BluetoothType::GATT_CHARACTERISTIC; + break; + + default: + result = tinyb::BluetoothType::NONE; + break; + } + + return result; +} + + jobject get_bluetooth_type(JNIEnv *env, const char *field_name) { jclass b_type_enum = search_class(env, JAVA_PACKAGE "/BluetoothType"); @@ -127,14 +181,13 @@ jobject get_bluetooth_type(JNIEnv *env, const char *field_name) return result; } - jobject get_new_arraylist(JNIEnv *env, unsigned int size, jmethodID *add) { jclass arraylist_class = search_class(env, "Ljava/util/ArrayList;"); jmethodID arraylist_ctor = search_method(env, arraylist_class, "", "(I)V", false); jobject result = env->NewObject(arraylist_class, arraylist_ctor, size); - if (result == NULL) + if (!result) { throw std::runtime_error("cannot create instance of class\n"); } diff --git a/java/jni/helper.hpp b/java/jni/helper.hpp index 3a7f1664..84d49c47 100644 --- a/java/jni/helper.hpp +++ b/java/jni/helper.hpp @@ -26,6 +26,7 @@ #include #include "tinyb/BluetoothObject.hpp" +#include "tinyb/BluetoothObject.hpp" jfieldID getInstanceField(JNIEnv *env, jobject obj); @@ -36,6 +37,8 @@ jmethodID search_method(JNIEnv *env, jclass clazz, const char *method_name, jfieldID search_field(JNIEnv *env, jclass clazz, const char *field_name, const char *type, bool is_static); bool from_jboolean_to_bool(jboolean val); +std::string from_jstring_to_string(JNIEnv *env, jstring str); +tinyb::BluetoothType from_int_to_btype(int type); jobject get_bluetooth_type(JNIEnv *env, const char *field_name); jobject get_new_arraylist(JNIEnv *env, unsigned int size, jmethodID *add); @@ -63,7 +66,7 @@ jobject generic_clone(JNIEnv *env, jobject obj) jmethodID generic_ctor = search_method(env, generic_class, "", "(J)V", false); jobject result = env->NewObject(generic_class, generic_ctor, (jlong)copy_generic); - if (result == NULL) + if (!result) { throw std::runtime_error("cannot create instance of class\n"); } @@ -81,7 +84,9 @@ jobject convert_vector_to_jobject(JNIEnv *env, std::vector>& jobject result = get_new_arraylist(env, array_size, &arraylist_add); if (array_size == 0) + { return result; + } jclass clazz = search_class(env, T::java_class().c_str()); jmethodID clazz_ctor = search_method(env, clazz, "", ctor_prototype, false); @@ -90,7 +95,7 @@ jobject convert_vector_to_jobject(JNIEnv *env, std::vector>& { T *elem = array.at(i).release(); jobject object = env->NewObject(clazz, clazz_ctor, (long)elem); - if (object == NULL) + if (!object) { throw std::runtime_error("cannot create instance of class\n"); } -- cgit v1.2.3