* src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c
[cacao.git] / src / native / vm / gnu / java_lang_VMClassLoader.c
1 /* src/native/vm/gnu/VMClassLoader.c
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: java_lang_VMClassLoader.c 7408 2007-02-26 22:11:38Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <sys/stat.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37
38 #include "native/jni.h"
39 #include "native/native.h"
40 #include "native/include/java_lang_Class.h"
41 #include "native/include/java_lang_String.h"
42 #include "native/include/java_security_ProtectionDomain.h"  /* required by... */
43 #include "native/include/java_lang_ClassLoader.h"
44 #include "native/include/java_util_Vector.h"
45
46 #include "native/vm/java_lang_ClassLoader.h"
47
48 #include "toolbox/logging.h"
49
50 #include "vm/builtin.h"
51 #include "vm/exceptions.h"
52 #include "vm/initialize.h"
53 #include "vm/stringlocal.h"
54 #include "vm/vm.h"
55
56 #include "vm/jit/asmpart.h"
57
58 #include "vmcore/class.h"
59 #include "vmcore/classcache.h"
60 #include "vmcore/linker.h"
61 #include "vmcore/loader.h"
62 #include "vmcore/options.h"
63 #include "vmcore/statistics.h"
64 #include "vmcore/suck.h"
65 #include "vmcore/zip.h"
66
67 #if defined(ENABLE_JVMTI)
68 #include "native/jvmti/cacaodbg.h"
69 #endif
70
71
72 /*
73  * Class:     java/lang/VMClassLoader
74  * Method:    defineClass
75  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
76  */
77 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_bytearray *data, s4 offset, s4 len, java_security_ProtectionDomain *pd)
78 {
79         return _Jv_java_lang_ClassLoader_defineClass(cl, name, data, offset, len, pd);
80 }
81
82
83 /*
84  * Class:     java/lang/VMClassLoader
85  * Method:    getPrimitiveClass
86  * Signature: (C)Ljava/lang/Class;
87  */
88 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, s4 type)
89 {
90         classinfo *c;
91         s4         index;
92
93         /* get primitive class */
94
95         switch (type) {
96         case 'I':
97                 index = PRIMITIVETYPE_INT;
98                 break;
99         case 'J':
100                 index = PRIMITIVETYPE_LONG;
101                 break;
102         case 'F':
103                 index = PRIMITIVETYPE_FLOAT;
104                 break;
105         case 'D':
106                 index = PRIMITIVETYPE_DOUBLE;
107                 break;
108         case 'B':
109                 index = PRIMITIVETYPE_BYTE;
110                 break;
111         case 'C':
112                 index = PRIMITIVETYPE_CHAR;
113                 break;
114         case 'S':
115                 index = PRIMITIVETYPE_SHORT;
116                 break;
117         case 'Z':
118                 index = PRIMITIVETYPE_BOOLEAN;
119                 break;
120         case 'V':
121                 index = PRIMITIVETYPE_VOID;
122                 break;
123         default:
124                 exceptions_throw_noclassdeffounderror(utf_null);
125                 c = NULL;
126         }
127
128         c = primitivetype_table[index].class_primitive;
129
130         return (java_lang_Class *) c;
131 }
132
133
134 /*
135  * Class:     java/lang/VMClassLoader
136  * Method:    resolveClass
137  * Signature: (Ljava/lang/Class;)V
138  */
139 JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jclass clazz, java_lang_Class *c)
140 {
141         classinfo *ci;
142
143         ci = (classinfo *) c;
144
145         if (!ci) {
146                 exceptions_throw_nullpointerexception();
147                 return;
148         }
149
150         /* link the class */
151
152         if (!(ci->state & CLASS_LINKED))
153                 (void) link_class(ci);
154
155         return;
156 }
157
158
159 /*
160  * Class:     java/lang/VMClassLoader
161  * Method:    loadClass
162  * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
163  */
164 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, jboolean resolve)
165 {
166         classinfo         *c;
167         utf               *u;
168         java_objectheader *xptr;
169
170         if (name == NULL) {
171                 exceptions_throw_nullpointerexception();
172                 return NULL;
173         }
174
175         /* create utf string in which '.' is replaced by '/' */
176
177         u = javastring_toutf(name, true);
178
179         /* load class */
180
181         c = load_class_bootstrap(u);
182
183         if (c == NULL)
184                 goto exception;
185
186         /* resolve class -- if requested */
187
188 /*      if (resolve) */
189                 if (!link_class(c))
190                         goto exception;
191
192         return (java_lang_Class *) c;
193
194  exception:
195         xptr = exceptions_get_exception();
196
197         c = xptr->vftbl->class;
198         
199         /* if the exception is a NoClassDefFoundError, we replace it with a
200            ClassNotFoundException, otherwise return the exception */
201
202         if (c == class_java_lang_NoClassDefFoundError) {
203                 /* clear exceptionptr, because builtin_new checks for 
204                    ExceptionInInitializerError */
205                 exceptions_clear_exception();
206
207                 exceptions_throw_classnotfoundexception(u);
208         }
209
210         return NULL;
211 }
212
213
214 /*
215  * Class:     java/lang/VMClassLoader
216  * Method:    nativeGetResources
217  * Signature: (Ljava/lang/String;)Ljava/util/Vector;
218  */
219 JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, java_lang_String *name)
220 {
221         jobject               o;         /* vector being created     */
222         methodinfo           *m;         /* "add" method of vector   */
223         java_lang_String     *path;      /* path to be added         */
224         list_classpath_entry *lce;       /* classpath entry          */
225         utf                  *utfname;   /* utf to look for          */
226         char                 *buffer;    /* char buffer              */
227         char                 *namestart; /* start of name to use     */
228         char                 *tmppath;   /* temporary buffer         */
229         s4                    namelen;   /* length of name to use    */
230         s4                    searchlen; /* length of name to search */
231         s4                    bufsize;   /* size of buffer allocated */
232         s4                    pathlen;   /* name of path to assemble */
233         struct stat           buf;       /* buffer for stat          */
234         jboolean              ret;       /* return value of "add"    */
235
236         /* get the resource name as utf string */
237
238         utfname = javastring_toutf(name, false);
239         if (!utfname)
240                 return NULL;
241
242         /* copy it to a char buffer */
243
244         namelen = utf_bytes(utfname);
245         searchlen = namelen;
246         bufsize = namelen + strlen("0");
247         buffer = MNEW(char, bufsize);
248
249         utf_copy(buffer, utfname);
250         namestart = buffer;
251
252         /* skip leading '/' */
253
254         if (namestart[0] == '/') {
255                 namestart++;
256                 namelen--;
257                 searchlen--;
258         }
259
260         /* remove trailing `.class' */
261
262         if (namelen >= 6 && strcmp(namestart + (namelen - 6), ".class") == 0) {
263                 searchlen -= 6;
264         }
265
266         /* create a new needle to look for, if necessary */
267
268         if (searchlen != bufsize-1) {
269                 utfname = utf_new(namestart, searchlen);
270                 if (utfname == NULL)
271                         goto return_NULL;
272         }
273                         
274         /* new Vector() */
275
276         o = native_new_and_init(class_java_util_Vector);
277
278         if (!o)
279                 goto return_NULL;
280
281         /* get Vector.add() method */
282
283         m = class_resolveclassmethod(class_java_util_Vector,
284                                                                  utf_add,
285                                                                  utf_new_char("(Ljava/lang/Object;)Z"),
286                                                                  NULL,
287                                                                  true);
288
289         if (!m)
290                 goto return_NULL;
291
292         /* iterate over all classpath entries */
293
294         for (lce = list_first(list_classpath_entries); lce != NULL;
295                  lce = list_next(list_classpath_entries, lce)) {
296                 /* clear path pointer */
297                 path = NULL;
298
299 #if defined(ENABLE_ZLIB)
300                 if (lce->type == CLASSPATH_ARCHIVE) {
301
302                         if (zip_find(lce, utfname)) {
303                                 pathlen = strlen("jar:file://") + lce->pathlen + strlen("!/") +
304                                         namelen + strlen("0");
305
306                                 tmppath = MNEW(char, pathlen);
307
308                                 sprintf(tmppath, "jar:file://%s!/%s", lce->path, namestart);
309                                 path = javastring_new_from_utf_string(tmppath),
310
311                                 MFREE(tmppath, char, pathlen);
312                         }
313
314                 } else {
315 #endif /* defined(ENABLE_ZLIB) */
316                         pathlen = strlen("file://") + lce->pathlen + namelen + strlen("0");
317
318                         tmppath = MNEW(char, pathlen);
319
320                         sprintf(tmppath, "file://%s%s", lce->path, namestart);
321
322                         /* Does this file exist? */
323
324                         if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
325                                 if (!S_ISDIR(buf.st_mode))
326                                         path = javastring_new_from_utf_string(tmppath);
327
328                         MFREE(tmppath, char, pathlen);
329 #if defined(ENABLE_ZLIB)
330                 }
331 #endif
332
333                 /* if a resource was found, add it to the vector */
334
335                 if (path) {
336                         ret = vm_call_method_int(m, o, path);
337
338                         if (exceptions_get_exception() != NULL)
339                                 goto return_NULL;
340
341                         if (ret == 0) 
342                                 goto return_NULL;
343                 }
344         }
345
346         MFREE(buffer, char, bufsize);
347
348         return (java_util_Vector *) o;
349
350 return_NULL:
351         MFREE(buffer, char, bufsize);
352
353         return NULL;
354 }
355
356
357 /*
358  * Class:     java/lang/VMClassLoader
359  * Method:    defaultAssertionStatus
360  * Signature: ()Z
361  */
362 JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
363 {
364         return _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus;
365 }
366
367
368 /*
369  * Class:     java/lang/VMClassLoader
370  * Method:    findLoadedClass
371  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
372  */
373 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name)
374 {
375         classinfo *c;
376         utf       *u;
377
378         /* replace `.' by `/', this is required by the classcache */
379
380         u = javastring_toutf(name, true);
381
382         /* lookup for defining classloader */
383
384         c = classcache_lookup_defined((classloader *) cl, u);
385
386         /* if not found, lookup for initiating classloader */
387
388         if (c == NULL)
389                 c = classcache_lookup((classloader *) cl, u);
390
391         return (java_lang_Class *) c;
392 }
393
394
395 /*
396  * These are local overrides for various environment variables in Emacs.
397  * Please do not remove this and leave it at the end of the file, where
398  * Emacs will automagically detect them.
399  * ---------------------------------------------------------------------
400  * Local variables:
401  * mode: c
402  * indent-tabs-mode: t
403  * c-basic-offset: 4
404  * tab-width: 4
405  * End:
406  * vim:noexpandtab:sw=4:ts=4:
407  */