android_util_XmlBlock.cpp revision 896043d67d3ac75760bd99db8a1561e31ebee1e1
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 30namespace android { 31 32// ---------------------------------------------------------------------------- 33 34static 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(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 reinterpret_cast<jlong>(osb); 59} 60 61static jlong android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz, 62 jlong token) 63{ 64 ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); 65 if (osb == NULL) { 66 jniThrowNullPointerException(env, NULL); 67 return 0; 68 } 69 70 return reinterpret_cast<jlong>(&osb->getStrings()); 71} 72 73static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz, 74 jlong token) 75{ 76 ResXMLTree* osb = reinterpret_cast<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 reinterpret_cast<jlong>(st); 91} 92 93static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz, 94 jlong token) 95{ 96 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 97 if (st == NULL) { 98 return ResXMLParser::END_DOCUMENT; 99 } 100 101 do { 102 ResXMLParser::event_code_t code = 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 119bad: 120 jniThrowException(env, "org/xmlpull/v1/XmlPullParserException", 121 "Corrupt XML binary file"); 122 return ResXMLParser::BAD_DOCUMENT; 123} 124 125static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz, 126 jlong token) 127{ 128 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 129 if (st == NULL) { 130 return -1; 131 } 132 133 return static_cast<jint>(st->getElementNamespaceID()); 134} 135 136static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz, 137 jlong token) 138{ 139 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 140 if (st == NULL) { 141 return -1; 142 } 143 144 return static_cast<jint>(st->getElementNameID()); 145} 146 147static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz, 148 jlong token) 149{ 150 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 151 if (st == NULL) { 152 return -1; 153 } 154 155 return static_cast<jint>(st->getTextID()); 156} 157 158static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz, 159 jlong token) 160{ 161 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 162 if (st == NULL) { 163 jniThrowNullPointerException(env, NULL); 164 return 0; 165 } 166 167 return static_cast<jint>(st->getLineNumber()); 168} 169 170static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz, 171 jlong token) 172{ 173 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 174 if (st == NULL) { 175 jniThrowNullPointerException(env, NULL); 176 return 0; 177 } 178 179 return static_cast<jint>(st->getAttributeCount()); 180} 181 182static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz, 183 jlong token, jint idx) 184{ 185 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 186 if (st == NULL) { 187 jniThrowNullPointerException(env, NULL); 188 return 0; 189 } 190 191 return static_cast<jint>(st->getAttributeNamespaceID(idx)); 192} 193 194static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz, 195 jlong token, jint idx) 196{ 197 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 198 if (st == NULL) { 199 jniThrowNullPointerException(env, NULL); 200 return 0; 201 } 202 203 return static_cast<jint>(st->getAttributeNameID(idx)); 204} 205 206static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz, 207 jlong token, jint idx) 208{ 209 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 210 if (st == NULL) { 211 jniThrowNullPointerException(env, NULL); 212 return 0; 213 } 214 215 return static_cast<jint>(st->getAttributeNameResID(idx)); 216} 217 218static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz, 219 jlong token, jint idx) 220{ 221 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 222 if (st == NULL) { 223 jniThrowNullPointerException(env, NULL); 224 return 0; 225 } 226 227 return static_cast<jint>(st->getAttributeDataType(idx)); 228} 229 230static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz, 231 jlong token, jint idx) 232{ 233 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 234 if (st == NULL) { 235 jniThrowNullPointerException(env, NULL); 236 return 0; 237 } 238 239 return static_cast<jint>(st->getAttributeData(idx)); 240} 241 242static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz, 243 jlong token, jint idx) 244{ 245 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 246 if (st == NULL) { 247 jniThrowNullPointerException(env, NULL); 248 return 0; 249 } 250 251 return static_cast<jint>(st->getAttributeValueStringID(idx)); 252} 253 254static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz, 255 jlong token, 256 jstring ns, jstring name) 257{ 258 ResXMLParser* st = reinterpret_cast<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 = static_cast<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 284static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz, 285 jlong token) 286{ 287 ResXMLParser* st = reinterpret_cast<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 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; 295} 296 297static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz, 298 jlong token) 299{ 300 ResXMLParser* st = reinterpret_cast<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 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1; 308} 309 310static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz, 311 jlong token) 312{ 313 ResXMLParser* st = reinterpret_cast<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 334static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz, 335 jlong token) 336{ 337 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); 338 if (st == NULL) { 339 jniThrowNullPointerException(env, NULL); 340 return; 341 } 342 343 delete st; 344} 345 346static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz, 347 jlong token) 348{ 349 ResXMLTree* osb = reinterpret_cast<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 */ 363static JNINativeMethod gXmlBlockMethods[] = { 364 /* name, signature, funcPtr */ 365 { "nativeCreate", "([BII)J", 366 (void*) android_content_XmlBlock_nativeCreate }, 367 { "nativeGetStringBlock", "(J)J", 368 (void*) android_content_XmlBlock_nativeGetStringBlock }, 369 { "nativeCreateParseState", "(J)J", 370 (void*) android_content_XmlBlock_nativeCreateParseState }, 371 { "nativeNext", "(J)I", 372 (void*) android_content_XmlBlock_nativeNext }, 373 { "nativeGetNamespace", "(J)I", 374 (void*) android_content_XmlBlock_nativeGetNamespace }, 375 { "nativeGetName", "(J)I", 376 (void*) android_content_XmlBlock_nativeGetName }, 377 { "nativeGetText", "(J)I", 378 (void*) android_content_XmlBlock_nativeGetText }, 379 { "nativeGetLineNumber", "(J)I", 380 (void*) android_content_XmlBlock_nativeGetLineNumber }, 381 { "nativeGetAttributeCount", "(J)I", 382 (void*) android_content_XmlBlock_nativeGetAttributeCount }, 383 { "nativeGetAttributeNamespace","(JI)I", 384 (void*) android_content_XmlBlock_nativeGetAttributeNamespace }, 385 { "nativeGetAttributeName", "(JI)I", 386 (void*) android_content_XmlBlock_nativeGetAttributeName }, 387 { "nativeGetAttributeResource", "(JI)I", 388 (void*) android_content_XmlBlock_nativeGetAttributeResource }, 389 { "nativeGetAttributeDataType", "(JI)I", 390 (void*) android_content_XmlBlock_nativeGetAttributeDataType }, 391 { "nativeGetAttributeData", "(JI)I", 392 (void*) android_content_XmlBlock_nativeGetAttributeData }, 393 { "nativeGetAttributeStringValue", "(JI)I", 394 (void*) android_content_XmlBlock_nativeGetAttributeStringValue }, 395 { "nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I", 396 (void*) android_content_XmlBlock_nativeGetAttributeIndex }, 397 { "nativeGetIdAttribute", "(J)I", 398 (void*) android_content_XmlBlock_nativeGetIdAttribute }, 399 { "nativeGetClassAttribute", "(J)I", 400 (void*) android_content_XmlBlock_nativeGetClassAttribute }, 401 { "nativeGetStyleAttribute", "(J)I", 402 (void*) android_content_XmlBlock_nativeGetStyleAttribute }, 403 { "nativeDestroyParseState", "(J)V", 404 (void*) android_content_XmlBlock_nativeDestroyParseState }, 405 { "nativeDestroy", "(J)V", 406 (void*) android_content_XmlBlock_nativeDestroy }, 407}; 408 409int 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