Add ByteString support for RCSResourceAttributes JAVA and JNI.
authorkoushik.girijala <g.koushik@samsung.com>
Fri, 30 Dec 2016 10:49:36 +0000 (16:19 +0530)
committerUze Choi <uzchoi@samsung.com>
Wed, 4 Jan 2017 04:26:07 +0000 (04:26 +0000)
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 <g.koushik@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/16029
Reviewed-by: Abhishek Pandey <abhi.siso@samsung.com>
Reviewed-by: JungYong KIM <jyong2.kim@samsung.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsByteString.java [new file with mode: 0644]
service/resource-encapsulation/android/service/src/main/java/org/iotivity/service/RcsValue.java
service/resource-encapsulation/android/service/src/main/jni/JniRcsValue.cpp
service/resource-encapsulation/android/service/src/main/jni/util/JNIEnvWrapper.h
service/resource-encapsulation/android/service/src/main/jni/util/JavaClasses.h

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 (file)
index 0000000..e02ad74
--- /dev/null
@@ -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
index e1fd331..a9edc82 100644 (file)
@@ -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.
      *
index 46ea958..cb1639f 100644 (file)
@@ -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<uint8_t> 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<JNIEnvWrapper>) converter;
+
+        static decltype(&newRCSByteStringObject<JNIEnvWrapper>) newObjectFunc;
+
+        static constexpr char className[] = CLS_NAME_RESOURCEBYTESTRING;
+    };
+    constexpr char JniTypeTrait< RCSByteString >::className[];
+    decltype(&invoke_ByteString_byteStringValue<JNIEnvWrapper>) JniTypeTrait< RCSByteString >::converter =
+        &invoke_ByteString_byteStringValue<JNIEnvWrapper>;
+
+    decltype(&newRCSByteStringObject<JNIEnvWrapper>) JniTypeTrait< RCSByteString >::newObjectFunc =
+        &newRCSByteStringObject<JNIEnvWrapper>;
 
     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);
 }
index 2723178..facc807 100644 (file)
@@ -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();
     }
index d87e3d5..10033ad 100644 (file)
@@ -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"