* src/vm/jit/i386/darwin/md-asm.h: Repaired --enable-cycles-stats.
[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 */
26
27
28 #include "config.h"
29
30 #include <assert.h>
31 #include <sys/stat.h>
32
33 #include "vm/types.h"
34
35 #include "mm/memory.h"
36
37 #include "native/jni.h"
38 #include "native/llni.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 #include "native/include/java_util_HashMap.h"
46 #include "native/include/java_util_Map.h"
47 #include "native/include/java_lang_Boolean.h"
48
49 #include "native/include/java_lang_VMClassLoader.h"
50
51 #include "native/vm/java_lang_ClassLoader.h"
52
53 #include "toolbox/logging.h"
54 #include "toolbox/list.h"
55
56 #if defined(ENABLE_ASSERTION)
57 #include "vm/assertion.h"
58 #endif
59
60 #include "vm/builtin.h"
61 #include "vm/exceptions.h"
62 #include "vm/initialize.h"
63 #include "vm/primitive.h"
64 #include "vm/stringlocal.h"
65 #include "vm/vm.h"
66
67 #include "vm/jit/asmpart.h"
68
69 #include "vmcore/class.h"
70 #include "vmcore/classcache.h"
71 #include "vmcore/linker.h"
72 #include "vmcore/loader.h"
73 #include "vmcore/options.h"
74 #include "vmcore/statistics.h"
75 #include "vmcore/suck.h"
76 #include "vmcore/zip.h"
77
78 #if defined(ENABLE_JVMTI)
79 #include "native/jvmti/cacaodbg.h"
80 #endif
81
82 /* native methods implemented by this file ************************************/
83
84 static JNINativeMethod methods[] = {
85         { "defineClass",                "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClassLoader_defineClass                },
86         { "getPrimitiveClass",          "(C)Ljava/lang/Class;",                                                                             (void *) (ptrint) &Java_java_lang_VMClassLoader_getPrimitiveClass          },
87         { "resolveClass",               "(Ljava/lang/Class;)V",                                                                             (void *) (ptrint) &Java_java_lang_VMClassLoader_resolveClass               },
88         { "loadClass",                  "(Ljava/lang/String;Z)Ljava/lang/Class;",                                                           (void *) (ptrint) &Java_java_lang_VMClassLoader_loadClass                  },
89         { "nativeGetResources",         "(Ljava/lang/String;)Ljava/util/Vector;",                                                           (void *) (ptrint) &Java_java_lang_VMClassLoader_nativeGetResources         },
90         { "defaultAssertionStatus",     "()Z",                                                                                              (void *) (ptrint) &Java_java_lang_VMClassLoader_defaultAssertionStatus     },
91         { "defaultUserAssertionStatus", "()Z",                                                                                              (void *) (ptrint) &Java_java_lang_VMClassLoader_defaultUserAssertionStatus },
92         { "packageAssertionStatus0",    "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;",                                          (void *) (ptrint) &Java_java_lang_VMClassLoader_packageAssertionStatus0    },
93         { "classAssertionStatus0",      "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;",                                          (void *) (ptrint) &Java_java_lang_VMClassLoader_classAssertionStatus0      },
94         { "findLoadedClass",            "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;",                                     (void *) (ptrint) &Java_java_lang_VMClassLoader_findLoadedClass            },
95 };
96
97
98 /* _Jv_java_lang_VMClassLoader_init ********************************************
99
100    Register native functions.
101
102 *******************************************************************************/
103
104 void _Jv_java_lang_VMClassLoader_init(void)
105 {
106         utf *u;
107
108         u = utf_new_char("java/lang/VMClassLoader");
109
110         native_method_register(u, methods, NATIVE_METHODS_COUNT);
111 }
112
113
114 /*
115  * Class:     java/lang/VMClassLoader
116  * Method:    defineClass
117  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
118  */
119 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_handle_bytearray_t *data, s4 offset, s4 len, java_security_ProtectionDomain *pd)
120 {
121         return _Jv_java_lang_ClassLoader_defineClass(cl, name, data, offset, len, pd);
122 }
123
124
125 /*
126  * Class:     java/lang/VMClassLoader
127  * Method:    getPrimitiveClass
128  * Signature: (C)Ljava/lang/Class;
129  */
130 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, s4 type)
131 {
132         classinfo *c;
133
134         c = primitive_class_get_by_char(type);
135
136         if (c == NULL) {
137                 exceptions_throw_classnotfoundexception(utf_null);
138                 return NULL;
139         }
140
141         return LLNI_classinfo_wrap(c);
142 }
143
144
145 /*
146  * Class:     java/lang/VMClassLoader
147  * Method:    resolveClass
148  * Signature: (Ljava/lang/Class;)V
149  */
150 JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jclass clazz, java_lang_Class *c)
151 {
152         classinfo *ci;
153
154         ci = LLNI_classinfo_unwrap(c);
155
156         if (!ci) {
157                 exceptions_throw_nullpointerexception();
158                 return;
159         }
160
161         /* link the class */
162
163         if (!(ci->state & CLASS_LINKED))
164                 (void) link_class(ci);
165
166         return;
167 }
168
169
170 /*
171  * Class:     java/lang/VMClassLoader
172  * Method:    loadClass
173  * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
174  */
175 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, s4 resolve)
176 {
177         classinfo *c;
178         utf       *u;
179
180         if (name == NULL) {
181                 exceptions_throw_nullpointerexception();
182                 return NULL;
183         }
184
185         /* create utf string in which '.' is replaced by '/' */
186
187         u = javastring_toutf((java_handle_t *) name, true);
188
189         /* load class */
190
191         c = load_class_bootstrap(u);
192
193         if (c == NULL)
194                 return NULL;
195
196         /* resolve class -- if requested */
197
198 /*      if (resolve) */
199                 if (!link_class(c))
200                         return NULL;
201
202         return LLNI_classinfo_wrap(c);
203 }
204
205
206 /*
207  * Class:     java/lang/VMClassLoader
208  * Method:    nativeGetResources
209  * Signature: (Ljava/lang/String;)Ljava/util/Vector;
210  */
211 JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, java_lang_String *name)
212 {
213         java_handle_t        *o;         /* vector being created     */
214         methodinfo           *m;         /* "add" method of vector   */
215         java_handle_t        *path;      /* path to be added         */
216         list_classpath_entry *lce;       /* classpath entry          */
217         utf                  *utfname;   /* utf to look for          */
218         char                 *buffer;    /* char buffer              */
219         char                 *namestart; /* start of name to use     */
220         char                 *tmppath;   /* temporary buffer         */
221         s4                    namelen;   /* length of name to use    */
222         s4                    searchlen; /* length of name to search */
223         s4                    bufsize;   /* size of buffer allocated */
224         s4                    pathlen;   /* name of path to assemble */
225         struct stat           buf;       /* buffer for stat          */
226         jboolean              ret;       /* return value of "add"    */
227
228         /* get the resource name as utf string */
229
230         utfname = javastring_toutf((java_handle_t *) name, false);
231
232         if (utfname == NULL)
233                 return NULL;
234
235         /* copy it to a char buffer */
236
237         namelen   = utf_bytes(utfname);
238         searchlen = namelen;
239         bufsize   = namelen + strlen("0");
240         buffer    = MNEW(char, bufsize);
241
242         utf_copy(buffer, utfname);
243         namestart = buffer;
244
245         /* skip leading '/' */
246
247         if (namestart[0] == '/') {
248                 namestart++;
249                 namelen--;
250                 searchlen--;
251         }
252
253         /* remove trailing `.class' */
254
255         if (namelen >= 6 && strcmp(namestart + (namelen - 6), ".class") == 0) {
256                 searchlen -= 6;
257         }
258
259         /* create a new needle to look for, if necessary */
260
261         if (searchlen != bufsize-1) {
262                 utfname = utf_new(namestart, searchlen);
263                 if (utfname == NULL)
264                         goto return_NULL;
265         }
266                         
267         /* new Vector() */
268
269         o = native_new_and_init(class_java_util_Vector);
270
271         if (o == NULL)
272                 goto return_NULL;
273
274         /* get Vector.add() method */
275
276         m = class_resolveclassmethod(class_java_util_Vector,
277                                                                  utf_add,
278                                                                  utf_new_char("(Ljava/lang/Object;)Z"),
279                                                                  NULL,
280                                                                  true);
281
282         if (m == NULL)
283                 goto return_NULL;
284
285         /* iterate over all classpath entries */
286
287         for (lce = list_first(list_classpath_entries); lce != NULL;
288                  lce = list_next(list_classpath_entries, lce)) {
289                 /* clear path pointer */
290                 path = NULL;
291
292 #if defined(ENABLE_ZLIB)
293                 if (lce->type == CLASSPATH_ARCHIVE) {
294
295                         if (zip_find(lce, utfname)) {
296                                 pathlen = strlen("jar:file://") + lce->pathlen + strlen("!/") +
297                                         namelen + strlen("0");
298
299                                 tmppath = MNEW(char, pathlen);
300
301                                 sprintf(tmppath, "jar:file://%s!/%s", lce->path, namestart);
302                                 path = javastring_new_from_utf_string(tmppath),
303
304                                 MFREE(tmppath, char, pathlen);
305                         }
306
307                 } else {
308 #endif /* defined(ENABLE_ZLIB) */
309                         pathlen = strlen("file://") + lce->pathlen + namelen + strlen("0");
310
311                         tmppath = MNEW(char, pathlen);
312
313                         sprintf(tmppath, "file://%s%s", lce->path, namestart);
314
315                         /* Does this file exist? */
316
317                         if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
318                                 if (!S_ISDIR(buf.st_mode))
319                                         path = javastring_new_from_utf_string(tmppath);
320
321                         MFREE(tmppath, char, pathlen);
322 #if defined(ENABLE_ZLIB)
323                 }
324 #endif
325
326                 /* if a resource was found, add it to the vector */
327
328                 if (path != NULL) {
329                         ret = vm_call_method_int(m, o, path);
330
331                         if (exceptions_get_exception() != NULL)
332                                 goto return_NULL;
333
334                         if (ret == 0) 
335                                 goto return_NULL;
336                 }
337         }
338
339         MFREE(buffer, char, bufsize);
340
341         return (java_util_Vector *) o;
342
343 return_NULL:
344         MFREE(buffer, char, bufsize);
345
346         return NULL;
347 }
348
349
350 /*
351  * Class:     java/lang/VMClassLoader
352  * Method:    defaultAssertionStatus
353  * Signature: ()Z
354  */
355 JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
356 {
357 #if defined(ENABLE_ASSERTION)
358         return assertion_system_enabled;
359 #else
360         return false;
361 #endif
362 }
363
364 /*
365  * Class:     java/lang/VMClassLoader
366  * Method:    userAssertionStatus
367  * Signature: ()Z
368  */
369 JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultUserAssertionStatus(JNIEnv *env, jclass clazz)
370 {
371 #if defined(ENABLE_ASSERTION)
372         return assertion_user_enabled;
373 #else
374         return false;
375 #endif
376 }
377
378 /*
379  * Class:     java/lang/VMClassLoader
380  * Method:    packageAssertionStatus
381  * Signature: ()Ljava_util_Map;
382  */
383 JNIEXPORT java_util_Map* JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(JNIEnv *env, jclass clazz, java_lang_Boolean *jtrue, java_lang_Boolean *jfalse)
384 {
385         java_handle_t     *hm;
386 #if defined(ENABLE_ASSERTION)
387         java_handle_t     *js;
388         methodinfo        *m;
389         assertion_name_t  *item;
390 #endif
391
392         /* new HashMap() */
393
394         hm = native_new_and_init(class_java_util_HashMap);
395         if (hm == NULL) {
396                 return NULL;
397         }
398
399 #if defined(ENABLE_ASSERTION)
400         /* if nothing todo, return now */
401
402         if (assertion_package_count == 0) {
403                 return (java_util_Map *) hm;
404         }
405
406         /* get HashMap.put method */
407
408         m = class_resolveclassmethod(class_java_util_HashMap,
409                                  utf_put,
410                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
411                                  NULL,
412                                  true);
413
414         if (m == NULL) {
415                 return NULL;
416         }
417
418         item = (assertion_name_t *)list_first(list_assertion_names);
419
420         while (item != NULL) {
421                 if (item->package == false) {
422                         item = (assertion_name_t *)list_next(list_assertion_names, item);
423                         continue;
424                 }
425                 
426                 if (strcmp(item->name, "") == 0) {
427                         /* unnamed package wanted */
428                         js = NULL;
429                 }
430                 else {
431                         js = javastring_new_from_ascii(item->name);
432                         if (js == NULL) {
433                                 return NULL;
434                         }
435                 }
436
437                 if (item->enabled == true) {
438                         vm_call_method(m, hm, js, jtrue);
439                 }
440                 else {
441                         vm_call_method(m, hm, js, jfalse);
442                 }
443
444                 item = (assertion_name_t *)list_next(list_assertion_names, item);
445         }
446 #endif
447
448         return (java_util_Map *) hm;
449 }
450
451 /*
452  * Class:     java/lang/VMClassLoader
453  * Method:    classAssertionStatus
454  * Signature: ()Ljava_util_Map;
455  */
456 JNIEXPORT java_util_Map* JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNIEnv *env, jclass clazz, java_lang_Boolean *jtrue, java_lang_Boolean *jfalse)
457 {
458         java_handle_t     *hm;
459 #if defined(ENABLE_ASSERTION)
460         java_handle_t     *js;
461         methodinfo        *m;
462         assertion_name_t  *item;
463 #endif
464
465         /* new HashMap() */
466
467         hm = native_new_and_init(class_java_util_HashMap);
468         if (hm == NULL) {
469                 return NULL;
470         }
471
472 #if defined(ENABLE_ASSERTION)
473         /* if nothing todo, return now */
474
475         if (assertion_class_count == 0) {
476                 return (java_util_Map *) hm;
477         }
478
479         /* get HashMap.put method */
480
481         m = class_resolveclassmethod(class_java_util_HashMap,
482                                  utf_put,
483                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
484                                  NULL,
485                                  true);
486
487         if (m == NULL) {
488                 return NULL;
489         }
490
491         item = (assertion_name_t *)list_first(list_assertion_names);
492
493         while (item != NULL) {
494                 if (item->package == true) {
495                         item = (assertion_name_t *)list_next(list_assertion_names, item);
496                         continue;
497                 }
498
499                 js = javastring_new_from_ascii(item->name);
500                 if (js == NULL) {
501                         return NULL;
502                 }
503
504                 if (item->enabled == true) {
505                         vm_call_method(m, hm, js, jtrue);
506                 }
507                 else {
508                         vm_call_method(m, hm, js, jfalse);
509                 }
510
511                 item = (assertion_name_t *)list_next(list_assertion_names, item);
512         }
513 #endif
514
515         return (java_util_Map *) hm;
516 }
517
518
519 /*
520  * Class:     java/lang/VMClassLoader
521  * Method:    findLoadedClass
522  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
523  */
524 JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *loader, java_lang_String *name)
525 {
526         classloader *cl;
527         classinfo   *c;
528         utf         *u;
529
530         /* XXX is it correct to add the classloader to the hashtable here? */
531
532         cl = loader_hashtable_classloader_add((java_handle_t *) loader);
533
534         /* replace `.' by `/', this is required by the classcache */
535
536         u = javastring_toutf((java_handle_t *) name, true);
537
538         /* lookup for defining classloader */
539
540         c = classcache_lookup_defined(cl, u);
541
542         /* if not found, lookup for initiating classloader */
543
544         if (c == NULL)
545                 c = classcache_lookup(cl, u);
546
547         return LLNI_classinfo_wrap(c);
548 }
549
550
551 /*
552  * These are local overrides for various environment variables in Emacs.
553  * Please do not remove this and leave it at the end of the file, where
554  * Emacs will automagically detect them.
555  * ---------------------------------------------------------------------
556  * Local variables:
557  * mode: c
558  * indent-tabs-mode: t
559  * c-basic-offset: 4
560  * tab-width: 4
561  * End:
562  * vim:noexpandtab:sw=4:ts=4:
563  */