• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
android_content_XmlBlock_nativeCreate(JNIEnv * env,jobject clazz,jbyteArray bArray,jint off,jint len)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 
android_content_XmlBlock_nativeGetStringBlock(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeCreateParseState(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeNext(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeGetNamespace(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeGetName(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeGetText(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeGetLineNumber(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeGetAttributeCount(JNIEnv * env,jobject clazz,jlong token)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 
android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv * env,jobject clazz,jlong token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeName(JNIEnv * env,jobject clazz,jlong token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeResource(JNIEnv * env,jobject clazz,jlong token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv * env,jobject clazz,jlong token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeData(JNIEnv * env,jobject clazz,jlong token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv * env,jobject clazz,jlong token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv * env,jobject clazz,jlong token,jstring ns,jstring name)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 = 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 
android_content_XmlBlock_nativeGetIdAttribute(JNIEnv * env,jobject clazz,jlong token)287 static 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 
android_content_XmlBlock_nativeGetClassAttribute(JNIEnv * env,jobject clazz,jlong token)300 static 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 
android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv * env,jobject clazz,jlong token)313 static 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 
android_content_XmlBlock_nativeDestroyParseState(JNIEnv * env,jobject clazz,jlong token)337 static 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 
android_content_XmlBlock_nativeDestroy(JNIEnv * env,jobject clazz,jlong token)349 static 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  */
366 static 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 
register_android_content_XmlBlock(JNIEnv * env)412 int 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