1 /* //device/libs/android_runtime/android_util_XmlBlock.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "XmlBlock" 19 20 #include "jni.h" 21 #include <nativehelper/JNIHelp.h> 22 #include <core_jni_helpers.h> 23 #include <androidfw/AssetManager.h> 24 #include <androidfw/ResourceTypes.h> 25 #include <utils/Log.h> 26 #include <utils/misc.h> 27 28 #include <stdio.h> 29 30 namespace android { 31 32 // ---------------------------------------------------------------------------- 33 34 static jlong android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz, 35 jbyteArray bArray, 36 jint off, jint len) 37 { 38 if (bArray == NULL) { 39 jniThrowNullPointerException(env, NULL); 40 return 0; 41 } 42 43 jsize bLen = env->GetArrayLength(bArray); 44 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) { 45 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 46 return 0; 47 } 48 49 jbyte* b = env->GetByteArrayElements(bArray, NULL); 50 ResXMLTree* osb = new ResXMLTree(); 51 osb->setTo(b+off, len, true); 52 env->ReleaseByteArrayElements(bArray, b, 0); 53 54 if (osb->getError() != NO_ERROR) { 55 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 56 return 0; 57 } 58 59 return reinterpret_cast<jlong>(osb); 60 } 61 62 static jlong android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz, 63 jlong token) 64 { 65 ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); 66 if (osb == NULL) { 67 jniThrowNullPointerException(env, NULL); 68 return 0; 69 } 70 71 return reinterpret_cast<jlong>(&osb->getStrings()); 72 } 73 74 static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz, 75 jlong token, jint res_id) 76 { 77 ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); 78 if (osb == NULL) { 79 jniThrowNullPointerException(env, NULL); 80 return 0; 81 } 82 83 ResXMLParser* st = new ResXMLParser(*osb); 84 if (st == NULL) { 85 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 86 return 0; 87 } 88 89 st->setSourceResourceId(res_id); 90 st->restart(); 91 92 return reinterpret_cast<jlong>(st); 93 } 94 95 static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz, 96 jlong token) 97 { 98 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 99 if (st == NULL) { 100 return ResXMLParser::END_DOCUMENT; 101 } 102 103 do { 104 ResXMLParser::event_code_t code = st->next(); 105 switch (code) { 106 case ResXMLParser::START_TAG: 107 return 2; 108 case ResXMLParser::END_TAG: 109 return 3; 110 case ResXMLParser::TEXT: 111 return 4; 112 case ResXMLParser::START_DOCUMENT: 113 return 0; 114 case ResXMLParser::END_DOCUMENT: 115 return 1; 116 case ResXMLParser::BAD_DOCUMENT: 117 goto bad; 118 default: 119 break; 120 } 121 } while (true); 122 123 bad: 124 jniThrowException(env, "org/xmlpull/v1/XmlPullParserException", 125 "Corrupt XML binary file"); 126 return ResXMLParser::BAD_DOCUMENT; 127 } 128 129 static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz, 130 jlong token) 131 { 132 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 133 if (st == NULL) { 134 return -1; 135 } 136 137 return static_cast<jint>(st->getElementNamespaceID()); 138 } 139 140 static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz, 141 jlong token) 142 { 143 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 144 if (st == NULL) { 145 return -1; 146 } 147 148 return static_cast<jint>(st->getElementNameID()); 149 } 150 151 static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz, 152 jlong token) 153 { 154 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 155 if (st == NULL) { 156 return -1; 157 } 158 159 return static_cast<jint>(st->getTextID()); 160 } 161 162 static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz, 163 jlong token) 164 { 165 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 166 if (st == NULL) { 167 jniThrowNullPointerException(env, NULL); 168 return 0; 169 } 170 171 return static_cast<jint>(st->getLineNumber()); 172 } 173 174 static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz, 175 jlong token) 176 { 177 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 178 if (st == NULL) { 179 jniThrowNullPointerException(env, NULL); 180 return 0; 181 } 182 183 return static_cast<jint>(st->getAttributeCount()); 184 } 185 186 static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz, 187 jlong token, jint idx) 188 { 189 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 190 if (st == NULL) { 191 jniThrowNullPointerException(env, NULL); 192 return 0; 193 } 194 195 return static_cast<jint>(st->getAttributeNamespaceID(idx)); 196 } 197 198 static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz, 199 jlong token, jint idx) 200 { 201 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 202 if (st == NULL) { 203 jniThrowNullPointerException(env, NULL); 204 return 0; 205 } 206 207 return static_cast<jint>(st->getAttributeNameID(idx)); 208 } 209 210 static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz, 211 jlong token, jint idx) 212 { 213 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 214 if (st == NULL) { 215 jniThrowNullPointerException(env, NULL); 216 return 0; 217 } 218 219 return static_cast<jint>(st->getAttributeNameResID(idx)); 220 } 221 222 static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz, 223 jlong token, jint idx) 224 { 225 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 226 if (st == NULL) { 227 jniThrowNullPointerException(env, NULL); 228 return 0; 229 } 230 231 return static_cast<jint>(st->getAttributeDataType(idx)); 232 } 233 234 static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz, 235 jlong token, jint idx) 236 { 237 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 238 if (st == NULL) { 239 jniThrowNullPointerException(env, NULL); 240 return 0; 241 } 242 243 return static_cast<jint>(st->getAttributeData(idx)); 244 } 245 246 static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz, 247 jlong token, jint idx) 248 { 249 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 250 if (st == NULL) { 251 jniThrowNullPointerException(env, NULL); 252 return 0; 253 } 254 255 return static_cast<jint>(st->getAttributeValueStringID(idx)); 256 } 257 258 static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz, 259 jlong token, 260 jstring ns, jstring name) 261 { 262 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 263 if (st == NULL || name == NULL) { 264 jniThrowNullPointerException(env, NULL); 265 return 0; 266 } 267 268 const char16_t* ns16 = NULL; 269 jsize nsLen = 0; 270 if (ns) { 271 ns16 = reinterpret_cast<const char16_t*>(env->GetStringChars(ns, NULL)); 272 nsLen = env->GetStringLength(ns); 273 } 274 275 const char16_t* name16 = reinterpret_cast<const char16_t*>( 276 env->GetStringChars(name, NULL)); 277 jsize nameLen = env->GetStringLength(name); 278 279 jint idx = static_cast<jint>(st->indexOfAttribute(ns16, nsLen, name16, nameLen)); 280 281 if (ns) { 282 env->ReleaseStringChars(ns, reinterpret_cast<const jchar*>(ns16)); 283 } 284 env->ReleaseStringChars(name, reinterpret_cast<const jchar*>(name16)); 285 286 return idx; 287 } 288 289 static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz, 290 jlong token) 291 { 292 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 293 if (st == NULL) { 294 jniThrowNullPointerException(env, NULL); 295 return 0; 296 } 297 298 ssize_t idx = st->indexOfID(); 299 return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; 300 } 301 302 static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz, 303 jlong token) 304 { 305 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 306 if (st == NULL) { 307 jniThrowNullPointerException(env, NULL); 308 return 0; 309 } 310 311 ssize_t idx = st->indexOfClass(); 312 return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; 313 } 314 315 static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz, 316 jlong token) 317 { 318 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 319 if (st == NULL) { 320 jniThrowNullPointerException(env, NULL); 321 return 0; 322 } 323 324 ssize_t idx = st->indexOfStyle(); 325 if (idx < 0) { 326 return 0; 327 } 328 329 Res_value value; 330 if (st->getAttributeValue(idx, &value) < 0) { 331 return 0; 332 } 333 334 return value.dataType == value.TYPE_REFERENCE 335 || value.dataType == value.TYPE_ATTRIBUTE 336 ? value.data : 0; 337 } 338 339 static jint android_content_XmlBlock_nativeGetSourceResId(JNIEnv* env, jobject clazz, 340 jlong token) 341 { 342 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 343 if (st == NULL) { 344 return 0; 345 } else { 346 return st->getSourceResourceId(); 347 } 348 } 349 350 static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz, 351 jlong token) 352 { 353 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 354 if (st == NULL) { 355 jniThrowNullPointerException(env, NULL); 356 return; 357 } 358 359 delete st; 360 } 361 362 static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, 363 jlong token) 364 { 365 ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); 366 if (osb == NULL) { 367 jniThrowNullPointerException(env, NULL); 368 return; 369 } 370 371 delete osb; 372 } 373 374 // ---------------------------------------------------------------------------- 375 376 /* 377 * JNI registration. 378 */ 379 static const JNINativeMethod gXmlBlockMethods[] = { 380 /* name, signature, funcPtr */ 381 { "nativeCreate", "([BII)J", 382 (void*) android_content_XmlBlock_nativeCreate }, 383 { "nativeGetStringBlock", "(J)J", 384 (void*) android_content_XmlBlock_nativeGetStringBlock }, 385 { "nativeCreateParseState", "(JI)J", 386 (void*) android_content_XmlBlock_nativeCreateParseState }, 387 { "nativeDestroyParseState", "(J)V", 388 (void*) android_content_XmlBlock_nativeDestroyParseState }, 389 { "nativeDestroy", "(J)V", 390 (void*) android_content_XmlBlock_nativeDestroy }, 391 392 // ------------------- @FastNative ---------------------- 393 394 { "nativeNext", "(J)I", 395 (void*) android_content_XmlBlock_nativeNext }, 396 { "nativeGetNamespace", "(J)I", 397 (void*) android_content_XmlBlock_nativeGetNamespace }, 398 { "nativeGetName", "(J)I", 399 (void*) android_content_XmlBlock_nativeGetName }, 400 { "nativeGetText", "(J)I", 401 (void*) android_content_XmlBlock_nativeGetText }, 402 { "nativeGetLineNumber", "(J)I", 403 (void*) android_content_XmlBlock_nativeGetLineNumber }, 404 { "nativeGetAttributeCount", "(J)I", 405 (void*) android_content_XmlBlock_nativeGetAttributeCount }, 406 { "nativeGetAttributeNamespace","(JI)I", 407 (void*) android_content_XmlBlock_nativeGetAttributeNamespace }, 408 { "nativeGetAttributeName", "(JI)I", 409 (void*) android_content_XmlBlock_nativeGetAttributeName }, 410 { "nativeGetAttributeResource", "(JI)I", 411 (void*) android_content_XmlBlock_nativeGetAttributeResource }, 412 { "nativeGetAttributeDataType", "(JI)I", 413 (void*) android_content_XmlBlock_nativeGetAttributeDataType }, 414 { "nativeGetAttributeData", "(JI)I", 415 (void*) android_content_XmlBlock_nativeGetAttributeData }, 416 { "nativeGetAttributeStringValue", "(JI)I", 417 (void*) android_content_XmlBlock_nativeGetAttributeStringValue }, 418 { "nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I", 419 (void*) android_content_XmlBlock_nativeGetAttributeIndex }, 420 { "nativeGetIdAttribute", "(J)I", 421 (void*) android_content_XmlBlock_nativeGetIdAttribute }, 422 { "nativeGetClassAttribute", "(J)I", 423 (void*) android_content_XmlBlock_nativeGetClassAttribute }, 424 { "nativeGetStyleAttribute", "(J)I", 425 (void*) android_content_XmlBlock_nativeGetStyleAttribute }, 426 { "nativeGetSourceResId", "(J)I", 427 (void*) android_content_XmlBlock_nativeGetSourceResId}, 428 }; 429 430 int register_android_content_XmlBlock(JNIEnv* env) 431 { 432 return RegisterMethodsOrDie(env, 433 "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods)); 434 } 435 436 }; // namespace android 437