* src/vmcore/class.c (class_get_interfaces): New function.
[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    $Id: java_lang_Class.c 8307 2007-08-15 15:20:47Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34 #include <string.h>
35
36 #include "vm/types.h"
37
38 #include "mm/memory.h"
39
40 #include "native/jni.h"
41 #include "native/llni.h"
42 #include "native/native.h"
43
44 /* keep this order of the native includes */
45
46 #include "native/include/java_lang_String.h"
47
48 #if defined(ENABLE_JAVASE)
49 # if defined(WITH_CLASSPATH_SUN)
50 #  include "native/include/java_nio_ByteBuffer.h"       /* required by j.l.CL */
51 # endif
52 # include "native/include/java_lang_ClassLoader.h"
53 #endif
54
55 #include "native/include/java_lang_Object.h"
56 #include "native/include/java_lang_Class.h"
57
58 #if defined(ENABLE_JAVASE)
59 # include "native/include/java_lang_reflect_Constructor.h"
60 # include "native/include/java_lang_reflect_Field.h"
61 # include "native/include/java_lang_reflect_Method.h"
62 #endif
63
64 #include "native/vm/java_lang_Class.h"
65 #include "native/vm/java_lang_String.h"
66
67 #if defined(ENABLE_JAVASE)
68 # include "native/vm/reflect.h"
69 #endif
70
71 #include "toolbox/logging.h"
72
73 #include "vm/builtin.h"
74 #include "vm/exceptions.h"
75 #include "vm/global.h"
76 #include "vm/initialize.h"
77 #include "vm/primitive.h"
78 #include "vm/resolve.h"
79 #include "vm/stringlocal.h"
80
81 #include "vmcore/class.h"
82 #include "vmcore/loader.h"
83
84 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
85 #include "vmcore/annotation.h"
86 #include "native/include/sun_reflect_ConstantPool.h"
87 #endif
88
89 /*
90  * Class:     java/lang/Class
91  * Method:    getName
92  * Signature: ()Ljava/lang/String;
93  */
94 java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
95 {
96         classinfo        *c;
97         java_lang_String *s;
98         java_chararray   *ca;
99         u4                i;
100
101         c = (classinfo *) klass;
102
103         /* create a java string */
104
105         s = (java_lang_String *) javastring_new(c->name);
106
107         if (s == NULL)
108                 return NULL;
109
110         /* return string where '/' is replaced by '.' */
111
112         LLNI_field_get_ref(s, value, ca);
113
114         for (i = 0; i < ca->header.size; i++) {
115                 if (ca->data[i] == '/')
116                         ca->data[i] = '.';
117         }
118
119         return s;
120 }
121
122
123 /*
124  * Class:     java/lang/Class
125  * Method:    forName
126  * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
127  */
128 #if defined(ENABLE_JAVASE)
129 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
130 #elif defined(ENABLE_JAVAME_CLDC1_1)
131 java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
132 #endif
133 {
134 #if defined(ENABLE_JAVASE)
135         classloader *cl;
136 #endif
137         utf         *ufile;
138         utf         *uname;
139         classinfo   *c;
140         u2          *pos;
141         s4           i;
142
143 #if defined(ENABLE_JAVASE)
144         cl = (classloader *) loader;
145 #endif
146
147         /* illegal argument */
148
149         if (name == NULL) {
150                 exceptions_throw_nullpointerexception();
151                 return NULL;
152         }
153
154         /* create utf string in which '.' is replaced by '/' */
155
156         ufile = javastring_toutf((java_handle_t *) name, true);
157         uname = javastring_toutf((java_handle_t *) name, false);
158
159         /* name must not contain '/' (mauve test) */
160
161         for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
162                 if (*pos == '/') {
163                         exceptions_throw_classnotfoundexception(uname);
164                         return NULL;
165                 }
166         }
167
168         /* try to load, ... */
169
170 #if defined(ENABLE_JAVASE)
171         c = load_class_from_classloader(ufile, cl);
172 #elif defined(ENABLE_JAVAME_CLDC1_1)
173         c = load_class_bootstrap(ufile);
174 #endif
175
176         if (c == NULL)
177             return NULL;
178
179         /* link, ... */
180
181         if (!link_class(c))
182                 return NULL;
183         
184         /* ...and initialize it, if required */
185
186 #if defined(ENABLE_JAVASE)
187         if (initialize)
188 #endif
189                 if (!initialize_class(c))
190                         return NULL;
191
192         return (java_lang_Class *) c;
193 }
194
195
196 /*
197  * Class:     java/lang/Class
198  * Method:    isInstance
199  * Signature: (Ljava/lang/Object;)Z
200  */
201 s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
202 {
203         classinfo     *c;
204         java_handle_t *ob;
205
206         c = (classinfo *) klass;
207         ob = (java_handle_t *) o;
208
209         if (!(c->state & CLASS_LINKED))
210                 if (!link_class(c))
211                         return 0;
212
213         return builtin_instanceof(ob, c);
214 }
215
216
217 /*
218  * Class:     java/lang/Class
219  * Method:    isAssignableFrom
220  * Signature: (Ljava/lang/Class;)Z
221  */
222 s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
223 {
224         classinfo *kc;
225         classinfo *cc;
226
227         kc = (classinfo *) klass;
228         cc = (classinfo *) c;
229
230         if (cc == NULL) {
231                 exceptions_throw_nullpointerexception();
232                 return 0;
233         }
234
235         if (!(kc->state & CLASS_LINKED))
236                 if (!link_class(kc))
237                         return 0;
238
239         if (!(cc->state & CLASS_LINKED))
240                 if (!link_class(cc))
241                         return 0;
242
243         return class_isanysubclass(cc, kc);
244 }
245
246
247 /*
248  * Class:     java/lang/Class
249  * Method:    isInterface
250  * Signature: ()Z
251  */
252 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isInterface(JNIEnv *env, java_lang_Class *this)
253 {
254         classinfo *c;
255
256         c = (classinfo *) this;
257
258         return class_is_interface(c);
259 }
260
261
262 #if defined(ENABLE_JAVASE)
263
264 /*
265  * Class:     java/lang/Class
266  * Method:    isPrimitive
267  * Signature: ()Z
268  */
269 s4 _Jv_java_lang_Class_isPrimitive(java_lang_Class *klass)
270 {
271         classinfo *c;
272
273         c = (classinfo *) klass;
274
275         return class_is_primitive(c);
276 }
277
278
279 /*
280  * Class:     java/lang/Class
281  * Method:    getSuperclass
282  * Signature: ()Ljava/lang/Class;
283  */
284 java_lang_Class *_Jv_java_lang_Class_getSuperclass(java_lang_Class *klass)
285 {
286         classinfo *c;
287         classinfo *super;
288
289         c = (classinfo *) klass;
290
291         super = class_get_superclass(c);
292
293         return (java_lang_Class *) super;
294 }
295
296
297 /*
298  * Class:     java/lang/Class
299  * Method:    getInterfaces
300  * Signature: ()[Ljava/lang/Class;
301  */
302 java_objectarray *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
303 {
304         classinfo        *c;
305         java_objectarray *oa;
306
307         c = (classinfo *) klass;
308
309         oa = class_get_interfaces(c);
310
311         return oa;
312 }
313
314
315 /*
316  * Class:     java/lang/Class
317  * Method:    getComponentType
318  * Signature: ()Ljava/lang/Class;
319  */
320 java_lang_Class *_Jv_java_lang_Class_getComponentType(java_lang_Class *klass)
321 {
322         classinfo       *c;
323         classinfo       *comp;
324         arraydescriptor *desc;
325         
326         c = (classinfo *) klass;
327         
328         /* XXX maybe we could find a way to do this without linking. */
329         /* This way should be safe and easy, however.                */
330
331         if (!(c->state & CLASS_LINKED))
332                 if (!link_class(c))
333                         return NULL;
334
335         desc = c->vftbl->arraydesc;
336         
337         if (desc == NULL)
338                 return NULL;
339         
340         if (desc->arraytype == ARRAYTYPE_OBJECT)
341                 comp = desc->componentvftbl->class;
342         else
343                 comp = primitive_class_get_by_type(desc->arraytype);
344                 
345         return (java_lang_Class *) comp;
346 }
347
348
349 /*
350  * Class:     java/lang/Class
351  * Method:    getModifiers
352  * Signature: (Z)I
353  */
354 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
355 {
356         classinfo             *c;
357         classref_or_classinfo  inner;
358         classref_or_classinfo  outer;
359         utf                   *innername;
360         s4                     i;
361
362         c = (classinfo *) klass;
363
364         if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
365                 /* search for passed class as inner class */
366
367                 for (i = 0; i < c->innerclasscount; i++) {
368                         inner = c->innerclass[i].inner_class;
369                         outer = c->innerclass[i].outer_class;
370
371                         /* Check if inner is a classref or a real class and get
372                the name of the structure */
373
374                         innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
375
376                         /* innerclass is this class */
377
378                         if (innername == c->name) {
379                                 /* has the class actually an outer class? */
380
381                                 if (outer.any)
382                                         /* return flags got from the outer class file */
383                                         return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
384                                 else
385                                         return c->flags & ACC_CLASS_REFLECT_MASK;
386                         }
387                 }
388         }
389
390         /* passed class is no inner class or it was not requested */
391
392         return c->flags & ACC_CLASS_REFLECT_MASK;
393 }
394
395
396 /*
397  * Class:     java/lang/Class
398  * Method:    getDeclaringClass
399  * Signature: ()Ljava/lang/Class;
400  */
401 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
402 {
403         classinfo *c;
404
405         c = (classinfo *) klass;
406
407         return (java_lang_Class *) class_get_declaringclass(c);
408 }
409
410
411 /*
412  * Class:     java/lang/Class
413  * Method:    getDeclaredClasses
414  * Signature: (Z)[Ljava/lang/Class;
415  */
416 java_objectarray *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
417 {
418         classinfo             *c;
419         classref_or_classinfo  outer;
420         utf                   *outername;
421         s4                     declaredclasscount;  /* number of declared classes */
422         s4                     pos;                     /* current declared class */
423         java_objectarray      *oa;                   /* array of declared classes */
424         s4                     i;
425
426         c = (classinfo *) klass;
427         declaredclasscount = 0;
428
429         if (!class_is_primitive(c) && (c->name->text[0] != '[')) {
430                 /* determine number of declared classes */
431
432                 for (i = 0; i < c->innerclasscount; i++) {
433                         outer = c->innerclass[i].outer_class;
434
435                         /* check if outer_class is a classref or a real class and
436                get the class name from the structure */
437
438                         outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
439
440                         /* outer class is this class */
441
442                         if ((outername == c->name) &&
443                                 ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
444                                 declaredclasscount++;
445                 }
446         }
447
448         /* allocate Class[] and check for OOM */
449
450         oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
451
452         if (oa == NULL)
453                 return NULL;
454
455         for (i = 0, pos = 0; i < c->innerclasscount; i++) {
456                 outer = c->innerclass[i].outer_class;
457
458                 /* check if outer_class is a classref or a real class and
459                    get the class name from the structure */
460
461                 outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
462
463                 /* outer class is this class */
464
465                 if ((outername == c->name) &&
466                         ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
467                         classinfo *inner;
468
469                         if ((inner = resolve_classref_or_classinfo_eager(
470                                                                                            c->innerclass[i].inner_class,
471                                                                                            false)) == NULL)
472                                 return NULL;
473
474                         if (!(inner->state & CLASS_LINKED))
475                                 if (!link_class(inner))
476                                         return NULL;
477
478                         oa->data[pos++] = inner;
479                 }
480         }
481
482         return oa;
483 }
484
485
486 /*
487  * Class:     java/lang/Class
488  * Method:    getDeclaredFields
489  * Signature: (Z)[Ljava/lang/reflect/Field;
490  */
491 java_objectarray *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
492 {
493         classinfo               *c;
494         java_objectarray        *oa;            /* result: array of field-objects */
495         fieldinfo               *f;
496         java_lang_reflect_Field *rf;
497         s4 public_fields;                    /* number of elements in field-array */
498         s4 pos;
499         s4 i;
500
501         c = (classinfo *) klass;
502
503         /* determine number of fields */
504
505         for (i = 0, public_fields = 0; i < c->fieldscount; i++)
506                 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
507                         public_fields++;
508
509         /* create array of fields */
510
511         oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
512
513         if (oa == NULL)
514                 return NULL;
515
516         /* get the fields and store in the array */
517
518         for (i = 0, pos = 0; i < c->fieldscount; i++) {
519                 f = &(c->fields[i]);
520
521                 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
522                         /* create Field object */
523
524                         rf = reflect_field_new(f);
525
526                         /* store object into array */
527
528                         oa->data[pos++] = rf;
529                 }
530         }
531
532         return oa;
533 }
534
535
536 /*
537  * Class:     java/lang/Class
538  * Method:    getDeclaredMethods
539  * Signature: (Z)[Ljava/lang/reflect/Method;
540  */
541 java_objectarray *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
542 {
543         classinfo                *c;
544         java_lang_reflect_Method *rm;
545         java_objectarray         *oa;          /* result: array of Method-objects */
546         methodinfo               *m;      /* the current method to be represented */
547         s4 public_methods;               /* number of public methods of the class */
548         s4 pos;
549         s4 i;
550
551         c = (classinfo *) klass;
552
553         public_methods = 0;
554
555         /* JOWENN: array classes do not declare methods according to mauve
556            test.  It should be considered, if we should return to my old
557            clone method overriding instead of declaring it as a member
558            function. */
559
560         if (class_is_array(c))
561                 return builtin_anewarray(0, class_java_lang_reflect_Method);
562
563         /* determine number of methods */
564
565         for (i = 0; i < c->methodscount; i++) {
566                 m = &c->methods[i];
567
568                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
569                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
570                         !(m->flags & ACC_MIRANDA))
571                         public_methods++;
572         }
573
574         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
575
576         if (oa == NULL)
577                 return NULL;
578
579         for (i = 0, pos = 0; i < c->methodscount; i++) {
580                 m = &c->methods[i];
581
582                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
583                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
584                         !(m->flags & ACC_MIRANDA)) {
585                         /* create Method object */
586
587                         rm = reflect_method_new(m);
588
589                         /* store object into array */
590
591                         oa->data[pos++] = rm;
592                 }
593         }
594
595         return oa;
596 }
597
598
599 /*
600  * Class:     java/lang/Class
601  * Method:    getDeclaredConstructors
602  * Signature: (Z)[Ljava/lang/reflect/Constructor;
603  */
604 java_objectarray *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
605 {
606         classinfo                     *c;
607         methodinfo                    *m; /* the current method to be represented */
608         java_objectarray              *oa;     /* result: array of Method-objects */
609         java_lang_reflect_Constructor *rc;
610         s4 public_methods;               /* number of public methods of the class */
611         s4 pos;
612         s4 i;
613
614         c = (classinfo *) klass;
615
616         /* determine number of constructors */
617
618         for (i = 0, public_methods = 0; i < c->methodscount; i++) {
619                 m = &c->methods[i];
620
621                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
622                         (m->name == utf_init))
623                         public_methods++;
624         }
625
626         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
627
628         if (oa == NULL)
629                 return NULL;
630
631         for (i = 0, pos = 0; i < c->methodscount; i++) {
632                 m = &c->methods[i];
633
634                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
635                         (m->name == utf_init)) {
636                         /* create Constructor object */
637
638                         rc = reflect_constructor_new(m);
639
640                         /* store object into array */
641
642                         oa->data[pos++] = rc;
643                 }
644         }
645
646         return oa;
647 }
648
649
650 /*
651  * Class:     java/lang/Class
652  * Method:    getClassLoader
653  * Signature: ()Ljava/lang/ClassLoader;
654  */
655 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
656 {
657         classinfo *c;
658
659         c = (classinfo *) klass;
660
661         return (java_lang_ClassLoader *) c->classloader;
662 }
663
664 #endif /* defined(ENABLE_JAVASE) */
665
666
667 /*
668  * Class:     java/lang/Class
669  * Method:    isArray
670  * Signature: ()Z
671  */
672 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
673 {
674         classinfo *c;
675
676         c = (classinfo *) this;
677
678         return class_is_array(c);
679 }
680
681
682 #if defined(ENABLE_JAVASE)
683
684 /*
685  * Class:     java/lang/Class
686  * Method:    throwException
687  * Signature: (Ljava/lang/Throwable;)V
688  */
689 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
690 {
691         java_handle_t *o;
692
693         o = (java_handle_t *) t;
694
695         exceptions_set_exception(o);
696 }
697
698
699 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
700 /*
701  * Class:     java/lang/Class
702  * Method:    getDeclaredAnnotations
703  * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
704  */
705 java_objectarray *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
706 {
707         classinfo                *c            = (classinfo*)klass;
708         static methodinfo        *m_parseAnnotationsIntoArray   = NULL;
709         utf                      *utf_parseAnnotationsIntoArray = NULL;
710         utf                      *utf_desc     = NULL;
711         java_bytearray           *annotations  = NULL;
712         sun_reflect_ConstantPool *constantPool = NULL;
713         uint32_t                  size         = 0;
714         java_lang_Object         *o            = (java_lang_Object*)klass;
715
716         if (c == NULL) {
717                 exceptions_throw_nullpointerexception();
718                 return NULL;
719         }
720         
721         /* Return null for arrays and primitives: */
722         if (class_is_primitive(c) || class_is_array(c)) {
723                 return NULL;
724         }
725
726         if (c->annotations != NULL) {
727                 size        = c->annotations->size;
728                 annotations = builtin_newarray_byte(size);
729
730                 if(annotations != NULL) {
731                         MCOPY(annotations->data, c->annotations->data, uint8_t, size);
732                 }
733         }
734
735         constantPool = 
736                 (sun_reflect_ConstantPool*)native_new_and_init(
737                         class_sun_reflect_ConstantPool);
738         
739         if(constantPool == NULL) {
740                 /* out of memory */
741                 return NULL;
742         }
743
744         LLNI_field_set_ref(constantPool, constantPoolOop, o);
745
746         /* only resolve the method the first time */
747         if (m_parseAnnotationsIntoArray == NULL) {
748                 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
749                 utf_desc = utf_new_char(
750                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
751                         "[Ljava/lang/annotation/Annotation;");
752
753                 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
754                         /* out of memory */
755                         return NULL;
756                 }
757
758                 m_parseAnnotationsIntoArray = class_resolveclassmethod(
759                         class_sun_reflect_annotation_AnnotationParser,
760                         utf_parseAnnotationsIntoArray,
761                         utf_desc,
762                         class_java_lang_Class,
763                         true);
764
765                 if (m_parseAnnotationsIntoArray == NULL) {
766                         /* method not found */
767                         return NULL;
768                 }
769         }
770
771         return vm_call_method(
772                 m_parseAnnotationsIntoArray, NULL,
773                 annotations, constantPool, klass);
774 }
775 #endif
776
777
778 /*
779  * Class:     java/lang/Class
780  * Method:    getEnclosingClass
781  * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
782  */
783 java_lang_Class *_Jv_java_lang_Class_getEnclosingClass(java_lang_Class *klass)
784 {
785         classinfo             *c;
786         classref_or_classinfo  cr;
787         classinfo             *ec;
788
789         c = (classinfo *) klass;
790
791         /* get enclosing class */
792
793         cr = c->enclosingclass;
794
795         if (cr.any == NULL)
796                 return NULL;
797
798         /* resolve the class if necessary */
799
800         if (IS_CLASSREF(cr)) {
801                 ec = resolve_classref_eager(cr.ref);
802
803                 if (ec == NULL)
804                         return NULL;
805         }
806         else
807                 ec = cr.cls;
808
809         return (java_lang_Class *) ec;
810 }
811
812
813 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
814
815    Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
816    _Jv_java_lang_Class_getEnclosingMethod.
817
818 *******************************************************************************/
819
820 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
821 {
822         classref_or_classinfo     cr;
823         constant_nameandtype     *cn;
824         classinfo                *ec;
825         methodinfo               *m;
826
827         /* get enclosing class and method */
828
829         cr = c->enclosingclass;
830         cn = c->enclosingmethod;
831
832         /* check for enclosing class and method */
833
834         if (cr.any == NULL)
835                 return NULL;
836
837         if (cn == NULL)
838                 return NULL;
839
840         /* resolve the class if necessary */
841
842         if (IS_CLASSREF(cr)) {
843                 ec = resolve_classref_eager(cr.ref);
844
845                 if (ec == NULL)
846                         return NULL;
847         }
848         else
849                 ec = cr.cls;
850
851         /* find method in enclosing class */
852
853         m = class_findmethod(ec, cn->name, cn->descriptor);
854
855         if (m == NULL) {
856                 exceptions_throw_internalerror("Enclosing method doesn't exist");
857                 return NULL;
858         }
859
860         return m;
861 }
862
863
864 /*
865  * Class:     java/lang/Class
866  * Method:    getEnclosingConstructor
867  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
868  */
869 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
870 {
871         classinfo                     *c;
872         methodinfo                    *m;
873         java_lang_reflect_Constructor *rc;
874
875         c = (classinfo *) klass;
876
877         /* get enclosing method */
878
879         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
880
881         if (m == NULL)
882                 return NULL;
883
884         /* check for <init> */
885
886         if (m->name != utf_init)
887                 return NULL;
888
889         /* create Constructor object */
890
891         rc = reflect_constructor_new(m);
892
893         return rc;
894 }
895
896
897 /*
898  * Class:     java/lang/Class
899  * Method:    getEnclosingMethod
900  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
901  */
902 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
903 {
904         classinfo                *c;
905         methodinfo               *m;
906         java_lang_reflect_Method *rm;
907
908         c = (classinfo *) klass;
909
910         /* get enclosing method */
911
912         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
913
914         if (m == NULL)
915                 return NULL;
916
917         /* check for <init> */
918
919         if (m->name == utf_init)
920                 return NULL;
921
922         /* create java.lang.reflect.Method object */
923
924         rm = reflect_method_new(m);
925
926         return rm;
927 }
928
929
930 /*
931  * Class:     java/lang/Class
932  * Method:    getClassSignature
933  * Signature: (Ljava/lang/Class;)Ljava/lang/String;
934  */
935 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
936 {
937         classinfo     *c;
938         java_handle_t *o;
939
940         c = (classinfo *) klass;
941
942         if (c->signature == NULL)
943                 return NULL;
944
945         o = javastring_new(c->signature);
946
947         /* in error case o is NULL */
948
949         return (java_lang_String *) o;
950 }
951
952
953 #if 0
954 /*
955  * Class:     java/lang/Class
956  * Method:    isAnonymousClass
957  * Signature: (Ljava/lang/Class;)Z
958  */
959 s4 _Jv_java_lang_Class_isAnonymousClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
960
961
962 /*
963  * Class:     java/lang/VMClass
964  * Method:    isLocalClass
965  * Signature: (Ljava/lang/Class;)Z
966  */
967 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
968
969
970 /*
971  * Class:     java/lang/VMClass
972  * Method:    isMemberClass
973  * Signature: (Ljava/lang/Class;)Z
974  */
975 JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, struct java_lang_Class* par1);
976 #endif
977
978 #endif /* ENABLE_JAVASE */
979
980
981 /*
982  * These are local overrides for various environment variables in Emacs.
983  * Please do not remove this and leave it at the end of the file, where
984  * Emacs will automagically detect them.
985  * ---------------------------------------------------------------------
986  * Local variables:
987  * mode: c
988  * indent-tabs-mode: t
989  * c-basic-offset: 4
990  * tab-width: 4
991  * End:
992  * vim:noexpandtab:sw=4:ts=4:
993  */