From: koushik.girijala Date: Fri, 30 Dec 2016 10:49:36 +0000 (+0530) Subject: Add ByteString support for RCSResourceAttributes JAVA and JNI. X-Git-Tag: 1.3.0~921 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=eab5bd4d1e7dad610abb51bf4d6dee3becb9ab63;p=platform%2Fupstream%2Fiotivity.git Add ByteString support for RCSResourceAttributes JAVA and JNI. ByteString(Binary) was added in the Value of OCRepresentation. But, RE layer does not covered ByteString type. In this patch, ByteString type is added in RE layer for synchronization with OC. patch 2 : Fix memory leak Change-Id: I5e52fea9b7d4b5b09384fa24446f550d93b89395 Signed-off-by: koushik.girijala Reviewed-on: https://gerrit.iotivity.org/gerrit/16029 Reviewed-by: Abhishek Pandey Reviewed-by: JungYong KIM Tested-by: jenkins-iotivity Reviewed-by: Uze Choi --- diff --git a/service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsByteString.java b/service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsByteString.java new file mode 100644 index 0000000..e02ad74 --- /dev/null +++ b/service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsByteString.java @@ -0,0 +1,23 @@ +package org.iotivity.service; + +/** + * This Class represents byte string value for RcsResourceAttributes. + */ +public class RcsByteString { + + private byte[] mData; + private long mSize; + + public RcsByteString(byte[] data, long size) { + this.mData = data; + this.mSize = size; + } + + public byte[] getValue() { + return this.mData; + } + + public long getSize() { + return this.mSize; + } +} \ No newline at end of file diff --git a/service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsValue.java b/service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsValue.java index e1fd331..a9edc82 100644 --- a/service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsValue.java +++ b/service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsValue.java @@ -47,7 +47,7 @@ public final class RcsValue { * @see Type */ public static enum TypeId { - NULL, BOOLEAN, INTEGER, DOUBLE, STRING, ATTRIBUTES, ARRAY; + NULL, BOOLEAN, INTEGER, DOUBLE, STRING, BYTESTRING, ATTRIBUTES, ARRAY; } /** @@ -189,12 +189,14 @@ public final class RcsValue { types.put(Integer.class, new Type(TypeId.INTEGER)); types.put(Double.class, new Type(TypeId.DOUBLE)); types.put(String.class, new Type(TypeId.STRING)); + types.put(RcsByteString.class, new Type(TypeId.BYTESTRING)); types.put(RcsResourceAttributes.class, new Type(TypeId.ATTRIBUTES)); types.put(boolean[].class, new ArrayType(TypeId.BOOLEAN, 1)); types.put(int[].class, new ArrayType(TypeId.INTEGER, 1)); types.put(double[].class, new ArrayType(TypeId.DOUBLE, 1)); types.put(String[].class, new ArrayType(TypeId.STRING, 1)); + types.put(RcsByteString[].class, new ArrayType(TypeId.BYTESTRING, 1)); types.put(RcsResourceAttributes[].class, new ArrayType(TypeId.ATTRIBUTES, 1)); @@ -202,6 +204,7 @@ public final class RcsValue { types.put(int[][].class, new ArrayType(TypeId.INTEGER, 2)); types.put(double[][].class, new ArrayType(TypeId.DOUBLE, 2)); types.put(String[][].class, new ArrayType(TypeId.STRING, 2)); + types.put(RcsByteString[][].class, new ArrayType(TypeId.BYTESTRING, 2)); types.put(RcsResourceAttributes[][].class, new ArrayType(TypeId.ATTRIBUTES, 2)); @@ -209,6 +212,7 @@ public final class RcsValue { types.put(int[][][].class, new ArrayType(TypeId.INTEGER, 3)); types.put(double[][][].class, new ArrayType(TypeId.DOUBLE, 3)); types.put(String[][][].class, new ArrayType(TypeId.STRING, 3)); + types.put(RcsByteString[][][].class, new ArrayType(TypeId.BYTESTRING, 3)); types.put(RcsResourceAttributes[][][].class, new ArrayType(TypeId.ATTRIBUTES, 3)); @@ -469,8 +473,35 @@ public final class RcsValue { /** * Constructs a new value that holds a RcsResourceAttributes array. * - * @param value - * a RcsResourceAttributes array + * @param value a RcsByteString array + * @throws NullPointerException if value is null. + */ + public RcsValue(RcsByteString[] value) { + this((Object) value); + } + + /** + * Constructs a new value that holds a two-dimensional RcsByteString array. + * + * @param value a two-dimensional RcsByteString array + * @throws NullPointerException if value is null. + */ + public RcsValue(RcsByteString[][] value) { + this((Object) value); + } + + /** + * Constructs a new value that holds a three-dimensional RcsByteString array. + * + * @param value a three-dimensional RcsByteString array + * @throws NullPointerException if value is null. + */ + public RcsValue(RcsByteString[][][] value) { + this((Object) value); + } + + /** + * Constructs a new value that holds a RcsResourceAttributes array. * * @throws NullPointerException * if value is null. @@ -822,6 +853,36 @@ public final class RcsValue { } /** + * Returns the value as an RcsByteString array, null if the value is not the + * desired type. + * + * @return an RcsByteString array + */ + public RcsByteString[] asByteStringArray() { + return getOrNull(); + } + + /** + * Returns the value as a two-dimensional RcsByteString array, null if the + * value is not the desired type. + * + * @return a two-dimensional RcsByteString array + */ + public RcsByteString[][] asByteString2DArray() { + return getOrNull(); + } + + /** + * Returns the value as a three-dimensional RcsByteString array, null if the + * value is not the desired type. + * + * @return a three-dimensional RcsByteString array + */ + public RcsByteString[][][] asByteString3DArray() { + return getOrNull(); + } + + /** * Returns the value as an attributes array, null if the value is not the * desired type. * diff --git a/service/resource-encapsulation/android/service/src/main/jni/JniRcsValue.cpp b/service/resource-encapsulation/android/service/src/main/jni/JniRcsValue.cpp index 46ea958..cb1639f 100644 --- a/service/resource-encapsulation/android/service/src/main/jni/JniRcsValue.cpp +++ b/service/resource-encapsulation/android/service/src/main/jni/JniRcsValue.cpp @@ -56,6 +56,7 @@ namespace jobject g_obj_TypeId_Integer; jobject g_obj_TypeId_Double; jobject g_obj_TypeId_String; + jobject g_obj_TypeId_ByteString; jobject g_obj_TypeId_Attributes; jobject g_obj_TypeId_Array; @@ -189,6 +190,68 @@ namespace static constexpr char className[] = "L" CLS_NAME_STRING ";"; }; constexpr char JniTypeTrait< std::string >::className[]; + template< typename ENV > + inline RCSByteString invoke_ByteString_byteStringValue(JNIEnvWrapper *env, jobject byteStringObj) + { + EXPECT_RET(byteStringObj, "byteStringObj is null!", { }); + + jclass g_cls_RCSByteString = env->FindClassAsGlobalRef(CLS_NAME_RESOURCEBYTESTRING); + + static jfieldID field_data = env->GetFieldID(g_cls_RCSByteString, "mData", "[B"); + static jfieldID field_length = env->GetFieldID(g_cls_RCSByteString, "mSize", "J"); + + jbyteArray jDataInfo = (jbyteArray)env->GetObjectField(byteStringObj, field_data); + jlong jDataLength = env->GetLongField(byteStringObj, field_length); + + jbyte *byteStringData = env->GetByteArrayElements(jDataInfo, NULL); + + RCSByteString byteString((uint8_t *)byteStringData, (size_t)jDataLength); + + env->ReleaseByteArrayElements(jDataInfo, (jbyte*) byteStringData, JNI_ABORT); + env->DeleteGlobalRef(g_cls_RCSByteString); + + return byteString; + } + + template< typename ENV > + inline jobject newRCSByteStringObject(ENV* env, const RCSByteString& value) + { + jsize jSize = (jsize)value.size(); + + jbyteArray jData = env->NewByteArray(jSize); + + std::vector byteString = value.getByteString(); + + env->SetByteArrayRegion(jData, 0, jSize, (const jbyte*)&byteString[0]); + + jclass g_cls_RCSByteString = env->FindClassAsGlobalRef(CLS_NAME_RESOURCEBYTESTRING); + jmethodID g_ctor_RCSByteString = env->GetConstructorID(g_cls_RCSByteString, "([BJ)V"); + + EXPECT_RET(g_ctor_RCSByteString, "g_ctor_RCSByteString is null!", { }); + + jobject jObj = (jobject)env->NewObject(g_cls_RCSByteString, g_ctor_RCSByteString, jData, + (jlong)jSize); + + EXPECT_RET(jObj, "jObj is null!", { }); + + return jObj; + } + + template<> + struct JniTypeTrait< RCSByteString >: public ObjectType + { + static decltype(&invoke_ByteString_byteStringValue) converter; + + static decltype(&newRCSByteStringObject) newObjectFunc; + + static constexpr char className[] = CLS_NAME_RESOURCEBYTESTRING; + }; + constexpr char JniTypeTrait< RCSByteString >::className[]; + decltype(&invoke_ByteString_byteStringValue) JniTypeTrait< RCSByteString >::converter = + &invoke_ByteString_byteStringValue; + + decltype(&newRCSByteStringObject) JniTypeTrait< RCSByteString >::newObjectFunc = + &newRCSByteStringObject; template<> struct JniTypeTrait< RCSResourceAttributes >: public ObjectType @@ -316,6 +379,9 @@ namespace case RCSResourceAttributes::TypeId::STRING: return toNativeValue< std::string >(env, val, depth); + case RCSResourceAttributes::TypeId::BYTESTRING: + return toNativeValue< RCSByteString >(env, val, depth); + case RCSResourceAttributes::TypeId::ATTRIBUTES: return toNativeValue< RCSResourceAttributes >(env, val, depth); } @@ -414,6 +480,11 @@ namespace value.get< typename SeqType< DEPTH, std::string >::type >(), Int2Type< DEPTH >{ }); + case RCSResourceAttributes::TypeId::BYTESTRING: + return createJavaObject(env, + value.get< typename SeqType< DEPTH, RCSByteString >::type >(), + Int2Type< DEPTH > { }); + case RCSResourceAttributes::TypeId::ATTRIBUTES: return createJavaObject(env, value.get< typename SeqType< DEPTH, RCSResourceAttributes >::type >(), @@ -452,6 +523,7 @@ namespace if (env->IsSameObject(g_obj_TypeId_Integer, typeIdObj)) return TypeId::INT; if (env->IsSameObject(g_obj_TypeId_Double, typeIdObj)) return TypeId::DOUBLE; if (env->IsSameObject(g_obj_TypeId_String, typeIdObj)) return TypeId::STRING; + if (env->IsSameObject(g_obj_TypeId_ByteString, typeIdObj)) return TypeId::BYTESTRING; if (env->IsSameObject(g_obj_TypeId_Attributes, typeIdObj)) return TypeId::ATTRIBUTES; if (env->IsSameObject(g_obj_TypeId_Array, typeIdObj)) return TypeId::VECTOR; @@ -494,6 +566,7 @@ void initRCSValue(JNIEnvWrapper* env) g_obj_TypeId_Integer = getTypeIdObj(env, "INTEGER"); g_obj_TypeId_Double = getTypeIdObj(env, "DOUBLE"); g_obj_TypeId_String = getTypeIdObj(env, "STRING"); + g_obj_TypeId_ByteString = getTypeIdObj(env, "BYTESTRING"); g_obj_TypeId_Attributes = getTypeIdObj(env, "ATTRIBUTES"); g_obj_TypeId_Array = getTypeIdObj(env, "ARRAY"); } @@ -509,6 +582,7 @@ void clearRCSValue(JNIEnvWrapper* env) env->DeleteGlobalRef(g_obj_TypeId_Integer); env->DeleteGlobalRef(g_obj_TypeId_Double); env->DeleteGlobalRef(g_obj_TypeId_String); + env->DeleteGlobalRef(g_obj_TypeId_ByteString); env->DeleteGlobalRef(g_obj_TypeId_Attributes); env->DeleteGlobalRef(g_obj_TypeId_Array); } diff --git a/service/resource-encapsulation/android/service/src/main/jni/util/JNIEnvWrapper.h b/service/resource-encapsulation/android/service/src/main/jni/util/JNIEnvWrapper.h index 2723178..facc807 100644 --- a/service/resource-encapsulation/android/service/src/main/jni/util/JNIEnvWrapper.h +++ b/service/resource-encapsulation/android/service/src/main/jni/util/JNIEnvWrapper.h @@ -294,7 +294,14 @@ public: return ret; } - jobjectArray NewObjectArray(jsize len, jclass cls, jobject init) + jbyteArray NewByteArray(jsize len) + { + auto ret = m_env->NewByteArray(len); + if (m_env->ExceptionCheck()) throw JavaException(); + return ret; + } + + jobjectArray NewObjectArray(jsize len, jclass cls, jobject init) { auto ret = m_env->NewObjectArray(len, cls, init); if (m_env->ExceptionCheck()) throw JavaException(); @@ -315,6 +322,13 @@ public: return ret; } + jbyte *GetByteArrayElements(jbyteArray array, jboolean *value) + { + auto ret = m_env->GetByteArrayElements(array, value); + if (m_env->ExceptionCheck()) throw JavaException(); + return ret; + } + void SetObjectArrayElement(jobjectArray array, jsize index, jobject val) { m_env->SetObjectArrayElement(array, index, val); @@ -339,6 +353,12 @@ public: if (m_env->ExceptionCheck()) throw JavaException(); } + void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, const jbyte *buf) + { + m_env->SetByteArrayRegion(array, start, len, buf); + if (m_env->ExceptionCheck()) throw JavaException(); + } + void* GetPrimitiveArrayCritical(jarray array, jboolean* isCopy) { auto ret = m_env->GetPrimitiveArrayCritical(array, isCopy); @@ -352,7 +372,14 @@ public: if (m_env->ExceptionCheck()) throw JavaException(); } - void ThrowNew(jclass cls, const char* msg) { + void ReleaseByteArrayElements(jbyteArray array, jbyte* byteArray, int mode) + { + m_env->ReleaseByteArrayElements(array, byteArray, mode); + if (m_env->ExceptionCheck()) throw JavaException(); + } + + void ThrowNew(jclass cls, const char* msg) + { m_env->ThrowNew(cls, msg); throw JavaException(); } diff --git a/service/resource-encapsulation/android/service/src/main/jni/util/JavaClasses.h b/service/resource-encapsulation/android/service/src/main/jni/util/JavaClasses.h index d87e3d5..10033ad 100644 --- a/service/resource-encapsulation/android/service/src/main/jni/util/JavaClasses.h +++ b/service/resource-encapsulation/android/service/src/main/jni/util/JavaClasses.h @@ -31,6 +31,7 @@ #define CLS_NAME_RESOURCEATTRIBUTES PACKAGE_NAME "/RcsResourceAttributes" #define CLS_NAME_REMOTERESOURCEOBJECT PACKAGE_NAME "/client/RcsRemoteResourceObject" +#define CLS_NAME_RESOURCEBYTESTRING PACKAGE_NAME "/RcsByteString" #define CLS_NAME_OBJECT "java/lang/Object" #define CLS_NAME_STRING "java/lang/String"