Merged revisions 7797-7917 via svnmerge from
[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 7918 2007-05-20 20:42:18Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <sys/stat.h>
34
35 #include "vm/types.h"
36
37 #include "mm/memory.h"
38
39 #include "native/jni.h"
40 #include "native/native.h"
41 #include "native/include/java_lang_Class.h"
42 #include "native/include/java_lang_String.h"
43 #include "native/include/java_security_ProtectionDomain.h"  /* required by... */
44 #include "native/include/java_lang_ClassLoader.h"
45 #include "native/include/java_util_Vector.h"
46
47 #include "native/include/java_lang_VMClassLoader.h"
48
49 #include "native/vm/java_lang_ClassLoader.h"
50
51 #include "toolbox/logging.h"
52
53 #include "vm/builtin.h"
54 #include "vm/exceptions.h"
55 #include "vm/initialize.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.h"
58
59 #include "vm/jit/asmpart.h"
60
61 #include "vmcore/class.h"
62 #include "vmcore/classcache.h"
63 #include "vmcore/linker.h"
64 #include "vmcore/loader.h"
65 #include "vmcore/options.h"
66 #include "vmcore/statistics.h"
67 #include "vmcore/suck.h"
68 #include "vmcore/zip.h"
69
70 #if defined(ENABLE_JVMTI)
71 #include "native/jvmti/cacaodbg.h"
72 #endif
73
74
75 /* native methods implemented by this file ************************************/
76
77 static JNINativeMethod methods[] = {
78         { "defineClass",            "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClassLoader_defineClass            },
79         { "getPrimitiveClass",      "(C)Ljava/lang/Class;",                                                                             (void *) (ptrint) &Java_java_lang_VMClassLoader_getPrimitiveClass      },
80         { "resolveClass",           "(Ljava/lang/Class;)V",                                                                             (void *) (ptrint) &Java_java_lang_VMClassLoader_resolveClass           },
81         { "loadClass",              "(Ljava/lang/String;Z)Ljava/lang/Class;",                                                           (void *) (ptrint) &Java_java_lang_VMClassLoader_loadClass              },
82         { "nativeGetResources",     "(Ljava/lang/String;)Ljava/util/Vector;",                                                           (void *) (ptrint) &Java_java_lang_VMClassLoader_nativeGetResources     },
83         { "defaultAssertionStatus", "()Z",                                                                                              (void *) (ptrint) &Java_java_lang_VMClassLoader_defaultAssertionStatus },
84         { "findLoadedClass",        "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;",                                     (void *) (ptrint) &Java_java_lang_VMClassLoader_findLoadedClass        },
85 };
86
87
88 /* _Jv_java_lang_VMClassLoader_init ********************************************
89
90    Register native functions.
91
92 *******************************************************************************/
93
94 void _Jv_java_lang_VMClassLoader_init(void)
95 {
96         utf *u;
97
98         u = utf_new_char("java/lang/VMClassLoader");
99
100         native_method_register(u, methods, NATIVE_METHODS_COUNT);
101 }
102
103
104 /*
105  * Class:     java/lang/VMClassLoader
106  * Method:    defineClass
107  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
108  */
109 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)
110 {
111         return _Jv_java_lang_ClassLoader_defineClass(cl, name, data, offset, len, pd);
112 }
113
114
115 /*
116  * Class:     java/lang/VMClassLoader
117  * Method:    getPrimitiveClass
118  * Signature: (C)Ljava/lang/Class;
119  */
120 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, s4 type)
121 {
122         classinfo *c;
123         s4         index;
124
125         /* get primitive class */
126
127         switch (type) {
128         case 'I':
129                 index = PRIMITIVETYPE_INT;
130                 break;
131         case 'J':
132                 index = PRIMITIVETYPE_LONG;
133                 break;
134         case 'F':
135                 index = PRIMITIVETYPE_FLOAT;
136                 break;
137         case 'D':
138                 index = PRIMITIVETYPE_DOUBLE;
139                 break;
140         case 'B':
141                 index = PRIMITIVETYPE_BYTE;
142                 break;
143         case 'C':
144                 index = PRIMITIVETYPE_CHAR;
145                 break;
146         case 'S':
147                 index = PRIMITIVETYPE_SHORT;
148                 break;
149         case 'Z':
150                 index = PRIMITIVETYPE_BOOLEAN;
151                 break;
152         case 'V':
153                 index = PRIMITIVETYPE_VOID;
154                 break;
155         default:
156                 exceptions_throw_noclassdeffounderror(utf_null);
157                 c = NULL;
158         }
159
160         c = primitivetype_table[index].class_primitive;
161
162         return (java_lang_Class *) c;
163 }
164
165
166 /*
167  * Class:     java/lang/VMClassLoader
168  * Method:    resolveClass
169  * Signature: (Ljava/lang/Class;)V
170  */
171 JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jclass clazz, java_lang_Class *c)
172 {
173         classinfo *ci;
174
175         ci = (classinfo *) c;
176
177         if (!ci) {
178                 exceptions_throw_nullpointerexception();
179                 return;
180         }
181
182         /* link the class */
183
184         if (!(ci->state & CLASS_LINKED))
185                 (void) link_class(ci);
186
187         return;
188 }
189
190
191 /*
192  * Class:     java/lang/VMClassLoader
193  * Method:    loadClass
194  * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
195  */
196 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, s4 resolve)
197 {
198         classinfo         *c;
199         utf               *u;
200         java_objectheader *xptr;
201
202         if (name == NULL) {
203                 exceptions_throw_nullpointerexception();
204                 return NULL;
205         }
206
207         /* create utf string in which '.' is replaced by '/' */
208
209         u = javastring_toutf((java_objectheader *) name, true);
210
211         /* load class */
212
213         c = load_class_bootstrap(u);
214
215         if (c == NULL)
216                 goto exception;
217
218         /* resolve class -- if requested */
219
220 /*      if (resolve) */
221                 if (!link_class(c))
222                         goto exception;
223
224         return (java_lang_Class *) c;
225
226  exception:
227         xptr = exceptions_get_exception();
228
229         c = xptr->vftbl->class;
230         
231         /* if the exception is a NoClassDefFoundError, we replace it with a
232            ClassNotFoundException, otherwise return the exception */
233
234         if (c == class_java_lang_NoClassDefFoundError) {
235                 /* clear exceptionptr, because builtin_new checks for 
236                    ExceptionInInitializerError */
237                 exceptions_clear_exception();
238
239                 exceptions_throw_classnotfoundexception(u);
240         }
241
242         return NULL;
243 }
244
245
246 /*
247  * Class:     java/lang/VMClassLoader
248  * Method:    nativeGetResources
249  * Signature: (Ljava/lang/String;)Ljava/util/Vector;
250  */
251 JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, java_lang_String *name)
252 {
253         java_objectheader    *o;         /* vector being created     */
254         methodinfo           *m;         /* "add" method of vector   */
255         java_objectheader    *path;      /* path to be added         */
256         list_classpath_entry *lce;       /* classpath entry          */
257         utf                  *utfname;   /* utf to look for          */
258         char                 *buffer;    /* char buffer              */
259         char                 *namestart; /* start of name to use     */
260         char                 *tmppath;   /* temporary buffer         */
261         s4                    namelen;   /* length of name to use    */
262         s4                    searchlen; /* length of name to search */
263         s4                    bufsize;   /* size of buffer allocated */
264         s4                    pathlen;   /* name of path to assemble */
265         struct stat           buf;       /* buffer for stat          */
266         jboolean              ret;       /* return value of "add"    */
267
268         /* get the resource name as utf string */
269
270         utfname = javastring_toutf((java_objectheader *) name, false);
271
272         if (utfname == NULL)
273                 return NULL;
274
275         /* copy it to a char buffer */
276
277         namelen   = utf_bytes(utfname);
278         searchlen = namelen;
279         bufsize   = namelen + strlen("0");
280         buffer    = MNEW(char, bufsize);
281
282         utf_copy(buffer, utfname);
283         namestart = buffer;
284
285         /* skip leading '/' */
286
287         if (namestart[0] == '/') {
288                 namestart++;
289                 namelen--;
290                 searchlen--;
291         }
292
293         /* remove trailing `.class' */
294
295         if (namelen >= 6 && strcmp(namestart + (namelen - 6), ".class") == 0) {
296                 searchlen -= 6;
297         }
298
299         /* create a new needle to look for, if necessary */
300
301         if (searchlen != bufsize-1) {
302                 utfname = utf_new(namestart, searchlen);
303                 if (utfname == NULL)
304                         goto return_NULL;
305         }
306                         
307         /* new Vector() */
308
309         o = native_new_and_init(class_java_util_Vector);
310
311         if (o == NULL)
312                 goto return_NULL;
313
314         /* get Vector.add() method */
315
316         m = class_resolveclassmethod(class_java_util_Vector,
317                                                                  utf_add,
318                                                                  utf_new_char("(Ljava/lang/Object;)Z"),
319                                                                  NULL,
320                                                                  true);
321
322         if (m == NULL)
323                 goto return_NULL;
324
325         /* iterate over all classpath entries */
326
327         for (lce = list_first(list_classpath_entries); lce != NULL;
328                  lce = list_next(list_classpath_entries, lce)) {
329                 /* clear path pointer */
330                 path = NULL;
331
332 #if defined(ENABLE_ZLIB)
333                 if (lce->type == CLASSPATH_ARCHIVE) {
334
335                         if (zip_find(lce, utfname)) {
336                                 pathlen = strlen("jar:file://") + lce->pathlen + strlen("!/") +
337                                         namelen + strlen("0");
338
339                                 tmppath = MNEW(char, pathlen);
340
341                                 sprintf(tmppath, "jar:file://%s!/%s", lce->path, namestart);
342                                 path = javastring_new_from_utf_string(tmppath),
343
344                                 MFREE(tmppath, char, pathlen);
345                         }
346
347                 } else {
348 #endif /* defined(ENABLE_ZLIB) */
349                         pathlen = strlen("file://") + lce->pathlen + namelen + strlen("0");
350
351                         tmppath = MNEW(char, pathlen);
352
353                         sprintf(tmppath, "file://%s%s", lce->path, namestart);
354
355                         /* Does this file exist? */
356
357                         if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
358                                 if (!S_ISDIR(buf.st_mode))
359                                         path = javastring_new_from_utf_string(tmppath);
360
361                         MFREE(tmppath, char, pathlen);
362 #if defined(ENABLE_ZLIB)
363                 }
364 #endif
365
366                 /* if a resource was found, add it to the vector */
367
368                 if (path != NULL) {
369                         ret = vm_call_method_int(m, o, path);
370
371                         if (exceptions_get_exception() != NULL)
372                                 goto return_NULL;
373
374                         if (ret == 0) 
375                                 goto return_NULL;
376                 }
377         }
378
379         MFREE(buffer, char, bufsize);
380
381         return (java_util_Vector *) o;
382
383 return_NULL:
384         MFREE(buffer, char, bufsize);
385
386         return NULL;
387 }
388
389
390 /*
391  * Class:     java/lang/VMClassLoader
392  * Method:    defaultAssertionStatus
393  * Signature: ()Z
394  */
395 JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
396 {
397         return _Jv_jvm->Java_java_lang_VMClassLoader_defaultAssertionStatus;
398 }
399
400
401 /*
402  * Class:     java/lang/VMClassLoader
403  * Method:    findLoadedClass
404  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
405  */
406 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *loader, java_lang_String *name)
407 {
408         classloader *cl;
409         classinfo   *c;
410         utf         *u;
411
412         cl = (classloader *) loader;
413
414         /* replace `.' by `/', this is required by the classcache */
415
416         u = javastring_toutf((java_objectheader *) name, true);
417
418         /* lookup for defining classloader */
419
420         c = classcache_lookup_defined(cl, u);
421
422         /* if not found, lookup for initiating classloader */
423
424         if (c == NULL)
425                 c = classcache_lookup(cl, u);
426
427         return (java_lang_Class *) c;
428 }
429
430
431 /*
432  * These are local overrides for various environment variables in Emacs.
433  * Please do not remove this and leave it at the end of the file, where
434  * Emacs will automagically detect them.
435  * ---------------------------------------------------------------------
436  * Local variables:
437  * mode: c
438  * indent-tabs-mode: t
439  * c-basic-offset: 4
440  * tab-width: 4
441  * End:
442  * vim:noexpandtab:sw=4:ts=4:
443  */