1 /* xmlj_util.c
2 Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 #include "xmlj_util.h"
39 #include "xmlj_error.h"
40 #include <libxml/tree.h>
41 #include <unistd.h>
42 #include <jcl.h>
43
44 /* xmlChar->jstring cache */
45 #ifdef XMLJ_STRING_CACHE
46 #define XMLJ_STRING_CACHE_SIZE 1024
47 xmlHashTablePtr xmljStringCache = NULL;
48
49 void
50 xmljHashDeallocate (void *data, xmlChar *name);
51
52 void
xmljHashDeallocate(void * data,xmlChar * name)53 xmljHashDeallocate (void *data, xmlChar *name)
54 {
55 /* NOOP */
56 }
57 #endif /* XMLJ_STRING_CACHE */
58
59 jstring
xmljNewString(JNIEnv * env,const xmlChar * text)60 xmljNewString (JNIEnv * env, const xmlChar * text)
61 {
62 jstring ret;
63
64 if (text == NULL || (*env)->ExceptionOccurred (env))
65 {
66 return NULL;
67 }
68 #ifdef XMLJ_STRING_CACHE
69 if (xmljStringCache == NULL) /* Init cache */
70 {
71 xmljStringCache = xmlHashCreate (XMLJ_STRING_CACHE_SIZE);
72 }
73 ret = (jstring) xmlHashLookup (xmljStringCache, text);
74 if (ret == NULL)
75 {
76 ret = (*env)->NewStringUTF (env, (char *) text);
77 if (ret == NULL) /* Why? */
78 {
79 fprintf(stderr, "xmljNewString: ERROR: NewStringUTF returned null for \"%s\"\n", text);
80 fflush (stderr);
81 }
82 else
83 {
84 xmlHashAddEntry (xmljStringCache, text, ret);
85 }
86 }
87 #else
88 ret = (*env)->NewStringUTF (env, (char *) text);
89 if (ret == NULL) /* Why? */
90 {
91 printf("xmljNewString: ERROR: NewStringUTF returned null for \"%s\"\n", text);
92 }
93 #endif /* XMLJ_STRING_CACHE */
94 return ret;
95 }
96
97 void
xmljClearStringCache()98 xmljClearStringCache ()
99 {
100 #ifdef XMLJ_STRING_CACHE
101 if (xmljStringCache != NULL)
102 {
103 xmlHashFree (xmljStringCache, &xmljHashDeallocate);
104 }
105 #endif /* XMLJ_STRING_CACHE */
106 }
107
108 const xmlChar *
xmljGetStringChars(JNIEnv * env,jstring text)109 xmljGetStringChars (JNIEnv * env, jstring text)
110 {
111 const char *s_text;
112 xmlChar *x_text;
113
114 if (text == NULL)
115 {
116 return NULL;
117 }
118
119 s_text = (*env)->GetStringUTFChars (env, text, 0);
120 x_text = (s_text == NULL) ? NULL : xmlCharStrdup (s_text);
121 if (s_text != NULL && x_text == NULL)
122 {
123 /* TODO raise exception */
124 }
125 (*env)->ReleaseStringUTFChars (env, text, s_text);
126 return x_text;
127 }
128
129 const xmlChar *
xmljGetPrefix(const xmlChar * qName)130 xmljGetPrefix (const xmlChar * qName)
131 {
132 const xmlChar *localName;
133 const xmlChar *ret;
134 xmlChar **prefix;
135
136 prefix = (xmlChar **) malloc (sizeof (xmlChar *));
137 localName = xmlSplitQName2 (qName, prefix);
138 if (localName == NULL)
139 {
140 return NULL;
141 }
142 ret = *prefix;
143 free (prefix);
144 return ret;
145 }
146
147 const xmlChar *
xmljGetLocalName(const xmlChar * qName)148 xmljGetLocalName (const xmlChar * qName)
149 {
150 const xmlChar *localName;
151 xmlChar **prefix;
152
153 prefix = (xmlChar **) malloc (sizeof (xmlChar *));
154 localName = xmlSplitQName2 (qName, prefix);
155 if (localName == NULL)
156 {
157 return qName;
158 }
159 free (prefix);
160 return localName;
161 }
162
xmljGetMethodID(JNIEnv * env,jobject target,const char * name,const char * signature)163 jmethodID xmljGetMethodID (JNIEnv *env,
164 jobject target,
165 const char *name,
166 const char *signature)
167 {
168 jclass cls;
169 jmethodID ret;
170
171 cls = (*env)->GetObjectClass (env, target);
172 if (cls == NULL)
173 {
174 xmljThrowException (env,
175 "java/lang/ClassNotFoundException",
176 NULL);
177 return NULL;
178 }
179 ret = (*env)->GetMethodID (env,
180 cls,
181 name,
182 signature);
183 if (ret == NULL)
184 {
185 jclass clscls;
186 jmethodID nm;
187 jstring clsname;
188 const char *c_clsName;
189 char cat[512] = "[method signature too long]";
190
191 clscls = (*env)->FindClass (env, "java/lang/Class");
192 if (clscls == NULL)
193 {
194 return NULL;
195 }
196 nm = (*env)->GetMethodID (env, clscls, "getName",
197 "()Ljava/lang/String;");
198 if (nm == NULL)
199 {
200 return NULL;
201 }
202 clsname = (jstring) (*env)->CallObjectMethod (env,
203 (jobject)cls,
204 nm);
205 if (clsname == NULL)
206 {
207 return NULL;
208 }
209 c_clsName = (*env)->GetStringUTFChars (env, clsname, 0);
210 sprintf (cat, "%s.%s %s", c_clsName, name, signature);
211 xmljThrowException (env,
212 "java/lang/NoSuchMethodException",
213 cat);
214 (*env)->ReleaseStringUTFChars (env, clsname, c_clsName);
215 }
216 return ret;
217 }
218
219 void *
xmljAsPointer(JNIEnv * env,jobject ptr)220 xmljAsPointer (JNIEnv *env, jobject ptr)
221 {
222 return JCL_GetRawData(env, ptr);
223 }
224
225 jobject
xmljAsField(JNIEnv * env,void * ptr)226 xmljAsField (JNIEnv *env, void * ptr)
227 {
228 return JCL_NewRawDataObject(env, ptr);
229 }
230
231 JNIEnv *
xmljGetJNIEnv()232 xmljGetJNIEnv ()
233 {
234 JavaVM **jvms;
235 jsize *jvm_count;
236 JavaVM *jvm;
237 JNIEnv **envs;
238 JNIEnv *env;
239
240 jvms = (JavaVM **) malloc (sizeof (JavaVM *));
241 if (!jvms)
242 {
243 return NULL;
244 }
245 jvm_count = (jsize *) malloc (sizeof (jsize));
246 if (!jvm_count)
247 {
248 free (jvms);
249 return NULL;
250 }
251 if (JNI_GetCreatedJavaVMs (jvms, 1, jvm_count))
252 {
253 free (jvms);
254 free (jvm_count);
255 return NULL;
256 }
257 jvm = *jvms;
258 envs = (JNIEnv **) malloc (sizeof (JNIEnv *));
259 if (!envs)
260 {
261 free (jvms);
262 free (jvm_count);
263 return NULL;
264 }
265 (*jvm)->AttachCurrentThread (jvm, (void **) envs, NULL);
266 (*jvm)->GetEnv (jvm, (void **) envs, JNI_VERSION_1_2);
267 if (envs)
268 {
269 env = *envs;
270 free (envs);
271 }
272 else
273 {
274 env = NULL;
275 }
276 free (jvms);
277 free (jvm_count);
278 return env;
279 }
280
281