blob: 8887fdcfd989c5cc7b785b1cced9e91b0d2ed227 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //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
30namespace android {
31
32// ----------------------------------------------------------------------------
33
34static 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
44static 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
71static 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
83static 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
103static 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
129bad:
130 doThrow(env, "org/xmlpull/v1/XmlPullParserException",
131 "Corrupt XML binary file");
132 return ResXMLParser::BAD_DOCUMENT;
133}
134
135static 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
146static 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
157static 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
168static 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
180static 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
192static 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
204static 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
216static 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
228static 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
240static 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
252static 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
264static 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
294static 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
307static 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
320static 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
344static 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
356static 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 */
373static 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
419int 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