• 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 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 
android_content_XmlBlock_nativeGetStringBlock(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeCreateParseState(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeNext(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetNamespace(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetName(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetText(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetLineNumber(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetAttributeCount(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv * env,jobject clazz,jint token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeName(JNIEnv * env,jobject clazz,jint token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeResource(JNIEnv * env,jobject clazz,jint token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv * env,jobject clazz,jint token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeData(JNIEnv * env,jobject clazz,jint token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv * env,jobject clazz,jint token,jint idx)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 
android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv * env,jobject clazz,jint token,jstring ns,jstring name)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 
android_content_XmlBlock_nativeGetIdAttribute(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetClassAttribute(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeDestroyParseState(JNIEnv * env,jobject clazz,jint token)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 
android_content_XmlBlock_nativeDestroy(JNIEnv * env,jobject clazz,jint token)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 
register_android_content_XmlBlock(JNIEnv * env)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