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(×tamp, 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