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) 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->restart(); 90 91 return reinterpret_cast<jlong>(st); 92 } 93 94 static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz, 95 jlong token) 96 { 97 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 98 if (st == NULL) { 99 return ResXMLParser::END_DOCUMENT; 100 } 101 102 do { 103 ResXMLParser::event_code_t code = st->next(); 104 switch (code) { 105 case ResXMLParser::START_TAG: 106 return 2; 107 case ResXMLParser::END_TAG: 108 return 3; 109 case ResXMLParser::TEXT: 110 return 4; 111 case ResXMLParser::START_DOCUMENT: 112 return 0; 113 case ResXMLParser::END_DOCUMENT: 114 return 1; 115 case ResXMLParser::BAD_DOCUMENT: 116 goto bad; 117 default: 118 break; 119 } 120 } while (true); 121 122 bad: 123 jniThrowException(env, "org/xmlpull/v1/XmlPullParserException", 124 "Corrupt XML binary file"); 125 return ResXMLParser::BAD_DOCUMENT; 126 } 127 128 static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz, 129 jlong token) 130 { 131 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 132 if (st == NULL) { 133 return -1; 134 } 135 136 return static_cast<jint>(st->getElementNamespaceID()); 137 } 138 139 static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz, 140 jlong token) 141 { 142 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 143 if (st == NULL) { 144 return -1; 145 } 146 147 return static_cast<jint>(st->getElementNameID()); 148 } 149 150 static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz, 151 jlong token) 152 { 153 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 154 if (st == NULL) { 155 return -1; 156 } 157 158 return static_cast<jint>(st->getTextID()); 159 } 160 161 static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz, 162 jlong token) 163 { 164 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 165 if (st == NULL) { 166 jniThrowNullPointerException(env, NULL); 167 return 0; 168 } 169 170 return static_cast<jint>(st->getLineNumber()); 171 } 172 173 static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz, 174 jlong token) 175 { 176 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 177 if (st == NULL) { 178 jniThrowNullPointerException(env, NULL); 179 return 0; 180 } 181 182 return static_cast<jint>(st->getAttributeCount()); 183 } 184 185 static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz, 186 jlong token, jint idx) 187 { 188 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 189 if (st == NULL) { 190 jniThrowNullPointerException(env, NULL); 191 return 0; 192 } 193 194 return static_cast<jint>(st->getAttributeNamespaceID(idx)); 195 } 196 197 static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz, 198 jlong token, jint idx) 199 { 200 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 201 if (st == NULL) { 202 jniThrowNullPointerException(env, NULL); 203 return 0; 204 } 205 206 return static_cast<jint>(st->getAttributeNameID(idx)); 207 } 208 209 static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz, 210 jlong token, jint idx) 211 { 212 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 213 if (st == NULL) { 214 jniThrowNullPointerException(env, NULL); 215 return 0; 216 } 217 218 return static_cast<jint>(st->getAttributeNameResID(idx)); 219 } 220 221 static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz, 222 jlong token, jint idx) 223 { 224 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 225 if (st == NULL) { 226 jniThrowNullPointerException(env, NULL); 227 return 0; 228 } 229 230 return static_cast<jint>(st->getAttributeDataType(idx)); 231 } 232 233 static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz, 234 jlong token, jint idx) 235 { 236 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 237 if (st == NULL) { 238 jniThrowNullPointerException(env, NULL); 239 return 0; 240 } 241 242 return static_cast<jint>(st->getAttributeData(idx)); 243 } 244 245 static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz, 246 jlong token, jint idx) 247 { 248 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 249 if (st == NULL) { 250 jniThrowNullPointerException(env, NULL); 251 return 0; 252 } 253 254 return static_cast<jint>(st->getAttributeValueStringID(idx)); 255 } 256 257 static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz, 258 jlong token, 259 jstring ns, jstring name) 260 { 261 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 262 if (st == NULL || name == NULL) { 263 jniThrowNullPointerException(env, NULL); 264 return 0; 265 } 266 267 const char16_t* ns16 = NULL; 268 jsize nsLen = 0; 269 if (ns) { 270 ns16 = reinterpret_cast<const char16_t*>(env->GetStringChars(ns, NULL)); 271 nsLen = env->GetStringLength(ns); 272 } 273 274 const char16_t* name16 = reinterpret_cast<const char16_t*>( 275 env->GetStringChars(name, NULL)); 276 jsize nameLen = env->GetStringLength(name); 277 278 jint idx = static_cast<jint>(st->indexOfAttribute(ns16, nsLen, name16, nameLen)); 279 280 if (ns) { 281 env->ReleaseStringChars(ns, reinterpret_cast<const jchar*>(ns16)); 282 } 283 env->ReleaseStringChars(name, reinterpret_cast<const jchar*>(name16)); 284 285 return idx; 286 } 287 288 static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz, 289 jlong token) 290 { 291 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 292 if (st == NULL) { 293 jniThrowNullPointerException(env, NULL); 294 return 0; 295 } 296 297 ssize_t idx = st->indexOfID(); 298 return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; 299 } 300 301 static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz, 302 jlong token) 303 { 304 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 305 if (st == NULL) { 306 jniThrowNullPointerException(env, NULL); 307 return 0; 308 } 309 310 ssize_t idx = st->indexOfClass(); 311 return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; 312 } 313 314 static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz, 315 jlong token) 316 { 317 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 318 if (st == NULL) { 319 jniThrowNullPointerException(env, NULL); 320 return 0; 321 } 322 323 ssize_t idx = st->indexOfStyle(); 324 if (idx < 0) { 325 return 0; 326 } 327 328 Res_value value; 329 if (st->getAttributeValue(idx, &value) < 0) { 330 return 0; 331 } 332 333 return value.dataType == value.TYPE_REFERENCE 334 || value.dataType == value.TYPE_ATTRIBUTE 335 ? value.data : 0; 336 } 337 338 static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz, 339 jlong token) 340 { 341 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 342 if (st == NULL) { 343 jniThrowNullPointerException(env, NULL); 344 return; 345 } 346 347 delete st; 348 } 349 350 static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, 351 jlong token) 352 { 353 ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); 354 if (osb == NULL) { 355 jniThrowNullPointerException(env, NULL); 356 return; 357 } 358 359 delete osb; 360 } 361 362 // ---------------------------------------------------------------------------- 363 364 /* 365 * JNI registration. 366 */ 367 static const JNINativeMethod gXmlBlockMethods[] = { 368 /* name, signature, funcPtr */ 369 { "nativeCreate", "([BII)J", 370 (void*) android_content_XmlBlock_nativeCreate }, 371 { "nativeGetStringBlock", "(J)J", 372 (void*) android_content_XmlBlock_nativeGetStringBlock }, 373 { "nativeCreateParseState", "(J)J", 374 (void*) android_content_XmlBlock_nativeCreateParseState }, 375 { "nativeDestroyParseState", "(J)V", 376 (void*) android_content_XmlBlock_nativeDestroyParseState }, 377 { "nativeDestroy", "(J)V", 378 (void*) android_content_XmlBlock_nativeDestroy }, 379 380 // ------------------- @FastNative ---------------------- 381 382 { "nativeNext", "(J)I", 383 (void*) android_content_XmlBlock_nativeNext }, 384 { "nativeGetNamespace", "(J)I", 385 (void*) android_content_XmlBlock_nativeGetNamespace }, 386 { "nativeGetName", "(J)I", 387 (void*) android_content_XmlBlock_nativeGetName }, 388 { "nativeGetText", "(J)I", 389 (void*) android_content_XmlBlock_nativeGetText }, 390 { "nativeGetLineNumber", "(J)I", 391 (void*) android_content_XmlBlock_nativeGetLineNumber }, 392 { "nativeGetAttributeCount", "(J)I", 393 (void*) android_content_XmlBlock_nativeGetAttributeCount }, 394 { "nativeGetAttributeNamespace","(JI)I", 395 (void*) android_content_XmlBlock_nativeGetAttributeNamespace }, 396 { "nativeGetAttributeName", "(JI)I", 397 (void*) android_content_XmlBlock_nativeGetAttributeName }, 398 { "nativeGetAttributeResource", "(JI)I", 399 (void*) android_content_XmlBlock_nativeGetAttributeResource }, 400 { "nativeGetAttributeDataType", "(JI)I", 401 (void*) android_content_XmlBlock_nativeGetAttributeDataType }, 402 { "nativeGetAttributeData", "(JI)I", 403 (void*) android_content_XmlBlock_nativeGetAttributeData }, 404 { "nativeGetAttributeStringValue", "(JI)I", 405 (void*) android_content_XmlBlock_nativeGetAttributeStringValue }, 406 { "nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I", 407 (void*) android_content_XmlBlock_nativeGetAttributeIndex }, 408 { "nativeGetIdAttribute", "(J)I", 409 (void*) android_content_XmlBlock_nativeGetIdAttribute }, 410 { "nativeGetClassAttribute", "(J)I", 411 (void*) android_content_XmlBlock_nativeGetClassAttribute }, 412 { "nativeGetStyleAttribute", "(J)I", 413 (void*) android_content_XmlBlock_nativeGetStyleAttribute }, 414 }; 415 416 int register_android_content_XmlBlock(JNIEnv* env) 417 { 418 return RegisterMethodsOrDie(env, 419 "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods)); 420 } 421 422 }; // namespace android 423