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