blob: ad6033b1c175965dd2d56db66268625c73d0d70c [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**
Elliott Hughes8451b252011-04-07 19:17:57 -07005** 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes8451b252011-04-07 19:17:57 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes8451b252011-04-07 19:17:57 -070011** 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
18#define LOG_TAG "XmlBlock"
19
20#include "jni.h"
Elliott Hughes8451b252011-04-07 19:17:57 -070021#include "JNIHelp.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022#include <android_runtime/AndroidRuntime.h>
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080023#include <androidfw/AssetManager.h>
24#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025#include <utils/Log.h>
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080026#include <utils/misc.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
28#include <stdio.h>
29
30namespace android {
31
32// ----------------------------------------------------------------------------
33
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034static jint android_content_XmlBlock_nativeCreate(JNIEnv* env, jobject clazz,
35 jbyteArray bArray,
36 jint off, jint len)
37{
38 if (bArray == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070039 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040 return 0;
41 }
42
43 jsize bLen = env->GetArrayLength(bArray);
44 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Elliott Hughes8451b252011-04-07 19:17:57 -070045 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046 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) {
Elliott Hughes8451b252011-04-07 19:17:57 -070054 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 return 0;
56 }
57
58 return (jint)osb;
59}
60
61static jint android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject clazz,
62 jint token)
63{
64 ResXMLTree* osb = (ResXMLTree*)token;
65 if (osb == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070066 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 return 0;
68 }
69
70 return (jint)&osb->getStrings();
71}
72
73static jint android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz,
74 jint token)
75{
76 ResXMLTree* osb = (ResXMLTree*)token;
77 if (osb == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070078 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 return 0;
80 }
81
82 ResXMLParser* st = new ResXMLParser(*osb);
83 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -070084 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 return 0;
86 }
87
88 st->restart();
89
90 return (jint)st;
91}
92
93static 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);
Elliott Hughes8451b252011-04-07 19:17:57 -0700118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119bad:
Elliott Hughes8451b252011-04-07 19:17:57 -0700120 jniThrowException(env, "org/xmlpull/v1/XmlPullParserException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 "Corrupt XML binary file");
122 return ResXMLParser::BAD_DOCUMENT;
123}
124
125static 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 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 return (jint)st->getElementNamespaceID();
134}
135
136static 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
147static 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
158static jint android_content_XmlBlock_nativeGetLineNumber(JNIEnv* env, jobject clazz,
159 jint token)
160{
161 ResXMLParser* st = (ResXMLParser*)token;
162 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700163 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 return 0;
165 }
166
167 return (jint)st->getLineNumber();
168}
169
170static jint android_content_XmlBlock_nativeGetAttributeCount(JNIEnv* env, jobject clazz,
171 jint token)
172{
173 ResXMLParser* st = (ResXMLParser*)token;
174 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700175 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 return 0;
177 }
178
179 return (jint)st->getAttributeCount();
180}
181
182static jint android_content_XmlBlock_nativeGetAttributeNamespace(JNIEnv* env, jobject clazz,
183 jint token, jint idx)
184{
185 ResXMLParser* st = (ResXMLParser*)token;
186 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700187 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 return 0;
189 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 return (jint)st->getAttributeNamespaceID(idx);
192}
193
194static jint android_content_XmlBlock_nativeGetAttributeName(JNIEnv* env, jobject clazz,
195 jint token, jint idx)
196{
197 ResXMLParser* st = (ResXMLParser*)token;
198 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700199 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 return 0;
201 }
202
203 return (jint)st->getAttributeNameID(idx);
204}
205
206static jint android_content_XmlBlock_nativeGetAttributeResource(JNIEnv* env, jobject clazz,
207 jint token, jint idx)
208{
209 ResXMLParser* st = (ResXMLParser*)token;
210 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700211 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 return 0;
213 }
214
215 return (jint)st->getAttributeNameResID(idx);
216}
217
218static jint android_content_XmlBlock_nativeGetAttributeDataType(JNIEnv* env, jobject clazz,
219 jint token, jint idx)
220{
221 ResXMLParser* st = (ResXMLParser*)token;
222 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700223 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 return 0;
225 }
226
227 return (jint)st->getAttributeDataType(idx);
228}
229
230static jint android_content_XmlBlock_nativeGetAttributeData(JNIEnv* env, jobject clazz,
231 jint token, jint idx)
232{
233 ResXMLParser* st = (ResXMLParser*)token;
234 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700235 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 return 0;
237 }
238
239 return (jint)st->getAttributeData(idx);
240}
241
242static jint android_content_XmlBlock_nativeGetAttributeStringValue(JNIEnv* env, jobject clazz,
243 jint token, jint idx)
244{
245 ResXMLParser* st = (ResXMLParser*)token;
246 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700247 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 return 0;
249 }
250
251 return (jint)st->getAttributeValueStringID(idx);
252}
253
254static 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) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700260 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 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 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 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
284static jint android_content_XmlBlock_nativeGetIdAttribute(JNIEnv* env, jobject clazz,
285 jint token)
286{
287 ResXMLParser* st = (ResXMLParser*)token;
288 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700289 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 return 0;
291 }
292
293 ssize_t idx = st->indexOfID();
294 return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
295}
296
297static jint android_content_XmlBlock_nativeGetClassAttribute(JNIEnv* env, jobject clazz,
298 jint token)
299{
300 ResXMLParser* st = (ResXMLParser*)token;
301 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700302 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 return 0;
304 }
Elliott Hughes8451b252011-04-07 19:17:57 -0700305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 ssize_t idx = st->indexOfClass();
307 return idx >= 0 ? (jint)st->getAttributeValueStringID(idx) : -1;
308}
309
310static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobject clazz,
311 jint token)
312{
313 ResXMLParser* st = (ResXMLParser*)token;
314 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700315 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 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
Elliott Hughes8451b252011-04-07 19:17:57 -0700329 return value.dataType == value.TYPE_REFERENCE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 || value.dataType == value.TYPE_ATTRIBUTE
331 ? value.data : 0;
332}
333
334static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz,
335 jint token)
336{
337 ResXMLParser* st = (ResXMLParser*)token;
338 if (st == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700339 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 return;
341 }
342
343 delete st;
344}
345
346static void android_content_XmlBlock_nativeDestroy(JNIEnv* env, jobject clazz,
347 jint token)
348{
349 ResXMLTree* osb = (ResXMLTree*)token;
350 if (osb == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700351 jniThrowNullPointerException(env, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 return;
353 }
354
355 delete osb;
356}
357
358// ----------------------------------------------------------------------------
359
360/*
361 * JNI registration.
362 */
363static 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
409int 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