android_util_XmlBlock.cpp revision de898ff42912bd7ca1bfb099cd439562496765a4
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();
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
62static 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
74static 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
94static 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
122bad:
123    jniThrowException(env, "org/xmlpull/v1/XmlPullParserException",
124            "Corrupt XML binary file");
125    return ResXMLParser::BAD_DOCUMENT;
126}
127
128static 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
139static 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
150static 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
161static 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
173static 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
185static 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
197static 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
209static 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
221static 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
233static 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
245static 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
257static 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 = env->GetStringChars(ns, NULL);
271        nsLen = env->GetStringLength(ns);
272    }
273
274    const char16_t* name16 = env->GetStringChars(name, NULL);
275    jsize nameLen = env->GetStringLength(name);
276
277    jint idx = static_cast<jint>(st->indexOfAttribute(ns16, nsLen, name16, nameLen));
278
279    if (ns) {
280        env->ReleaseStringChars(ns, ns16);
281    }
282    env->ReleaseStringChars(name, name16);
283
284    return idx;
285}
286
287static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz,
288                                                          jlong token)
289{
290    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
291    if (st == NULL) {
292        jniThrowNullPointerException(env, NULL);
293        return 0;
294    }
295
296    ssize_t idx = st->indexOfID();
297    return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1;
298}
299
300static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz,
301                                                             jlong token)
302{
303    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
304    if (st == NULL) {
305        jniThrowNullPointerException(env, NULL);
306        return 0;
307    }
308
309    ssize_t idx = st->indexOfClass();
310    return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1;
311}
312
313static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz,
314                                                             jlong token)
315{
316    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
317    if (st == NULL) {
318        jniThrowNullPointerException(env, NULL);
319        return 0;
320    }
321
322    ssize_t idx = st->indexOfStyle();
323    if (idx < 0) {
324        return 0;
325    }
326
327    Res_value value;
328    if (st->getAttributeValue(idx, &value) < 0) {
329        return 0;
330    }
331
332    return value.dataType == value.TYPE_REFERENCE
333        || value.dataType == value.TYPE_ATTRIBUTE
334        ? value.data : 0;
335}
336
337static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz,
338                                                          jlong token)
339{
340    ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
341    if (st == NULL) {
342        jniThrowNullPointerException(env, NULL);
343        return;
344    }
345
346    delete st;
347}
348
349static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz,
350                                                   jlong token)
351{
352    ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token);
353    if (osb == NULL) {
354        jniThrowNullPointerException(env, NULL);
355        return;
356    }
357
358    delete osb;
359}
360
361// ----------------------------------------------------------------------------
362
363/*
364 * JNI registration.
365 */
366static JNINativeMethod gXmlBlockMethods[] = {
367    /* name, signature, funcPtr */
368    { "nativeCreate",               "([BII)J",
369            (void*) android_content_XmlBlock_nativeCreate },
370    { "nativeGetStringBlock",       "(J)J",
371            (void*) android_content_XmlBlock_nativeGetStringBlock },
372    { "nativeCreateParseState",     "(J)J",
373            (void*) android_content_XmlBlock_nativeCreateParseState },
374    { "nativeNext",                 "(J)I",
375            (void*) android_content_XmlBlock_nativeNext },
376    { "nativeGetNamespace",         "(J)I",
377            (void*) android_content_XmlBlock_nativeGetNamespace },
378    { "nativeGetName",              "(J)I",
379            (void*) android_content_XmlBlock_nativeGetName },
380    { "nativeGetText",              "(J)I",
381            (void*) android_content_XmlBlock_nativeGetText },
382    { "nativeGetLineNumber",        "(J)I",
383            (void*) android_content_XmlBlock_nativeGetLineNumber },
384    { "nativeGetAttributeCount",    "(J)I",
385            (void*) android_content_XmlBlock_nativeGetAttributeCount },
386    { "nativeGetAttributeNamespace","(JI)I",
387            (void*) android_content_XmlBlock_nativeGetAttributeNamespace },
388    { "nativeGetAttributeName",     "(JI)I",
389            (void*) android_content_XmlBlock_nativeGetAttributeName },
390    { "nativeGetAttributeResource", "(JI)I",
391            (void*) android_content_XmlBlock_nativeGetAttributeResource },
392    { "nativeGetAttributeDataType", "(JI)I",
393            (void*) android_content_XmlBlock_nativeGetAttributeDataType },
394    { "nativeGetAttributeData",    "(JI)I",
395            (void*) android_content_XmlBlock_nativeGetAttributeData },
396    { "nativeGetAttributeStringValue", "(JI)I",
397            (void*) android_content_XmlBlock_nativeGetAttributeStringValue },
398    { "nativeGetAttributeIndex",    "(JLjava/lang/String;Ljava/lang/String;)I",
399            (void*) android_content_XmlBlock_nativeGetAttributeIndex },
400    { "nativeGetIdAttribute",      "(J)I",
401            (void*) android_content_XmlBlock_nativeGetIdAttribute },
402    { "nativeGetClassAttribute",   "(J)I",
403            (void*) android_content_XmlBlock_nativeGetClassAttribute },
404    { "nativeGetStyleAttribute",   "(J)I",
405            (void*) android_content_XmlBlock_nativeGetStyleAttribute },
406    { "nativeDestroyParseState",    "(J)V",
407            (void*) android_content_XmlBlock_nativeDestroyParseState },
408    { "nativeDestroy",              "(J)V",
409            (void*) android_content_XmlBlock_nativeDestroy },
410};
411
412int register_android_content_XmlBlock(JNIEnv* env)
413{
414    return AndroidRuntime::registerNativeMethods(env,
415            "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods));
416}
417
418}; // namespace android
419