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