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