Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <android_runtime/AndroidRuntime.h>
     18 #include "utils/Log.h"
     19 #include "DMServiceMain.h"
     20 #include "dmt.hpp"
     21 #include <stdarg.h>
     22 #include <dmMemory.h>
     23 
     24 extern "C" {
     25 #include "xltdec.h"
     26 }
     27 
     28 static const int RESULT_BUF_SIZE = 8192; /*2048*/
     29 
     30 // FIXME: get rid of these static variables!
     31 static PDmtTree ptrTree = NULL;
     32 static DMString s_strRootPath;
     33 static DmtPrincipal principal("localhost");
     34 static bool bShowTimestamp = false;
     35 
     36 static PDmtTree GetTree();
     37 static SYNCML_DM_RET_STATUS_T PrintNode(PDmtNode ptrNode);
     38 static void DumpSubTree(PDmtNode ptrNode);
     39 
     40 static char resultBuf[RESULT_BUF_SIZE];
     41 static void strcatEx(const char * format, ...)
     42 {
     43     if (!format) {
     44         return;
     45     }
     46 
     47     int len = strlen(resultBuf);
     48     if (len < RESULT_BUF_SIZE - 1) {
     49         va_list args;
     50         va_start(args, format);
     51         int ret = vsnprintf(&resultBuf[len], RESULT_BUF_SIZE - len - 1, format, args);
     52         if (ret == -1) {
     53             resultBuf[RESULT_BUF_SIZE - 1] = 0x0;
     54         }
     55         va_end(args);
     56     }
     57 }
     58 
     59 static PDmtNode GetNode(const DMString& strNodeName)
     60 {
     61     PDmtNode ptrNode;
     62     GetTree();
     63 
     64     if (ptrTree) {
     65         if (ptrTree->GetNode(strNodeName, ptrNode) != SYNCML_DM_SUCCESS) {
     66             strcatEx("can't get node %s", strNodeName.c_str());
     67         }
     68     }
     69 
     70     return ptrNode;
     71 }
     72 
     73 JNIEXPORT jstring JNICALL setStringNode(JNIEnv* jenv, jclass, jstring nodePath, jstring value)
     74 {
     75     resultBuf[0] = 0x0;
     76 
     77     const char* szNodePath = jenv->GetStringUTFChars(nodePath, NULL);
     78     const char* szValue = jenv->GetStringUTFChars(value, NULL);
     79 
     80     DMString strNodePath(szNodePath);
     81     DMString strValue(szValue);
     82 
     83     jenv->ReleaseStringUTFChars(nodePath, szNodePath);
     84     jenv->ReleaseStringUTFChars(value, szValue);
     85 
     86     PDmtNode ptrNode = GetNode(strNodePath);
     87     if (!ptrNode) {
     88         goto end;
     89     }
     90 
     91     if (ptrNode->SetStringValue(strValue) == SYNCML_DM_SUCCESS) {
     92         strcatEx("set value of node %s to %s successfully\n", strNodePath.c_str(), strValue.c_str());
     93         PrintNode(ptrNode);
     94     } else {
     95         strcatEx("can't set value of node %s to %s", strNodePath.c_str(), strValue.c_str());
     96     }
     97 
     98 end:
     99     jstring ret = jenv->NewStringUTF(resultBuf);
    100     return ret;
    101 }
    102 
    103 JNIEXPORT jstring JNICALL getNodeInfo(JNIEnv* jenv, jclass, jstring jszNode)
    104 {
    105     resultBuf[0] = 0x0;
    106 
    107     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    108     DMString strNode(szNode);
    109     jenv->ReleaseStringUTFChars(jszNode, szNode);
    110 
    111     PDmtNode ptrNode = GetNode(strNode);
    112     if (ptrNode) {
    113         PrintNode(ptrNode);
    114     }
    115 
    116     jstring ret = jenv->NewStringUTF(resultBuf);
    117     return ret;
    118 }
    119 
    120 JNIEXPORT jint JNICALL getNodeType(JNIEnv* jenv, jclass, jstring jszNode)
    121 {
    122     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    123     DMString strNode(szNode);
    124     jenv->ReleaseStringUTFChars(jszNode, szNode);
    125 
    126     PDmtNode ptrNode = GetNode(strNode);
    127     if (ptrNode && !ptrNode->IsExternalStorageNode())
    128     {
    129         DmtData oData;
    130         LOGD("Enter get value...\n");
    131         SYNCML_DM_RET_STATUS_T ret = ptrNode->GetValue(oData);
    132         if (ret != SYNCML_DM_SUCCESS) {
    133             LOGD("Value is null");
    134             return 0;   // return NULL type on error
    135         }
    136         return oData.GetType();
    137     }
    138 
    139     return 0;   // return NULL type on error
    140 }
    141 
    142 JNIEXPORT jstring JNICALL getNodeValue(JNIEnv* jenv, jclass, jstring jszNode)
    143 {
    144     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    145     DMString strNode(szNode);
    146     jenv->ReleaseStringUTFChars(jszNode, szNode);
    147 
    148     PDmtNode ptrNode = GetNode(strNode);
    149     if (ptrNode && !ptrNode->IsExternalStorageNode())
    150     {
    151         LOGD("Enter get value...\n");
    152         DmtData oData;
    153         DMString value;
    154 
    155         if (!ptrNode->IsLeaf()) {
    156             SYNCML_DM_RET_STATUS_T ret = ptrNode->GetValue(oData);
    157             if (ret != SYNCML_DM_SUCCESS) {
    158                 LOGE("can't get child nodes");
    159                 return NULL;    // return NULL reference on error
    160             }
    161             DMStringVector aChildren;
    162             ret = oData.GetNodeValue(aChildren);
    163             if (ret != SYNCML_DM_SUCCESS) {
    164                 LOGE("oData.getNodeValue() failed");
    165                 return NULL;    // return NULL reference on error
    166             }
    167             UINT32 childLength = aChildren.size();
    168             for (UINT32 i = 0; i < childLength; ++i) {
    169                 if (i != 0) {
    170                     value += '|';
    171                 }
    172                 value += aChildren[i];
    173             }
    174         }
    175         else
    176         {
    177             SYNCML_DM_RET_STATUS_T ret = ptrNode->GetValue(oData);
    178             if (ret != SYNCML_DM_SUCCESS) {
    179                 LOGE("Value is null");
    180                 return NULL;   // return NULL reference on error
    181             }
    182             if (oData.GetString(value) != SYNCML_DM_SUCCESS) {
    183                 LOGE("oData.GetString() failed");
    184                 return NULL;   // return NULL reference on error
    185             }
    186         }
    187 
    188         return jenv->NewStringUTF(value.c_str());
    189     }
    190 
    191     return NULL;    // return NULL reference on error
    192 }
    193 
    194 JNIEXPORT jstring JNICALL executePlugin(JNIEnv* jenv, jclass, jstring jszNode, jstring jszData)
    195 {
    196     resultBuf[0] = 0x0;
    197 
    198     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    199     DMString strNode(szNode);
    200     jenv->ReleaseStringUTFChars(jszNode, szNode);
    201 
    202     const char* szData = jenv->GetStringUTFChars(jszData, NULL);
    203     DMString strData(szData);
    204     jenv->ReleaseStringUTFChars(jszData, szData);
    205 
    206     PDmtNode ptrNode = GetNode(strNode);
    207     if (ptrNode) {
    208         DMString strResult;
    209         if (ptrNode->Execute(strData, strResult) == SYNCML_DM_SUCCESS) {
    210             strcatEx("execute node %s successfully, result=%s\n", strNode.c_str(), strResult.c_str());
    211         } else {
    212             strcatEx("can't execute node %s", strNode.c_str());
    213         }
    214     }
    215 
    216     jstring ret = jenv->NewStringUTF(resultBuf);
    217     return ret;
    218 }
    219 
    220 JNIEXPORT jstring JNICALL dumpTree(JNIEnv *jenv, jclass, jstring jszNode)
    221 {
    222     resultBuf[0] = 0x0;
    223 
    224     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    225     DMString strNode(szNode);
    226     jenv->ReleaseStringUTFChars(jszNode, szNode);
    227 
    228     PDmtNode ptrNode = GetNode(strNode);
    229     if (ptrNode) {
    230         DumpSubTree(ptrNode);
    231     }
    232 
    233     jstring ret = jenv->NewStringUTF(resultBuf);
    234     return ret;
    235 }
    236 
    237 JNIEXPORT jint JNICALL createInterior(JNIEnv *jenv, jclass, jstring jszNode)
    238 {
    239     GetTree();
    240     if (!ptrTree) {
    241         return static_cast<jint>(SYNCML_DM_FAIL);
    242     }
    243 
    244     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    245     DMString strNode(szNode);
    246     jenv->ReleaseStringUTFChars(jszNode, szNode);
    247 
    248     PDmtNode ptrNode;
    249     SYNCML_DM_RET_STATUS_T ret = ptrTree->CreateInteriorNode(strNode, ptrNode);
    250     if (ret == SYNCML_DM_SUCCESS) {
    251         LOGI("node %s created successfully\n", strNode.c_str());
    252     } else {
    253         LOGE("can't create node %s", strNode.c_str());
    254     }
    255     return static_cast<jint>(ret);
    256 }
    257 
    258 JNIEXPORT jint JNICALL createLeaf(JNIEnv *jenv, jclass, jstring jszNode, jstring jszData)
    259 {
    260     if (jszNode == NULL) {
    261         return static_cast<jint>(SYNCML_DM_FAIL);
    262     }
    263 
    264     GetTree();
    265     if (!ptrTree) {
    266         return static_cast<jint>(SYNCML_DM_FAIL);
    267     }
    268 
    269     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    270     const char* szData = NULL;
    271 
    272     if (jszData != NULL) {
    273         szData = jenv->GetStringUTFChars(jszData, NULL);
    274     }
    275 
    276     PDmtNode ptrNode;
    277     SYNCML_DM_RET_STATUS_T ret = ptrTree->CreateLeafNode(szNode, ptrNode, DmtData(szData));
    278     if (ret == SYNCML_DM_SUCCESS) {
    279         LOGI("node %s (%s) created successfully\n", szNode, szData);
    280     } else {
    281         LOGE("can't create node %s", szNode);
    282     }
    283 
    284     jenv->ReleaseStringUTFChars(jszNode, szNode);
    285     jenv->ReleaseStringUTFChars(jszData, szData);
    286 
    287     return static_cast<jint>(ret);
    288 }
    289 
    290 
    291 JNIEXPORT jint JNICALL createLeafByte(JNIEnv *jenv, jclass clz, jstring jszNode,
    292         jbyteArray bDataArray)
    293 {
    294     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    295     jbyte* jData = (jbyte*)jenv->GetByteArrayElements(bDataArray, NULL);
    296     jsize arraySize = jenv->GetArrayLength(bDataArray);
    297 
    298     char* pData = (char*)DmAllocMem(arraySize+1);
    299     memcpy(pData, jData, arraySize);
    300     pData[arraySize] = '\0';
    301 
    302     PDmtNode ptrNode;
    303     GetTree();
    304 
    305     jenv->ReleaseByteArrayElements(bDataArray, jData, 0);
    306 
    307     if ( ptrTree == NULL ) {
    308         DmFreeMem(pData);
    309         return SYNCML_DM_FAIL;
    310     }
    311 
    312     LOGI("NodePath=%s,Byte Data=0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X\n", szNode, pData[0], pData[1],
    313             pData[2], pData[3], pData[4], pData[5], pData[6]);
    314 
    315     DMString strNode(szNode);
    316 
    317     //PDmtNode ptrNode;
    318     SYNCML_DM_RET_STATUS_T ret = ptrTree->CreateLeafNode(szNode, ptrNode, DmtData( pData ));
    319     if (ret == SYNCML_DM_SUCCESS) {
    320         LOGI("node %s created successfully\n", strNode.c_str());
    321     } else {
    322         LOGE("can't create node %s", strNode.c_str());
    323     }
    324     return static_cast<jint>(ret);
    325 }
    326 
    327 JNIEXPORT jint JNICALL deleteNode(JNIEnv *jenv, jclass, jstring jszNode)
    328 {
    329     GetTree();
    330     if (!ptrTree) {
    331         return static_cast<jint>(SYNCML_DM_FAIL);
    332     }
    333 
    334     const char* szNode = jenv->GetStringUTFChars(jszNode, NULL);
    335     DMString strNode(szNode);
    336     jenv->ReleaseStringUTFChars(jszNode, szNode);
    337 
    338     SYNCML_DM_RET_STATUS_T ret = ptrTree->DeleteNode(strNode);
    339     if (ret == SYNCML_DM_SUCCESS) {
    340         LOGI("node %s deleted successfully\n", strNode.c_str());
    341     } else {
    342         LOGE("can't delete node %s", strNode.c_str());
    343     }
    344     return static_cast<jint>(ret);
    345 }
    346 
    347 static PDmtTree GetTree()
    348 {
    349     if (ptrTree) return ptrTree;
    350 
    351     if (DmtTreeFactory::GetSubtree(principal, s_strRootPath, ptrTree) != SYNCML_DM_SUCCESS) {
    352         strcatEx("Can't get tree '%s'.", s_strRootPath.c_str());
    353     }
    354 
    355     return ptrTree;
    356 }
    357 
    358 static void DumpSubTree(PDmtNode ptrNode)
    359 {
    360     SYNCML_DM_RET_STATUS_T ret = PrintNode(ptrNode);
    361     strcatEx("\n");
    362     if (ret != SYNCML_DM_SUCCESS) return;
    363 
    364     if (!ptrNode->IsLeaf()) {
    365         DMVector<PDmtNode> aChildren;
    366         ret = ptrNode->GetChildNodes(aChildren);
    367         if (ret != SYNCML_DM_SUCCESS) {
    368             DMString path;
    369             ptrNode->GetPath(path);
    370             strcatEx("can't get child nodes of %s", path.c_str());
    371             return;
    372         }
    373         UINT32 childLength = aChildren.size();
    374         for (UINT32 i = 0; i < childLength; ++i) {
    375             DumpSubTree(aChildren[i]);
    376         }
    377     }
    378 }
    379 
    380 static SYNCML_DM_RET_STATUS_T PrintNode(PDmtNode ptrNode)
    381 {
    382     LOGD("Enter PrintNode\n");
    383     DmtAttributes oAttr;
    384     DMString path;
    385 
    386     SYNCML_DM_RET_STATUS_T ret = ptrNode->GetPath(path);
    387     if (ret != SYNCML_DM_SUCCESS)
    388     {
    389         strcatEx("can't get attributes of node %d", ret);
    390     }
    391 
    392     LOGD("Get attributes\n");
    393     if ((ret = ptrNode->GetAttributes(oAttr)) != ptrNode->GetPath(path)) {
    394         strcatEx("can't get attributes of node %s", path.c_str());
    395         return ret;
    396     }
    397 
    398     LOGD("Check storage mode...\n");
    399     DmtData oData;
    400     if (!ptrNode->IsExternalStorageNode())
    401     {
    402         LOGD("Enter get value...\n");
    403         SYNCML_DM_RET_STATUS_T ret1 = ptrNode->GetValue(oData);
    404         if (ret1 != SYNCML_DM_SUCCESS) {
    405             LOGD("Value is null");
    406             strcatEx("can't get value of node %s", path.c_str());
    407             return ret1;
    408         }
    409     }
    410 
    411     LOGD("Compose string begin...\n");
    412     strcatEx("path=%s\n", (const char*)path.c_str());
    413     strcatEx("isLeaf=%s\n", (ptrNode->IsLeaf()?"true":"false") );
    414     strcatEx("name=%s\n", (const char*)oAttr.GetName().c_str() );
    415     strcatEx("format=%s\n", (const char*)oAttr.GetFormat().c_str() );
    416     strcatEx("type=%s\n", (const char*)oAttr.GetType().c_str() );
    417     strcatEx("title=%s\n", (const char*)oAttr.GetTitle().c_str() );
    418     strcatEx("acl=%s\n", (const char*)oAttr.GetAcl().toString().c_str() );
    419     strcatEx("size=%d\n", oAttr.GetSize());
    420     if (bShowTimestamp) {
    421         time_t timestamp = (time_t)(oAttr.GetTimestamp()/1000L);
    422         if (timestamp == 0) {
    423             strcatEx("timestamp=(Unknown)\n");
    424         } else {
    425             char timestampbuf[27];
    426             ctime_r(&timestamp, timestampbuf);
    427             strcatEx("timestamp=%s", timestampbuf);
    428         }
    429     }
    430 
    431     strcatEx("version=%d\n", oAttr.GetVersion() );
    432     if ( !ptrNode->IsLeaf() ) {
    433         DMStringVector aChildren;
    434         oData.GetNodeValue(aChildren);
    435         strcatEx("children:");
    436         if ( aChildren.size() == 0 ) {
    437             strcatEx("null");
    438         }
    439         UINT32 childLength = aChildren.size();
    440         for (UINT32 i = 0; i < childLength; ++i) {
    441             const DMString& child = aChildren[i];
    442             strcatEx("%s/", child.c_str());
    443         }
    444         strcatEx("\n");
    445     } else {
    446         if (ptrNode->IsExternalStorageNode())
    447         {
    448             strcatEx("value=\n");
    449             strcatEx("It is an ESN node, not supported now");
    450             //displayESN(ptrNode);
    451         }
    452         else {
    453             if (oAttr.GetFormat() == "bin") {
    454                 strcatEx("Binary value: [");
    455                 const DMVector<UINT8>& val = oData.GetBinaryValue();
    456                 UINT32 valLength = val.size();
    457                 for (UINT32 i = 0; i < valLength; ++i) {
    458                     UINT8 byte = val[i];
    459                     strcatEx("%02x ", byte);
    460                 }
    461                 strcatEx("]\n");
    462             }
    463             else
    464             {
    465                 DMString s;
    466                 oData.GetString(s);
    467                 strcatEx("value=%s\n", s.c_str());
    468             }
    469         }
    470     }
    471     return SYNCML_DM_SUCCESS;
    472 }
    473 
    474 short wbxml2xml(unsigned char *bufIn, int bufInLen, unsigned char *bufOut, int * bufOutLen)
    475 {
    476     short ret = 0;
    477 #ifdef __SML_WBXML__
    478     ret = wbxml2xmlInternal(bufIn, bufInLen, bufOut,bufOutLen);
    479 #endif
    480     return ret;
    481 }
    482 
    483 JNIEXPORT jbyteArray JNICALL ConvertWbxml2Xml(JNIEnv* env, jclass, jbyteArray bArray)
    484 {
    485     unsigned char* xmlBuf = NULL;
    486     int xmlLen = 0;
    487 
    488     jbyte* wbxmlBuf = env->GetByteArrayElements(bArray, NULL);
    489     jsize  wbxmlLen = env->GetArrayLength(bArray);
    490     LOGD("ConvertWbxml2Xml: wbxml length = %d\n", wbxmlLen);
    491 
    492     if (wbxmlBuf == NULL || wbxmlLen <= 0)
    493     {
    494         LOGD("ConvertWbxml2Xml: nothing to convert\n");
    495         return NULL;
    496     }
    497 
    498     xmlLen = wbxmlLen * 6;
    499     xmlBuf = new unsigned char[xmlLen];
    500     if (xmlBuf == NULL)
    501     {
    502         LOGE("ConvertWbxml2Xml: failed to allocate memory\n");
    503         return NULL;
    504     }
    505     LOGD("ConvertWbxml2Xml: allocated xml length = %d\n", xmlLen);
    506 
    507 #ifdef __SML_WBXML__
    508     short ret = wbxml2xmlInternal((unsigned char*)wbxmlBuf, wbxmlLen, xmlBuf, &xmlLen);
    509 #else
    510     short ret = -1;
    511 #endif
    512 
    513     if (ret != 0) {
    514         LOGE("ConvertWbxml2Xml: wbxml2xml failed: %d\n", ret);
    515         delete [] xmlBuf;
    516         return NULL;
    517     }
    518 
    519     jbyteArray jb = env->NewByteArray(xmlLen);
    520     env->SetByteArrayRegion(jb, 0, xmlLen, (jbyte*)xmlBuf);
    521     LOGD("ConvertWbxml2Xml: result xml length = %d\n", xmlLen);
    522     delete [] xmlBuf;
    523     return jb;
    524 }
    525 
    526 static JNINativeMethod gMethods[] = {
    527     {"setStringNode",
    528         "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
    529         (void*)setStringNode},
    530     {"getNodeInfo",
    531         "(Ljava/lang/String;)Ljava/lang/String;",
    532         (void*)getNodeInfo},
    533     {"executePlugin",
    534         "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
    535         (void*)executePlugin},
    536     {"dumpTree",
    537         "(Ljava/lang/String;)Ljava/lang/String;",
    538         (void*)dumpTree},
    539     {"createInterior",
    540         "(Ljava/lang/String;)I",
    541         (void*)createInterior},
    542     {"createLeaf",
    543         "(Ljava/lang/String;Ljava/lang/String;)I",
    544         (void*)createLeaf},
    545     {"createLeaf",
    546         "(Ljava/lang/String;[B)I",
    547         (void*)createLeafByte},
    548     {"deleteNode",
    549         "(Ljava/lang/String;)I",
    550         (void*)deleteNode},
    551     {"nativeWbxmlToXml",
    552         "([B)[B",
    553         (void*)ConvertWbxml2Xml},
    554     {"getNodeType",
    555         "(Ljava/lang/String;)I",
    556         (void*)getNodeType},
    557     {"getNodeValue",
    558         "(Ljava/lang/String;)Ljava/lang/String;",
    559         (void*)getNodeValue},
    560 };
    561 
    562 int registerDMTreeNatives(JNIEnv *env)
    563 {
    564     jclass clazz = env->FindClass(javaDMEnginePackage);
    565     if (clazz == NULL)
    566         return JNI_FALSE;
    567 
    568     if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0)
    569     {
    570         LOGE("registerDMTreeNatives return ERROR");
    571         return JNI_FALSE;
    572     }
    573 
    574     return JNI_TRUE;
    575 }
    576