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