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