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 "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