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