OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / core / jni / android_util_XmlBlock.cpp
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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