Home | History | Annotate | Download | only in jni
      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