* src/vm/options.c: Moved -m, -sig and -all flags to -XX options.
[cacao.git] / src / native / vm / gnuclasspath / java_lang_VMClassLoader.cpp
1 /* src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <sys/stat.h>
31
32 #include "mm/memory.hpp"
33
34 #include "native/jni.hpp"
35 #include "native/llni.h"
36 #include "native/native.hpp"
37
38 #if defined(ENABLE_JNI_HEADERS)
39 # include "native/vm/include/java_lang_VMClassLoader.h"
40 #endif
41
42 #include "toolbox/logging.hpp"
43 #include "toolbox/list.hpp"
44
45 #if defined(ENABLE_ASSERTION)
46 #include "vm/assertion.hpp"
47 #endif
48
49 #include "vm/jit/builtin.hpp"
50 #include "vm/class.hpp"
51 #include "vm/classcache.hpp"
52 #include "vm/exceptions.hpp"
53 #include "vm/globals.hpp"
54 #include "vm/initialize.hpp"
55 #include "vm/javaobjects.hpp"
56 #include "vm/linker.hpp"
57 #include "vm/loader.hpp"
58 #include "vm/options.h"
59 #include "vm/primitive.hpp"
60 #include "vm/statistics.h"
61 #include "vm/string.hpp"
62 #include "vm/vm.hpp"
63 #include "vm/zip.hpp"
64
65 #include "vm/jit/asmpart.h"
66
67 #if defined(ENABLE_JVMTI)
68 #include "native/jvmti/cacaodbg.h"
69 #endif
70
71
72 // Native functions are exported as C functions.
73 extern "C" {
74
75 /*
76  * Class:     java/lang/VMClassLoader
77  * Method:    defineClass
78  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
79  */
80 JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, jobject cl, jstring name, jbyteArray data, jint offset, jint len, jobject pd)
81 {
82         utf             *utfname;
83         classinfo       *c;
84         classloader_t   *loader;
85         java_handle_bytearray_t* ba;
86         uint8_t*                 stream;
87
88 #if defined(ENABLE_JVMTI)
89         jint new_class_data_len = 0;
90         unsigned char* new_class_data = NULL;
91 #endif
92
93         /* check if data was passed */
94
95         if (data == NULL) {
96                 exceptions_throw_nullpointerexception();
97                 return NULL;
98         }
99
100         /* check the indexes passed */
101
102         if ((offset < 0) || (len < 0) || ((offset + len) > LLNI_array_size(data))) {
103                 exceptions_throw_arrayindexoutofboundsexception();
104                 return NULL;
105         }
106
107         /* add classloader to classloader hashtable */
108
109         loader = loader_hashtable_classloader_add((java_handle_t *) cl);
110
111         if (name != NULL) {
112                 /* convert '.' to '/' in java string */
113
114                 utfname = javastring_toutf((java_handle_t *) name, true);
115         } 
116         else {
117                 utfname = NULL;
118         }
119
120 #if defined(ENABLE_JVMTI)
121         /* XXX again this will not work because of the indirection cell for classloaders */
122         assert(0);
123         /* fire Class File Load Hook JVMTI event */
124
125         if (jvmti)
126                 jvmti_ClassFileLoadHook(utfname, len, (unsigned char *) data->data, 
127                                                                 loader, (java_handle_t *) pd, 
128                                                                 &new_class_data_len, &new_class_data);
129 #endif
130
131         /* define the class */
132
133 #if defined(ENABLE_JVMTI)
134         /* check if the JVMTI wants to modify the class */
135
136         if (new_class_data == NULL)
137                 c = class_define(utfname, loader, new_class_data_len, new_class_data, pd); 
138         else
139 #endif
140         {
141                 ba = (java_handle_bytearray_t*) data;
142                 stream = (uint8_t *) &LLNI_array_direct(ba, offset);
143                 c = class_define(utfname, loader, len, stream, (java_handle_t *) pd);
144         }
145
146         if (c == NULL)
147                 return NULL;
148
149         // REMOVEME
150         java_handle_t* h = LLNI_classinfo_wrap(c);
151
152         // Set ProtectionDomain.
153         java_lang_Class jlc(h);
154         jlc.set_pd(pd);
155
156         return (jclass) jlc.get_handle();
157 }
158
159
160 /*
161  * Class:     java/lang/VMClassLoader
162  * Method:    getPrimitiveClass
163  * Signature: (C)Ljava/lang/Class;
164  */
165 JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, jchar type)
166 {
167         classinfo *c;
168
169         c = Primitive::get_class_by_char(type);
170
171         if (c == NULL) {
172                 exceptions_throw_classnotfoundexception(utf_null);
173                 return NULL;
174         }
175
176         return (jclass) LLNI_classinfo_wrap(c);
177 }
178
179
180 /*
181  * Class:     java/lang/VMClassLoader
182  * Method:    resolveClass
183  * Signature: (Ljava/lang/Class;)V
184  */
185 JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jclass clazz, jclass c)
186 {
187         classinfo *ci;
188
189         ci = LLNI_classinfo_unwrap(c);
190
191         if (!ci) {
192                 exceptions_throw_nullpointerexception();
193                 return;
194         }
195
196         /* link the class */
197
198         if (!(ci->state & CLASS_LINKED))
199                 (void) link_class(ci);
200
201         return;
202 }
203
204
205 /*
206  * Class:     java/lang/VMClassLoader
207  * Method:    loadClass
208  * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
209  */
210 JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, jstring name, jboolean resolve)
211 {
212         classinfo *c;
213         utf       *u;
214
215         if (name == NULL) {
216                 exceptions_throw_nullpointerexception();
217                 return NULL;
218         }
219
220         /* create utf string in which '.' is replaced by '/' */
221
222         u = javastring_toutf((java_handle_t *) name, true);
223
224         /* load class */
225
226         c = load_class_bootstrap(u);
227
228         if (c == NULL)
229                 return NULL;
230
231         /* resolve class -- if requested */
232
233 /*      if (resolve) */
234                 if (!link_class(c))
235                         return NULL;
236
237         return (jclass) LLNI_classinfo_wrap(c);
238 }
239
240
241 /*
242  * Class:     java/lang/VMClassLoader
243  * Method:    nativeGetResources
244  * Signature: (Ljava/lang/String;)Ljava/util/Vector;
245  */
246 JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, jstring name)
247 {
248         java_handle_t        *o;         /* vector being created     */
249         methodinfo           *m;         /* "add" method of vector   */
250         java_handle_t        *path;      /* path to be added         */
251         utf                  *utfname;   /* utf to look for          */
252         char                 *buffer;    /* char buffer              */
253         char                 *namestart; /* start of name to use     */
254         char                 *tmppath;   /* temporary buffer         */
255         int32_t               namelen;   /* length of name to use    */
256         int32_t               searchlen; /* length of name to search */
257         int32_t               bufsize;   /* size of buffer allocated */
258         int32_t               pathlen;   /* name of path to assemble */
259         struct stat           buf;       /* buffer for stat          */
260         jboolean              ret;       /* return value of "add"    */
261
262         // Get current list of classpath entries.
263         SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
264
265         /* get the resource name as utf string */
266
267         utfname = javastring_toutf((java_handle_t *) name, false);
268
269         if (utfname == NULL)
270                 return NULL;
271
272         /* copy it to a char buffer */
273
274         namelen   = utf_bytes(utfname);
275         searchlen = namelen;
276         bufsize   = namelen + strlen("0");
277         buffer    = MNEW(char, bufsize);
278
279         utf_copy(buffer, utfname);
280         namestart = buffer;
281
282         /* skip leading '/' */
283
284         if (namestart[0] == '/') {
285                 namestart++;
286                 namelen--;
287                 searchlen--;
288         }
289
290         /* remove trailing `.class' */
291
292         if (namelen >= 6 && strcmp(namestart + (namelen - 6), ".class") == 0) {
293                 searchlen -= 6;
294         }
295
296         /* create a new needle to look for, if necessary */
297
298         if (searchlen != bufsize-1) {
299                 utfname = utf_new(namestart, searchlen);
300                 if (utfname == NULL)
301                         goto return_NULL;
302         }
303                         
304         /* new Vector() */
305
306         o = native_new_and_init(class_java_util_Vector);
307
308         if (o == NULL)
309                 goto return_NULL;
310
311         /* get Vector.add() method */
312
313         m = class_resolveclassmethod(class_java_util_Vector,
314                                                                  utf_add,
315                                                                  utf_new_char("(Ljava/lang/Object;)Z"),
316                                                                  NULL,
317                                                                  true);
318
319         if (m == NULL)
320                 goto return_NULL;
321
322         /* iterate over all classpath entries */
323
324         for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end(); it++) {
325                 list_classpath_entry* lce = *it;
326
327                 /* clear path pointer */
328                 path = NULL;
329
330 #if defined(ENABLE_ZLIB)
331                 if (lce->type == CLASSPATH_ARCHIVE) {
332
333                         if (zip_find(lce, utfname)) {
334                                 pathlen = strlen("jar:file://") + lce->pathlen + strlen("!/") +
335                                         namelen + strlen("0");
336
337                                 tmppath = MNEW(char, pathlen);
338
339                                 sprintf(tmppath, "jar:file://%s!/%s", lce->path, namestart);
340                                 path = javastring_new_from_utf_string(tmppath),
341
342                                 MFREE(tmppath, char, pathlen);
343                         }
344
345                 } else {
346 #endif /* defined(ENABLE_ZLIB) */
347                         pathlen = strlen("file://") + lce->pathlen + namelen + strlen("0");
348
349                         tmppath = MNEW(char, pathlen);
350
351                         sprintf(tmppath, "file://%s%s", lce->path, namestart);
352
353                         /* Does this file exist? */
354
355                         if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
356                                 if (!S_ISDIR(buf.st_mode))
357                                         path = javastring_new_from_utf_string(tmppath);
358
359                         MFREE(tmppath, char, pathlen);
360 #if defined(ENABLE_ZLIB)
361                 }
362 #endif
363
364                 /* if a resource was found, add it to the vector */
365
366                 if (path != NULL) {
367                         ret = vm_call_method_int(m, o, path);
368
369                         if (exceptions_get_exception() != NULL)
370                                 goto return_NULL;
371
372                         if (ret == 0) 
373                                 goto return_NULL;
374                 }
375         }
376
377         MFREE(buffer, char, bufsize);
378
379         return (jobject) o;
380
381 return_NULL:
382         MFREE(buffer, char, bufsize);
383
384         return NULL;
385 }
386
387
388 /*
389  * Class:     java/lang/VMClassLoader
390  * Method:    defaultAssertionStatus
391  * Signature: ()Z
392  */
393 JNIEXPORT jboolean JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
394 {
395 #if defined(ENABLE_ASSERTION)
396         return assertion_system_enabled;
397 #else
398         return false;
399 #endif
400 }
401
402 /*
403  * Class:     java/lang/VMClassLoader
404  * Method:    userAssertionStatus
405  * Signature: ()Z
406  */
407 JNIEXPORT jboolean JNICALL Java_java_lang_VMClassLoader_defaultUserAssertionStatus(JNIEnv *env, jclass clazz)
408 {
409 #if defined(ENABLE_ASSERTION)
410         return assertion_user_enabled;
411 #else
412         return false;
413 #endif
414 }
415
416 /*
417  * Class:     java/lang/VMClassLoader
418  * Method:    packageAssertionStatus
419  * Signature: (Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;
420  */
421 JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(JNIEnv *env, jclass clazz, jobject jtrue, jobject jfalse)
422 {
423         java_handle_t     *hm;
424 #if defined(ENABLE_ASSERTION)
425         java_handle_t     *js;
426         methodinfo        *m;
427 #endif
428
429         /* new HashMap() */
430
431         hm = native_new_and_init(class_java_util_HashMap);
432         if (hm == NULL) {
433                 return NULL;
434         }
435
436 #if defined(ENABLE_ASSERTION)
437         /* if nothing todo, return now */
438
439         if (assertion_package_count == 0) {
440                 return (jobject) hm;
441         }
442
443         /* get HashMap.put method */
444
445         m = class_resolveclassmethod(class_java_util_HashMap,
446                                  utf_put,
447                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
448                                  NULL,
449                                  true);
450
451         if (m == NULL) {
452                 return NULL;
453         }
454
455         for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
456                 assertion_name_t* item = *it;
457
458                 if (item->package == false)
459                         continue;
460                 
461                 if (strcmp(item->name, "") == 0) {
462                         /* unnamed package wanted */
463                         js = NULL;
464                 }
465                 else {
466                         js = javastring_new_from_ascii(item->name);
467                         if (js == NULL) {
468                                 return NULL;
469                         }
470                 }
471
472                 if (item->enabled == true) {
473                         vm_call_method(m, hm, js, jtrue);
474                 }
475                 else {
476                         vm_call_method(m, hm, js, jfalse);
477                 }
478         }
479 #endif
480
481         return (jobject) hm;
482 }
483
484 /*
485  * Class:     java/lang/VMClassLoader
486  * Method:    classAssertionStatus
487  * Signature: (Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;
488  */
489 JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNIEnv *env, jclass clazz, jobject jtrue, jobject jfalse)
490 {
491         java_handle_t     *hm;
492 #if defined(ENABLE_ASSERTION)
493         java_handle_t     *js;
494         methodinfo        *m;
495 #endif
496
497         /* new HashMap() */
498
499         hm = native_new_and_init(class_java_util_HashMap);
500         if (hm == NULL) {
501                 return NULL;
502         }
503
504 #if defined(ENABLE_ASSERTION)
505         /* if nothing todo, return now */
506
507         if (assertion_class_count == 0) {
508                 return (jobject) hm;
509         }
510
511         /* get HashMap.put method */
512
513         m = class_resolveclassmethod(class_java_util_HashMap,
514                                  utf_put,
515                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
516                                  NULL,
517                                  true);
518
519         if (m == NULL) {
520                 return NULL;
521         }
522
523         for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
524                 assertion_name_t* item = *it;
525
526                 if (item->package == true)
527                         continue;
528
529                 js = javastring_new_from_ascii(item->name);
530                 if (js == NULL) {
531                         return NULL;
532                 }
533
534                 if (item->enabled == true) {
535                         vm_call_method(m, hm, js, jtrue);
536                 }
537                 else {
538                         vm_call_method(m, hm, js, jfalse);
539                 }
540         }
541 #endif
542
543         return (jobject) hm;
544 }
545
546
547 /*
548  * Class:     java/lang/VMClassLoader
549  * Method:    findLoadedClass
550  * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
551  */
552 JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, jobject loader, jstring name)
553 {
554         classloader_t *cl;
555         classinfo     *c;
556         utf           *u;
557
558         /* XXX is it correct to add the classloader to the hashtable here? */
559
560         cl = loader_hashtable_classloader_add((java_handle_t *) loader);
561
562         /* replace `.' by `/', this is required by the classcache */
563
564         u = javastring_toutf((java_handle_t *) name, true);
565
566         /* lookup for defining classloader */
567
568         c = classcache_lookup_defined(cl, u);
569
570         /* if not found, lookup for initiating classloader */
571
572         if (c == NULL)
573                 c = classcache_lookup(cl, u);
574
575         return (jclass) LLNI_classinfo_wrap(c);
576 }
577
578 } // extern "C"
579
580
581 /* native methods implemented by this file ************************************/
582
583 static JNINativeMethod methods[] = {
584         { (char*) "defineClass",                (char*) "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_defineClass                },
585         { (char*) "getPrimitiveClass",          (char*) "(C)Ljava/lang/Class;",                                                                             (void*) (uintptr_t) &Java_java_lang_VMClassLoader_getPrimitiveClass          },
586         { (char*) "resolveClass",               (char*) "(Ljava/lang/Class;)V",                                                                             (void*) (uintptr_t) &Java_java_lang_VMClassLoader_resolveClass               },
587         { (char*) "loadClass",                  (char*) "(Ljava/lang/String;Z)Ljava/lang/Class;",                                                           (void*) (uintptr_t) &Java_java_lang_VMClassLoader_loadClass                  },
588         { (char*) "nativeGetResources",         (char*) "(Ljava/lang/String;)Ljava/util/Vector;",                                                           (void*) (uintptr_t) &Java_java_lang_VMClassLoader_nativeGetResources         },
589         { (char*) "defaultAssertionStatus",     (char*) "()Z",                                                                                              (void*) (uintptr_t) &Java_java_lang_VMClassLoader_defaultAssertionStatus     },
590         { (char*) "defaultUserAssertionStatus", (char*) "()Z",                                                                                              (void*) (uintptr_t) &Java_java_lang_VMClassLoader_defaultUserAssertionStatus },
591         { (char*) "packageAssertionStatus0",    (char*) "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;",                                          (void*) (uintptr_t) &Java_java_lang_VMClassLoader_packageAssertionStatus0    },
592         { (char*) "classAssertionStatus0",      (char*) "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;",                                          (void*) (uintptr_t) &Java_java_lang_VMClassLoader_classAssertionStatus0      },
593         { (char*) "findLoadedClass",            (char*) "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;",                                     (void*) (uintptr_t) &Java_java_lang_VMClassLoader_findLoadedClass            },
594 };
595
596
597 /* _Jv_java_lang_VMClassLoader_init ********************************************
598
599    Register native functions.
600
601 *******************************************************************************/
602
603 void _Jv_java_lang_VMClassLoader_init(void)
604 {
605         utf* u = utf_new_char("java/lang/VMClassLoader");
606
607         NativeMethods& nm = VM::get_current()->get_nativemethods();
608         nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
609 }
610
611
612 /*
613  * These are local overrides for various environment variables in Emacs.
614  * Please do not remove this and leave it at the end of the file, where
615  * Emacs will automagically detect them.
616  * ---------------------------------------------------------------------
617  * Local variables:
618  * mode: c++
619  * indent-tabs-mode: t
620  * c-basic-offset: 4
621  * tab-width: 4
622  * End:
623  * vim:noexpandtab:sw=4:ts=4:
624  */