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