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 <utils/misc.h>
22 #include <android_runtime/AndroidRuntime.h>
23 #include <utils/AssetManager.h>
24 #include <utils/Log.h>
25
26 #include <utils/ResourceTypes.h>
27
28 #include <stdio.h>
29
30 namespace android {
31
32 // ----------------------------------------------------------------------------
33
doThrow(JNIEnv * env,const char * exc,const char * msg=NULL)34 static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
35 {
36 jclass npeClazz;
37
38 npeClazz = env->FindClass(exc);
39 LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc);
40
41 env->ThrowNew(npeClazz, msg);
42 }
43
android_content_XmlBlock_nativeCreate(JNIEnv * env,jobject clazz,jbyteArray bArray,jint off,jint len)44 static jint android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz,
45 jbyteArray bArray,
46 jint off, jint len)
47 {
48 if (bArray == NULL) {
49 doThrow(env, "java/lang/NullPointerException");
50 return 0;
51 }
52
53 jsize bLen = env->GetArrayLength(bArray);
54 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
55 doThrow(env, "java/lang/IndexOutOfBoundsException");
56 return 0;
57 }
58
59 jbyte* b = env->GetByteArrayElements(bArray, NULL);
60 ResXMLTree* osb = new ResXMLTree(b+off, len, true);
61 env->ReleaseByteArrayElements(bArray, b, 0);
62
63 if (osb == NULL || osb->getError() != NO_ERROR) {
64 doThrow(env, "java/lang/IllegalArgumentException");
65 return 0;
66 }
67
68 return (jint)osb;
69 }
70
android_content_XmlBlock_nativeGetStringBlock(JNIEnv * env,jobject clazz,jint token)71 static jint android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz,
72 jint token)
73 {
74 ResXMLTree* osb = (ResXMLTree*)token;
75 if (osb == NULL) {
76 doThrow(env, "java/lang/NullPointerException");
77 return 0;
78 }
79
80 return (jint)&osb->getStrings();
81 }
82
android_content_XmlBlock_nativeCreateParseState(JNIEnv * env,jobject clazz,jint token)83 static jint android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz,
84 jint token)
85 {
86 ResXMLTree* osb = (ResXMLTree*)token;
87 if (osb == NULL) {
88 doThrow(env, "java/lang/NullPointerException");
89 return 0;
90 }
91
92 ResXMLParser* st = new ResXMLParser(*osb);
93 if (st == NULL) {
94 doThrow(env, "java/lang/OutOfMemoryError");
95 return 0;
96 }
97
98 st->restart();
99
100 return (jint)st;
101 }
102
android_content_XmlBlock_nativeNext(JNIEnv * env,jobject clazz,jint token)103 static jint android_content_XmlBlock_nativeNext(JNIEnv* env, jobject clazz,
104 jint token)
105 {
106 ResXMLParser* st = (ResXMLParser*)token;
107 if (st == NULL) {
108 return ResXMLParser::END_DOCUMENT;
109 }
110
111 do {
112 jint code = (jint)st->next();
113 switch (code) {
114 case ResXMLParser::START_TAG:
115 return 2;
116 case ResXMLParser::END_TAG:
117 return 3;
118 case ResXMLParser::TEXT:
119 return 4;
120 case ResXMLParser::START_DOCUMENT:
121 return 0;
122 case ResXMLParser::END_DOCUMENT:
123 return 1;
124 case ResXMLParser::BAD_DOCUMENT:
125 goto bad;
126 }
127 } while (true);
128
129 bad:
130 doThrow(env, "org/xmlpull/v1/XmlPullParserException",
131 "Corrupt XML binary file");
132 return ResXMLParser::BAD_DOCUMENT;
133 }
134
android_content_XmlBlock_nativeGetNamespace(JNIEnv * env,jobject clazz,jint token)135 static jint android_content_XmlBlock_nativeGetNamespace(JNIEnv* env, jobject clazz,
136 jint token)
137 {
138 ResXMLParser* st = (ResXMLParser*)token;
139 if (st == NULL) {
140 return -1;
141 }
142
143 return (jint)st->getElementNamespaceID();
144 }
145
android_content_XmlBlock_nativeGetName(JNIEnv * env,jobject clazz,jint token)146 static jint android_content_XmlBlock_nativeGetName(JNIEnv* env, jobject clazz,
147 jint token)
148 {
149 ResXMLParser* st = (ResXMLParser*)token;
150 if (st == NULL) {
151 return -1;
152 }
153
154 return (jint)st->getElementNameID();
155 }
156
android_content_XmlBlock_nativeGetText(JNIEnv * env,jobject clazz,jint token)157 static jint android_content_XmlBlock_nativeGetText(JNIEnv* env, jobject clazz,
158 jint token)
159 {
160 ResXMLParser* st = (ResXMLParser*)token;
161 if (st == NULL) {
162 return -1;
163 }
164
165 return (jint)st->getTextID();
166 }
167
android_content_XmlBlock_nativeGetLineNumber(JNIEnv * env,jobject clazz,jint token)168 static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz,
169 jint token)
170 {
171 ResXMLParser* st = (ResXMLParser*)token;
172 if (st == NULL) {
173 doThrow(env, "java/lang/NullPointerException");
174 return 0;
175 }
176
177 return (jint)st->getLineNumber();
178 }
179
android_content_XmlBlock_nativeGetAttributeCount(JNIEnv * env,jobject clazz,jint token)180 static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz,
181 jint token)
182 {
183 ResXMLParser* st = (ResXMLParser*)token;
184 if (st == NULL) {
185 doThrow(env, "java/lang/NullPointerException");
186 return 0;
187 }
188
189 return (jint)st->getAttributeCount();
190 }
191
android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv * env,jobject clazz,jint token,jint idx)192 static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz,
193 jint token, jint idx)
194 {
195 ResXMLParser* st = (ResXMLParser*)token;
196 if (st == NULL) {
197 doThrow(env, "java/lang/NullPointerException");
198 return 0;
199 }
200
201 return (jint)st->getAttributeNamespaceID(idx);
202 }
203
android_content_XmlBlock_nativeGetAttributeName(JNIEnv * env,jobject clazz,jint token,jint idx)204 static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz,
205 jint token, jint idx)
206 {
207 ResXMLParser* st = (ResXMLParser*)token;
208 if (st == NULL) {
209 doThrow(env, "java/lang/NullPointerException");
210 return 0;
211 }
212
213 return (jint)st->getAttributeNameID(idx);
214 }
215
android_content_XmlBlock_nativeGetAttributeResource(JNIEnv * env,jobject clazz,jint token,jint idx)216 static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz,
217 jint token, jint idx)
218 {
219 ResXMLParser* st = (ResXMLParser*)token;
220 if (st == NULL) {
221 doThrow(env, "java/lang/NullPointerException");
222 return 0;
223 }
224
225 return (jint)st->getAttributeNameResID(idx);
226 }
227
android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv * env,jobject clazz,jint token,jint idx)228 static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz,
229 jint token, jint idx)
230 {
231 ResXMLParser* st = (ResXMLParser*)token;
232 if (st == NULL) {
233 doThrow(env, "java/lang/NullPointerException");
234 return 0;
235 }
236
237 return (jint)st->getAttributeDataType(idx);
238 }
239
android_content_XmlBlock_nativeGetAttributeData(JNIEnv * env,jobject clazz,jint token,jint idx)240 static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz,
241 jint token, jint idx)
242 {
243 ResXMLParser* st = (ResXMLParser*)token;
244 if (st == NULL) {
245 doThrow(env, "java/lang/NullPointerException");
246 return 0;
247 }
248
249 return (jint)st->getAttributeData(idx);
250 }
251
android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv * env,jobject clazz,jint token,jint idx)252 static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz,
253 jint token, jint idx)
254 {
255 ResXMLParser* st = (ResXMLParser*)token;
256 if (st == NULL) {
257 doThrow(env, "java/lang/NullPointerException");
258 return 0;
259 }
260
261 return (jint)st->getAttributeValueStringID(idx);
262 }
263
android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv * env,jobject clazz,jint token,jstring ns,jstring name)264 static jint android_content_XmlBlock_nativeGetAttributeIndex(JNIEnv* env, jobject clazz,
265 jint token,
266 jstring ns, jstring name)
267 {
268 ResXMLParser* st = (ResXMLParser*)token;
269 if (st == NULL || name == NULL) {
270 doThrow(env, "java/lang/NullPointerException");
271 return 0;
272 }
273
274 const char16_t* ns16 = NULL;
275 jsize nsLen = 0;
276 if (ns) {
277 ns16 = env->GetStringChars(ns, NULL);
278 nsLen = env->GetStringLength(ns);
279 }
280
281 const char16_t* name16 = env->GetStringChars(name, NULL);
282 jsize nameLen = env->GetStringLength(name);
283
284 jint idx = (jint)st->indexOfAttribute(ns16, nsLen, name16, nameLen);
285
286 if (ns) {
287 env->ReleaseStringChars(ns, ns16);
288 }
289 env->ReleaseStringChars(name, name16);
290
291 return idx;
292 }
293
android_content_XmlBlock_nativeGetIdAttribute(JNIEnv * env,jobject clazz,jint token)294 static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz,
295 jint token)
296 {
297 ResXMLParser* st = (ResXMLParser*)token;
298 if (st == NULL) {
299 doThrow(env, "java/lang/NullPointerException");
300 return 0;
301 }
302
303 ssize_t idx = st->indexOfID();
304 return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
305 }
306
android_content_XmlBlock_nativeGetClassAttribute(JNIEnv * env,jobject clazz,jint token)307 static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz,
308 jint token)
309 {
310 ResXMLParser* st = (ResXMLParser*)token;
311 if (st == NULL) {
312 doThrow(env, "java/lang/NullPointerException");
313 return 0;
314 }
315
316 ssize_t idx = st->indexOfClass();
317 return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
318 }
319
android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv * env,jobject clazz,jint token)320 static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz,
321 jint token)
322 {
323 ResXMLParser* st = (ResXMLParser*)token;
324 if (st == NULL) {
325 doThrow(env, "java/lang/NullPointerException");
326 return 0;
327 }
328
329 ssize_t idx = st->indexOfStyle();
330 if (idx < 0) {
331 return 0;
332 }
333
334 Res_value value;
335 if (st->getAttributeValue(idx, &value) < 0) {
336 return 0;
337 }
338
339 return value.dataType == value.TYPE_REFERENCE
340 || value.dataType == value.TYPE_ATTRIBUTE
341 ? value.data : 0;
342 }
343
android_content_XmlBlock_nativeDestroyParseState(JNIEnv * env,jobject clazz,jint token)344 static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz,
345 jint token)
346 {
347 ResXMLParser* st = (ResXMLParser*)token;
348 if (st == NULL) {
349 doThrow(env, "java/lang/NullPointerException");
350 return;
351 }
352
353 delete st;
354 }
355
android_content_XmlBlock_nativeDestroy(JNIEnv * env,jobject clazz,jint token)356 static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz,
357 jint token)
358 {
359 ResXMLTree* osb = (ResXMLTree*)token;
360 if (osb == NULL) {
361 doThrow(env, "java/lang/NullPointerException");
362 return;
363 }
364
365 delete osb;
366 }
367
368 // ----------------------------------------------------------------------------
369
370 /*
371 * JNI registration.
372 */
373 static JNINativeMethod gXmlBlockMethods[] = {
374 /* name, signature, funcPtr */
375 { "nativeCreate", "([BII)I",
376 (void*) android_content_XmlBlock_nativeCreate },
377 { "nativeGetStringBlock", "(I)I",
378 (void*) android_content_XmlBlock_nativeGetStringBlock },
379 { "nativeCreateParseState", "(I)I",
380 (void*) android_content_XmlBlock_nativeCreateParseState },
381 { "nativeNext", "(I)I",
382 (void*) android_content_XmlBlock_nativeNext },
383 { "nativeGetNamespace", "(I)I",
384 (void*) android_content_XmlBlock_nativeGetNamespace },
385 { "nativeGetName", "(I)I",
386 (void*) android_content_XmlBlock_nativeGetName },
387 { "nativeGetText", "(I)I",
388 (void*) android_content_XmlBlock_nativeGetText },
389 { "nativeGetLineNumber", "(I)I",
390 (void*) android_content_XmlBlock_nativeGetLineNumber },
391 { "nativeGetAttributeCount", "(I)I",
392 (void*) android_content_XmlBlock_nativeGetAttributeCount },
393 { "nativeGetAttributeNamespace","(II)I",
394 (void*) android_content_XmlBlock_nativeGetAttributeNamespace },
395 { "nativeGetAttributeName", "(II)I",
396 (void*) android_content_XmlBlock_nativeGetAttributeName },
397 { "nativeGetAttributeResource", "(II)I",
398 (void*) android_content_XmlBlock_nativeGetAttributeResource },
399 { "nativeGetAttributeDataType", "(II)I",
400 (void*) android_content_XmlBlock_nativeGetAttributeDataType },
401 { "nativeGetAttributeData", "(II)I",
402 (void*) android_content_XmlBlock_nativeGetAttributeData },
403 { "nativeGetAttributeStringValue", "(II)I",
404 (void*) android_content_XmlBlock_nativeGetAttributeStringValue },
405 { "nativeGetAttributeIndex", "(ILjava/lang/String;Ljava/lang/String;)I",
406 (void*) android_content_XmlBlock_nativeGetAttributeIndex },
407 { "nativeGetIdAttribute", "(I)I",
408 (void*) android_content_XmlBlock_nativeGetIdAttribute },
409 { "nativeGetClassAttribute", "(I)I",
410 (void*) android_content_XmlBlock_nativeGetClassAttribute },
411 { "nativeGetStyleAttribute", "(I)I",
412 (void*) android_content_XmlBlock_nativeGetStyleAttribute },
413 { "nativeDestroyParseState", "(I)V",
414 (void*) android_content_XmlBlock_nativeDestroyParseState },
415 { "nativeDestroy", "(I)V",
416 (void*) android_content_XmlBlock_nativeDestroy },
417 };
418
register_android_content_XmlBlock(JNIEnv * env)419 int register_android_content_XmlBlock(JNIEnv* env)
420 {
421 return AndroidRuntime::registerNativeMethods(env,
422 "android/content/res/XmlBlock", gXmlBlockMethods, NELEM(gXmlBlockMethods));
423 }
424
425 }; // namespace android
426
427