* src/vm/jit/i386/darwin/md-os.c (md_replace_executionstate_read):
[cacao.git] / src / native / vm / java_lang_Class.c
1 /* src/native/vm/java_lang_Class.c - java/lang/Class
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 <stdint.h>
32 #include <string.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37
38 #include "native/jni.h"
39 #include "native/llni.h"
40 #include "native/native.h"
41
42 /* keep this order of the native includes */
43
44 #include "native/include/java_lang_String.h"
45
46 #if defined(ENABLE_JAVASE)
47 # if defined(WITH_CLASSPATH_SUN)
48 #  include "native/include/java_nio_ByteBuffer.h"       /* required by j.l.CL */
49 # endif
50 # include "native/include/java_lang_ClassLoader.h"
51 #endif
52
53 #include "native/include/java_lang_Object.h"
54 #include "native/include/java_lang_Class.h"
55
56 #if defined(ENABLE_JAVASE)
57 # include "native/include/java_lang_reflect_Constructor.h"
58 # include "native/include/java_lang_reflect_Field.h"
59 # include "native/include/java_lang_reflect_Method.h"
60 #endif
61
62 #include "native/vm/java_lang_Class.h"
63
64 #if defined(ENABLE_JAVASE)
65 # include "native/vm/reflect.h"
66 #endif
67
68 #include "toolbox/logging.h"
69
70 #include "vm/array.h"
71 #include "vm/builtin.h"
72 #include "vm/exceptions.h"
73 #include "vm/global.h"
74 #include "vm/initialize.h"
75 #include "vm/primitive.h"
76 #include "vm/resolve.h"
77 #include "vm/stringlocal.h"
78
79 #include "vmcore/class.h"
80 #include "vmcore/loader.h"
81
82 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
83 #include "native/include/sun_reflect_ConstantPool.h"
84
85 #include "vm/vm.h"
86
87 #include "vmcore/annotation.h"
88 #endif
89
90 /*
91  * Class:     java/lang/Class
92  * Method:    getName
93  * Signature: ()Ljava/lang/String;
94  */
95 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
96 {
97         classinfo               *c;
98         java_lang_String        *s;
99         java_handle_chararray_t *ca;
100         u4                       i;
101
102         c = LLNI_classinfo_unwrap(klass);
103
104         /* create a java string */
105
106         s = (java_lang_String *) javastring_new(c->name);
107
108         if (s == NULL)
109                 return NULL;
110
111         /* return string where '/' is replaced by '.' */
112
113         LLNI_field_get_ref(s, value, ca);
114
115         for (i = 0; i < LLNI_array_size(ca); i++) {
116                 if (LLNI_array_direct(ca, i) == '/')
117                         LLNI_array_direct(ca, i) = '.';
118         }
119
120         return s;
121 }
122
123
124 /*
125  * Class:     java/lang/Class
126  * Method:    forName
127  * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
128  */
129 #if defined(ENABLE_JAVASE)
130 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
131 #elif defined(ENABLE_JAVAME_CLDC1_1)
132 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
133 #endif
134 {
135 #if defined(ENABLE_JAVASE)
136         classloader *cl;
137 #endif
138         utf         *ufile;
139         utf         *uname;
140         classinfo   *c;
141         u2          *pos;
142         s4           i;
143
144 #if defined(ENABLE_JAVASE)
145         cl = loader_hashtable_classloader_add((java_handle_t *) loader);
146 #endif
147
148         /* illegal argument */
149
150         if (name == NULL) {
151                 exceptions_throw_nullpointerexception();
152                 return NULL;
153         }
154
155         /* create utf string in which '.' is replaced by '/' */
156
157         ufile = javastring_toutf((java_handle_t *) name, true);
158         uname = javastring_toutf((java_handle_t *) name, false);
159
160         /* name must not contain '/' (mauve test) */
161
162         for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
163                 if (*pos == '/') {
164                         exceptions_throw_classnotfoundexception(uname);
165                         return NULL;
166                 }
167         }
168
169         /* try to load, ... */
170
171 #if defined(ENABLE_JAVASE)
172         c = load_class_from_classloader(ufile, cl);
173 #elif defined(ENABLE_JAVAME_CLDC1_1)
174         c = load_class_bootstrap(ufile);
175 #endif
176
177         if (c == NULL)
178             return NULL;
179
180         /* link, ... */
181
182         if (!link_class(c))
183                 return NULL;
184         
185         /* ...and initialize it, if required */
186
187 #if defined(ENABLE_JAVASE)
188         if (initialize)
189 #endif
190                 if (!initialize_class(c))
191                         return NULL;
192
193         return LLNI_classinfo_wrap(c);
194 }
195
196
197 /*
198  * Class:     java/lang/Class
199  * Method:    isInstance
200  * Signature: (Ljava/lang/Object;)Z
201  */
202 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
203 {
204         classinfo     *c;
205         java_handle_t *ob;
206
207         c = LLNI_classinfo_unwrap(klass);
208         ob = (java_handle_t *) o;
209
210         if (!(c->state & CLASS_LINKED))
211                 if (!link_class(c))
212                         return 0;
213
214         return builtin_instanceof(ob, c);
215 }
216
217
218 /*
219  * Class:     java/lang/Class
220  * Method:    isAssignableFrom
221  * Signature: (Ljava/lang/Class;)Z
222  */
223 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
224 {
225         classinfo *kc;
226         classinfo *cc;
227
228         kc = LLNI_classinfo_unwrap(klass);
229         cc = LLNI_classinfo_unwrap(c);
230
231         if (cc == NULL) {
232                 exceptions_throw_nullpointerexception();
233                 return 0;
234         }
235
236         if (!(kc->state & CLASS_LINKED))
237                 if (!link_class(kc))
238                         return 0;
239
240         if (!(cc->state & CLASS_LINKED))
241                 if (!link_class(cc))
242                         return 0;
243
244         return class_isanysubclass(cc, kc);
245 }
246
247
248 #if defined(ENABLE_JAVASE)
249
250 /*
251  * Class:     java/lang/Class
252  * Method:    getDeclaredFields
253  * Signature: (Z)[Ljava/lang/reflect/Field;
254  */
255 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
256 {
257         classinfo                 *c;
258         java_handle_objectarray_t *oa;          /* result: array of field-objects */
259         fieldinfo                 *f;
260         java_lang_reflect_Field   *rf;
261         s4 public_fields;                    /* number of elements in field-array */
262         s4 pos;
263         s4 i;
264
265         c = LLNI_classinfo_unwrap(klass);
266
267         /* determine number of fields */
268
269         for (i = 0, public_fields = 0; i < c->fieldscount; i++)
270                 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
271                         public_fields++;
272
273         /* create array of fields */
274
275         oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
276
277         if (oa == NULL)
278                 return NULL;
279
280         /* get the fields and store in the array */
281
282         for (i = 0, pos = 0; i < c->fieldscount; i++) {
283                 f = &(c->fields[i]);
284
285                 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
286                         /* create Field object */
287
288                         rf = reflect_field_new(f);
289
290                         /* store object into array */
291
292                         array_objectarray_element_set(oa, pos, (java_handle_t *) rf);
293                         pos++;
294                 }
295         }
296
297         return oa;
298 }
299
300
301 /*
302  * Class:     java/lang/Class
303  * Method:    getDeclaredMethods
304  * Signature: (Z)[Ljava/lang/reflect/Method;
305  */
306 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
307 {
308         classinfo                 *c;
309         java_lang_reflect_Method  *rm;
310         java_handle_objectarray_t *oa;         /* result: array of Method-objects */
311         methodinfo                *m;     /* the current method to be represented */
312         s4 public_methods;               /* number of public methods of the class */
313         s4 pos;
314         s4 i;
315
316         c = LLNI_classinfo_unwrap(klass);
317
318         public_methods = 0;
319
320         /* JOWENN: array classes do not declare methods according to mauve
321            test.  It should be considered, if we should return to my old
322            clone method overriding instead of declaring it as a member
323            function. */
324
325         if (class_is_array(c))
326                 return builtin_anewarray(0, class_java_lang_reflect_Method);
327
328         /* determine number of methods */
329
330         for (i = 0; i < c->methodscount; i++) {
331                 m = &c->methods[i];
332
333                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
334                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
335                         !(m->flags & ACC_MIRANDA))
336                         public_methods++;
337         }
338
339         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
340
341         if (oa == NULL)
342                 return NULL;
343
344         for (i = 0, pos = 0; i < c->methodscount; i++) {
345                 m = &c->methods[i];
346
347                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
348                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
349                         !(m->flags & ACC_MIRANDA)) {
350                         /* create Method object */
351
352                         rm = reflect_method_new(m);
353
354                         /* store object into array */
355
356                         array_objectarray_element_set(oa, pos, (java_handle_t *) rm);
357                         pos++;
358                 }
359         }
360
361         return oa;
362 }
363
364
365 /*
366  * Class:     java/lang/Class
367  * Method:    getDeclaredConstructors
368  * Signature: (Z)[Ljava/lang/reflect/Constructor;
369  */
370 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
371 {
372         classinfo                     *c;
373         methodinfo                    *m; /* the current method to be represented */
374         java_handle_objectarray_t     *oa;     /* result: array of Method-objects */
375         java_lang_reflect_Constructor *rc;
376         s4 public_methods;               /* number of public methods of the class */
377         s4 pos;
378         s4 i;
379
380         c = LLNI_classinfo_unwrap(klass);
381
382         /* determine number of constructors */
383
384         for (i = 0, public_methods = 0; i < c->methodscount; i++) {
385                 m = &c->methods[i];
386
387                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
388                         (m->name == utf_init))
389                         public_methods++;
390         }
391
392         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
393
394         if (oa == NULL)
395                 return NULL;
396
397         for (i = 0, pos = 0; i < c->methodscount; i++) {
398                 m = &c->methods[i];
399
400                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
401                         (m->name == utf_init)) {
402                         /* create Constructor object */
403
404                         rc = reflect_constructor_new(m);
405
406                         /* store object into array */
407
408                         array_objectarray_element_set(oa, pos, (java_handle_t *) rc);
409                         pos++;
410                 }
411         }
412
413         return oa;
414 }
415
416
417 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
418 /*
419  * Class:     java/lang/Class
420  * Method:    getDeclaredAnnotations
421  * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
422  */
423 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
424 {
425         classinfo                *c               = NULL; /* classinfo for the java.lang.Class object 'klass'       */
426         static methodinfo        *m_parseAnnotationsIntoArray   = NULL; /* parser method (cached, therefore static) */
427         utf                      *utf_parseAnnotationsIntoArray = NULL; /* parser method name     */
428         utf                      *utf_desc        = NULL;               /* parser method descriptor (signature)     */
429         java_handle_bytearray_t  *annotations     = NULL;               /* unparsed annotations   */
430         sun_reflect_ConstantPool *constantPool    = NULL;               /* constant pool of klass */
431         java_lang_Object         *constantPoolOop = (java_lang_Object*)klass; /* constantPoolOop field of */
432                                                                               /* sun.reflect.ConstantPool */
433
434         if (klass == NULL) {
435                 exceptions_throw_nullpointerexception();
436                 return NULL;
437         }
438         
439         c = LLNI_classinfo_unwrap(klass);
440
441         /* get annotations: */
442         annotations = class_get_annotations(c);
443
444         constantPool = 
445                 (sun_reflect_ConstantPool*)native_new_and_init(
446                         class_sun_reflect_ConstantPool);
447         
448         if (constantPool == NULL) {
449                 /* out of memory */
450                 return NULL;
451         }
452
453         LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
454
455         /* only resolve the parser method the first time */
456         if (m_parseAnnotationsIntoArray == NULL) {
457                 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
458                 utf_desc = utf_new_char(
459                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
460                         "[Ljava/lang/annotation/Annotation;");
461
462                 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
463                         /* out of memory */
464                         return NULL;
465                 }
466
467                 m_parseAnnotationsIntoArray = class_resolveclassmethod(
468                         class_sun_reflect_annotation_AnnotationParser,
469                         utf_parseAnnotationsIntoArray,
470                         utf_desc,
471                         class_java_lang_Class,
472                         true);
473
474                 if (m_parseAnnotationsIntoArray == NULL) {
475                         /* method not found */
476                         return NULL;
477                 }
478         }
479
480         return (java_handle_objectarray_t*)vm_call_method(
481                 m_parseAnnotationsIntoArray, NULL,
482                 annotations, constantPool, klass);
483 }
484 #endif
485
486
487 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
488
489    Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
490    _Jv_java_lang_Class_getEnclosingMethod.
491
492 *******************************************************************************/
493
494 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
495 {
496         constant_nameandtype *cn;
497         classinfo            *ec;
498         methodinfo           *m;
499
500         /* get enclosing class and method */
501
502         ec = class_get_enclosingclass(c);
503         cn = c->enclosingmethod;
504
505         /* check for enclosing class and method */
506
507         if (ec == NULL)
508                 return NULL;
509
510         if (cn == NULL)
511                 return NULL;
512
513         /* find method in enclosing class */
514
515         m = class_findmethod(ec, cn->name, cn->descriptor);
516
517         if (m == NULL) {
518                 exceptions_throw_internalerror("Enclosing method doesn't exist");
519                 return NULL;
520         }
521
522         return m;
523 }
524
525
526 /*
527  * Class:     java/lang/Class
528  * Method:    getEnclosingConstructor
529  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
530  */
531 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
532 {
533         classinfo                     *c;
534         methodinfo                    *m;
535         java_lang_reflect_Constructor *rc;
536
537         c = LLNI_classinfo_unwrap(klass);
538
539         /* get enclosing method */
540
541         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
542
543         if (m == NULL)
544                 return NULL;
545
546         /* check for <init> */
547
548         if (m->name != utf_init)
549                 return NULL;
550
551         /* create Constructor object */
552
553         rc = reflect_constructor_new(m);
554
555         return rc;
556 }
557
558
559 /*
560  * Class:     java/lang/Class
561  * Method:    getEnclosingMethod
562  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
563  */
564 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
565 {
566         classinfo                *c;
567         methodinfo               *m;
568         java_lang_reflect_Method *rm;
569
570         c = LLNI_classinfo_unwrap(klass);
571
572         /* get enclosing method */
573
574         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
575
576         if (m == NULL)
577                 return NULL;
578
579         /* check for <init> */
580
581         if (m->name == utf_init)
582                 return NULL;
583
584         /* create java.lang.reflect.Method object */
585
586         rm = reflect_method_new(m);
587
588         return rm;
589 }
590
591 #endif /* ENABLE_JAVASE */
592
593
594 /*
595  * These are local overrides for various environment variables in Emacs.
596  * Please do not remove this and leave it at the end of the file, where
597  * Emacs will automagically detect them.
598  * ---------------------------------------------------------------------
599  * Local variables:
600  * mode: c
601  * indent-tabs-mode: t
602  * c-basic-offset: 4
603  * tab-width: 4
604  * End:
605  * vim:noexpandtab:sw=4:ts=4:
606  */