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