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 <nativehelper/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,jint res_id)74 static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz,
75 jlong token, jint res_id)
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->setSourceResourceId(res_id);
90 st->restart();
91
92 return reinterpret_cast<jlong>(st);
93 }
94
android_content_XmlBlock_nativeNext(JNIEnv * env,jobject clazz,jlong token)95 static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz,
96 jlong token)
97 {
98 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
99 if (st == NULL) {
100 return ResXMLParser::END_DOCUMENT;
101 }
102
103 do {
104 ResXMLParser::event_code_t code = st->next();
105 switch (code) {
106 case ResXMLParser::START_TAG:
107 return 2;
108 case ResXMLParser::END_TAG:
109 return 3;
110 case ResXMLParser::TEXT:
111 return 4;
112 case ResXMLParser::START_DOCUMENT:
113 return 0;
114 case ResXMLParser::END_DOCUMENT:
115 return 1;
116 case ResXMLParser::BAD_DOCUMENT:
117 goto bad;
118 default:
119 break;
120 }
121 } while (true);
122
123 bad:
124 jniThrowException(env, "org/xmlpull/v1/XmlPullParserException",
125 "Corrupt XML binary file");
126 return ResXMLParser::BAD_DOCUMENT;
127 }
128
android_content_XmlBlock_nativeGetNamespace(JNIEnv * env,jobject clazz,jlong token)129 static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz,
130 jlong token)
131 {
132 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
133 if (st == NULL) {
134 return -1;
135 }
136
137 return static_cast<jint>(st->getElementNamespaceID());
138 }
139
android_content_XmlBlock_nativeGetName(JNIEnv * env,jobject clazz,jlong token)140 static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz,
141 jlong token)
142 {
143 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
144 if (st == NULL) {
145 return -1;
146 }
147
148 return static_cast<jint>(st->getElementNameID());
149 }
150
android_content_XmlBlock_nativeGetText(JNIEnv * env,jobject clazz,jlong token)151 static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz,
152 jlong token)
153 {
154 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
155 if (st == NULL) {
156 return -1;
157 }
158
159 return static_cast<jint>(st->getTextID());
160 }
161
android_content_XmlBlock_nativeGetLineNumber(JNIEnv * env,jobject clazz,jlong token)162 static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz,
163 jlong token)
164 {
165 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
166 if (st == NULL) {
167 jniThrowNullPointerException(env, NULL);
168 return 0;
169 }
170
171 return static_cast<jint>(st->getLineNumber());
172 }
173
android_content_XmlBlock_nativeGetAttributeCount(JNIEnv * env,jobject clazz,jlong token)174 static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz,
175 jlong token)
176 {
177 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
178 if (st == NULL) {
179 jniThrowNullPointerException(env, NULL);
180 return 0;
181 }
182
183 return static_cast<jint>(st->getAttributeCount());
184 }
185
android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv * env,jobject clazz,jlong token,jint idx)186 static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz,
187 jlong token, jint idx)
188 {
189 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
190 if (st == NULL) {
191 jniThrowNullPointerException(env, NULL);
192 return 0;
193 }
194
195 return static_cast<jint>(st->getAttributeNamespaceID(idx));
196 }
197
android_content_XmlBlock_nativeGetAttributeName(JNIEnv * env,jobject clazz,jlong token,jint idx)198 static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz,
199 jlong token, jint idx)
200 {
201 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
202 if (st == NULL) {
203 jniThrowNullPointerException(env, NULL);
204 return 0;
205 }
206
207 return static_cast<jint>(st->getAttributeNameID(idx));
208 }
209
android_content_XmlBlock_nativeGetAttributeResource(JNIEnv * env,jobject clazz,jlong token,jint idx)210 static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz,
211 jlong token, jint idx)
212 {
213 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
214 if (st == NULL) {
215 jniThrowNullPointerException(env, NULL);
216 return 0;
217 }
218
219 return static_cast<jint>(st->getAttributeNameResID(idx));
220 }
221
android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv * env,jobject clazz,jlong token,jint idx)222 static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz,
223 jlong token, jint idx)
224 {
225 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
226 if (st == NULL) {
227 jniThrowNullPointerException(env, NULL);
228 return 0;
229 }
230
231 return static_cast<jint>(st->getAttributeDataType(idx));
232 }
233
android_content_XmlBlock_nativeGetAttributeData(JNIEnv * env,jobject clazz,jlong token,jint idx)234 static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz,
235 jlong token, jint idx)
236 {
237 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
238 if (st == NULL) {
239 jniThrowNullPointerException(env, NULL);
240 return 0;
241 }
242
243 return static_cast<jint>(st->getAttributeData(idx));
244 }
245
android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv * env,jobject clazz,jlong token,jint idx)246 static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz,
247 jlong token, jint idx)
248 {
249 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
250 if (st == NULL) {
251 jniThrowNullPointerException(env, NULL);
252 return 0;
253 }
254
255 return static_cast<jint>(st->getAttributeValueStringID(idx));
256 }
257
android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv * env,jobject clazz,jlong token,jstring ns,jstring name)258 static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz,
259 jlong token,
260 jstring ns, jstring name)
261 {
262 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
263 if (st == NULL || name == NULL) {
264 jniThrowNullPointerException(env, NULL);
265 return 0;
266 }
267
268 const char16_t* ns16 = NULL;
269 jsize nsLen = 0;
270 if (ns) {
271 ns16 = reinterpret_cast<const char16_t*>(env->GetStringChars(ns, NULL));
272 nsLen = env->GetStringLength(ns);
273 }
274
275 const char16_t* name16 = reinterpret_cast<const char16_t*>(
276 env->GetStringChars(name, NULL));
277 jsize nameLen = env->GetStringLength(name);
278
279 jint idx = static_cast<jint>(st->indexOfAttribute(ns16, nsLen, name16, nameLen));
280
281 if (ns) {
282 env->ReleaseStringChars(ns, reinterpret_cast<const jchar*>(ns16));
283 }
284 env->ReleaseStringChars(name, reinterpret_cast<const jchar*>(name16));
285
286 return idx;
287 }
288
android_content_XmlBlock_nativeGetIdAttribute(JNIEnv * env,jobject clazz,jlong token)289 static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz,
290 jlong token)
291 {
292 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
293 if (st == NULL) {
294 jniThrowNullPointerException(env, NULL);
295 return 0;
296 }
297
298 ssize_t idx = st->indexOfID();
299 return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1;
300 }
301
android_content_XmlBlock_nativeGetClassAttribute(JNIEnv * env,jobject clazz,jlong token)302 static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz,
303 jlong token)
304 {
305 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
306 if (st == NULL) {
307 jniThrowNullPointerException(env, NULL);
308 return 0;
309 }
310
311 ssize_t idx = st->indexOfClass();
312 return idx >= 0 ? static_cast<jint>(st->getAttributeValueStringID(idx)) : -1;
313 }
314
android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv * env,jobject clazz,jlong token)315 static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz,
316 jlong token)
317 {
318 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
319 if (st == NULL) {
320 jniThrowNullPointerException(env, NULL);
321 return 0;
322 }
323
324 ssize_t idx = st->indexOfStyle();
325 if (idx < 0) {
326 return 0;
327 }
328
329 Res_value value;
330 if (st->getAttributeValue(idx, &value) < 0) {
331 return 0;
332 }
333
334 return value.dataType == value.TYPE_REFERENCE
335 || value.dataType == value.TYPE_ATTRIBUTE
336 ? value.data : 0;
337 }
338
android_content_XmlBlock_nativeGetSourceResId(JNIEnv * env,jobject clazz,jlong token)339 static jint android_content_XmlBlock_nativeGetSourceResId(JNIEnv* env, jobject clazz,
340 jlong token)
341 {
342 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
343 if (st == NULL) {
344 return 0;
345 } else {
346 return st->getSourceResourceId();
347 }
348 }
349
android_content_XmlBlock_nativeDestroyParseState(JNIEnv * env,jobject clazz,jlong token)350 static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz,
351 jlong token)
352 {
353 ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token);
354 if (st == NULL) {
355 jniThrowNullPointerException(env, NULL);
356 return;
357 }
358
359 delete st;
360 }
361
android_content_XmlBlock_nativeDestroy(JNIEnv * env,jobject clazz,jlong token)362 static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz,
363 jlong token)
364 {
365 ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token);
366 if (osb == NULL) {
367 jniThrowNullPointerException(env, NULL);
368 return;
369 }
370
371 delete osb;
372 }
373
374 // ----------------------------------------------------------------------------
375
376 /*
377 * JNI registration.
378 */
379 static const JNINativeMethod gXmlBlockMethods[] = {
380 /* name, signature, funcPtr */
381 { "nativeCreate", "([BII)J",
382 (void*) android_content_XmlBlock_nativeCreate },
383 { "nativeGetStringBlock", "(J)J",
384 (void*) android_content_XmlBlock_nativeGetStringBlock },
385 { "nativeCreateParseState", "(JI)J",
386 (void*) android_content_XmlBlock_nativeCreateParseState },
387 { "nativeDestroyParseState", "(J)V",
388 (void*) android_content_XmlBlock_nativeDestroyParseState },
389 { "nativeDestroy", "(J)V",
390 (void*) android_content_XmlBlock_nativeDestroy },
391
392 // ------------------- @FastNative ----------------------
393
394 { "nativeNext", "(J)I",
395 (void*) android_content_XmlBlock_nativeNext },
396 { "nativeGetNamespace", "(J)I",
397 (void*) android_content_XmlBlock_nativeGetNamespace },
398 { "nativeGetName", "(J)I",
399 (void*) android_content_XmlBlock_nativeGetName },
400 { "nativeGetText", "(J)I",
401 (void*) android_content_XmlBlock_nativeGetText },
402 { "nativeGetLineNumber", "(J)I",
403 (void*) android_content_XmlBlock_nativeGetLineNumber },
404 { "nativeGetAttributeCount", "(J)I",
405 (void*) android_content_XmlBlock_nativeGetAttributeCount },
406 { "nativeGetAttributeNamespace","(JI)I",
407 (void*) android_content_XmlBlock_nativeGetAttributeNamespace },
408 { "nativeGetAttributeName", "(JI)I",
409 (void*) android_content_XmlBlock_nativeGetAttributeName },
410 { "nativeGetAttributeResource", "(JI)I",
411 (void*) android_content_XmlBlock_nativeGetAttributeResource },
412 { "nativeGetAttributeDataType", "(JI)I",
413 (void*) android_content_XmlBlock_nativeGetAttributeDataType },
414 { "nativeGetAttributeData", "(JI)I",
415 (void*) android_content_XmlBlock_nativeGetAttributeData },
416 { "nativeGetAttributeStringValue", "(JI)I",
417 (void*) android_content_XmlBlock_nativeGetAttributeStringValue },
418 { "nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I",
419 (void*) android_content_XmlBlock_nativeGetAttributeIndex },
420 { "nativeGetIdAttribute", "(J)I",
421 (void*) android_content_XmlBlock_nativeGetIdAttribute },
422 { "nativeGetClassAttribute", "(J)I",
423 (void*) android_content_XmlBlock_nativeGetClassAttribute },
424 { "nativeGetStyleAttribute", "(J)I",
425 (void*) android_content_XmlBlock_nativeGetStyleAttribute },
426 { "nativeGetSourceResId", "(J)I",
427 (void*) android_content_XmlBlock_nativeGetSourceResId},
428 };
429
register_android_content_XmlBlock(JNIEnv * env)430 int register_android_content_XmlBlock(JNIEnv* env)
431 {
432 return RegisterMethodsOrDie(env,
433 "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods));
434 }
435
436 }; // namespace android
437