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