* Merged with default branch at rev 16f3633aaa5a.
[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/builtin.h"
71 #include "vm/exceptions.h"
72 #include "vm/global.h"
73 #include "vm/initialize.h"
74 #include "vm/primitive.h"
75 #include "vm/resolve.h"
76 #include "vm/stringlocal.h"
77
78 #include "vmcore/class.h"
79 #include "vmcore/loader.h"
80
81 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
82 #include "native/include/sun_reflect_ConstantPool.h"
83
84 #include "vm/vm.h"
85
86 #include "vmcore/annotation.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_handle_chararray_t *ca;
99         u4                       i;
100
101         c = LLNI_classinfo_unwrap(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 < LLNI_array_size(ca); i++) {
115                 if (LLNI_array_direct(ca, i) == '/')
116                         LLNI_array_direct(ca, 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 = loader_hashtable_classloader_add((java_handle_t *) 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 LLNI_classinfo_wrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(klass);
228         cc = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(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 = LLNI_classinfo_unwrap(klass);
290
291         super = class_get_superclass(c);
292
293         return LLNI_classinfo_wrap(super);
294 }
295
296
297 /*
298  * Class:     java/lang/Class
299  * Method:    getInterfaces
300  * Signature: ()[Ljava/lang/Class;
301  */
302 java_handle_objectarray_t *_Jv_java_lang_Class_getInterfaces(java_lang_Class *klass)
303 {
304         classinfo                 *c;
305         java_handle_objectarray_t *oa;
306
307         c = LLNI_classinfo_unwrap(klass);
308
309         oa = class_get_interfaces(c);
310
311         return oa;
312 }
313
314
315 /*
316  * Class:     java/lang/Class
317  * Method:    getModifiers
318  * Signature: (Z)I
319  */
320 s4 _Jv_java_lang_Class_getModifiers(java_lang_Class *klass, s4 ignoreInnerClassesAttrib)
321 {
322         classinfo             *c;
323         classref_or_classinfo  inner;
324         classref_or_classinfo  outer;
325         utf                   *innername;
326         s4                     i;
327
328         c = LLNI_classinfo_unwrap(klass);
329
330         if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
331                 /* search for passed class as inner class */
332
333                 for (i = 0; i < c->innerclasscount; i++) {
334                         inner = c->innerclass[i].inner_class;
335                         outer = c->innerclass[i].outer_class;
336
337                         /* Check if inner is a classref or a real class and get
338                the name of the structure */
339
340                         innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
341
342                         /* innerclass is this class */
343
344                         if (innername == c->name) {
345                                 /* has the class actually an outer class? */
346
347                                 if (outer.any)
348                                         /* return flags got from the outer class file */
349                                         return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
350                                 else
351                                         return c->flags & ACC_CLASS_REFLECT_MASK;
352                         }
353                 }
354         }
355
356         /* passed class is no inner class or it was not requested */
357
358         return c->flags & ACC_CLASS_REFLECT_MASK;
359 }
360
361
362 /*
363  * Class:     java/lang/Class
364  * Method:    getDeclaringClass
365  * Signature: ()Ljava/lang/Class;
366  */
367 java_lang_Class *_Jv_java_lang_Class_getDeclaringClass(java_lang_Class *klass)
368 {
369         classinfo *c;
370         classinfo *dc;
371
372         c = LLNI_classinfo_unwrap(klass);
373
374         dc = class_get_declaringclass(c);
375
376         return LLNI_classinfo_wrap(dc);
377 }
378
379
380 /*
381  * Class:     java/lang/Class
382  * Method:    getDeclaredClasses
383  * Signature: (Z)[Ljava/lang/Class;
384  */
385 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredClasses(java_lang_Class *klass, s4 publicOnly)
386 {
387         classinfo                 *c;
388         java_handle_objectarray_t *oa;
389
390         c = LLNI_classinfo_unwrap(klass);
391
392         oa = class_get_declaredclasses(c, publicOnly);
393
394         return oa;
395 }
396
397
398 /*
399  * Class:     java/lang/Class
400  * Method:    getDeclaredFields
401  * Signature: (Z)[Ljava/lang/reflect/Field;
402  */
403 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
404 {
405         classinfo                 *c;
406         java_handle_objectarray_t *oa;          /* result: array of field-objects */
407         fieldinfo                 *f;
408         java_lang_reflect_Field   *rf;
409         s4 public_fields;                    /* number of elements in field-array */
410         s4 pos;
411         s4 i;
412
413         c = LLNI_classinfo_unwrap(klass);
414
415         /* determine number of fields */
416
417         for (i = 0, public_fields = 0; i < c->fieldscount; i++)
418                 if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
419                         public_fields++;
420
421         /* create array of fields */
422
423         oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
424
425         if (oa == NULL)
426                 return NULL;
427
428         /* get the fields and store in the array */
429
430         for (i = 0, pos = 0; i < c->fieldscount; i++) {
431                 f = &(c->fields[i]);
432
433                 if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
434                         /* create Field object */
435
436                         rf = reflect_field_new(f);
437
438                         /* store object into array */
439
440                         LLNI_objectarray_element_set(oa, pos, rf);
441                         pos++;
442                 }
443         }
444
445         return oa;
446 }
447
448
449 /*
450  * Class:     java/lang/Class
451  * Method:    getDeclaredMethods
452  * Signature: (Z)[Ljava/lang/reflect/Method;
453  */
454 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
455 {
456         classinfo                 *c;
457         java_lang_reflect_Method  *rm;
458         java_handle_objectarray_t *oa;         /* result: array of Method-objects */
459         methodinfo                *m;     /* the current method to be represented */
460         s4 public_methods;               /* number of public methods of the class */
461         s4 pos;
462         s4 i;
463
464         c = LLNI_classinfo_unwrap(klass);
465
466         public_methods = 0;
467
468         /* JOWENN: array classes do not declare methods according to mauve
469            test.  It should be considered, if we should return to my old
470            clone method overriding instead of declaring it as a member
471            function. */
472
473         if (class_is_array(c))
474                 return builtin_anewarray(0, class_java_lang_reflect_Method);
475
476         /* determine number of methods */
477
478         for (i = 0; i < c->methodscount; i++) {
479                 m = &c->methods[i];
480
481                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
482                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
483                         !(m->flags & ACC_MIRANDA))
484                         public_methods++;
485         }
486
487         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
488
489         if (oa == NULL)
490                 return NULL;
491
492         for (i = 0, pos = 0; i < c->methodscount; i++) {
493                 m = &c->methods[i];
494
495                 if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
496                         ((m->name != utf_init) && (m->name != utf_clinit)) &&
497                         !(m->flags & ACC_MIRANDA)) {
498                         /* create Method object */
499
500                         rm = reflect_method_new(m);
501
502                         /* store object into array */
503
504                         LLNI_objectarray_element_set(oa, pos, rm);
505                         pos++;
506                 }
507         }
508
509         return oa;
510 }
511
512
513 /*
514  * Class:     java/lang/Class
515  * Method:    getDeclaredConstructors
516  * Signature: (Z)[Ljava/lang/reflect/Constructor;
517  */
518 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
519 {
520         classinfo                     *c;
521         methodinfo                    *m; /* the current method to be represented */
522         java_handle_objectarray_t     *oa;     /* result: array of Method-objects */
523         java_lang_reflect_Constructor *rc;
524         s4 public_methods;               /* number of public methods of the class */
525         s4 pos;
526         s4 i;
527
528         c = LLNI_classinfo_unwrap(klass);
529
530         /* determine number of constructors */
531
532         for (i = 0, public_methods = 0; i < c->methodscount; i++) {
533                 m = &c->methods[i];
534
535                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
536                         (m->name == utf_init))
537                         public_methods++;
538         }
539
540         oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
541
542         if (oa == NULL)
543                 return NULL;
544
545         for (i = 0, pos = 0; i < c->methodscount; i++) {
546                 m = &c->methods[i];
547
548                 if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
549                         (m->name == utf_init)) {
550                         /* create Constructor object */
551
552                         rc = reflect_constructor_new(m);
553
554                         /* store object into array */
555
556                         LLNI_objectarray_element_set(oa, pos, rc);
557                         pos++;
558                 }
559         }
560
561         return oa;
562 }
563
564
565 /*
566  * Class:     java/lang/Class
567  * Method:    getClassLoader
568  * Signature: ()Ljava/lang/ClassLoader;
569  */
570 java_lang_ClassLoader *_Jv_java_lang_Class_getClassLoader(java_lang_Class *klass)
571 {
572         classinfo   *c;
573         classloader *cl;
574
575         c  = LLNI_classinfo_unwrap(klass);
576         cl = c->classloader;
577
578         if (cl == NULL)
579                 return NULL;
580         else
581 #if defined(ENABLE_HANDLES)
582                 /* the classloader entry itself is the handle */
583                 return (java_lang_ClassLoader *) cl;
584 #else
585                 /* get the object out of the classloader entry */
586                 return (java_lang_ClassLoader *) cl->object;
587 #endif
588 }
589
590 #endif /* defined(ENABLE_JAVASE) */
591
592
593 /*
594  * Class:     java/lang/Class
595  * Method:    isArray
596  * Signature: ()Z
597  */
598 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
599 {
600         classinfo *c;
601
602         c = LLNI_classinfo_unwrap(this);
603
604         return class_is_array(c);
605 }
606
607
608 #if defined(ENABLE_JAVASE)
609
610 /*
611  * Class:     java/lang/Class
612  * Method:    throwException
613  * Signature: (Ljava/lang/Throwable;)V
614  */
615 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
616 {
617         java_handle_t *o;
618
619         o = (java_handle_t *) t;
620
621         exceptions_set_exception(o);
622 }
623
624
625 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
626 /*
627  * Class:     java/lang/Class
628  * Method:    getDeclaredAnnotations
629  * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
630  */
631 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
632 {
633         classinfo                *c               = NULL;
634         static methodinfo        *m_parseAnnotationsIntoArray   = NULL;
635         utf                      *utf_parseAnnotationsIntoArray = NULL;
636         utf                      *utf_desc        = NULL;
637         java_handle_bytearray_t  *annotations     = NULL;
638         sun_reflect_ConstantPool *constantPool    = NULL;
639         java_lang_Object         *constantPoolOop = (java_lang_Object*)klass;
640
641         if (klass == NULL) {
642                 exceptions_throw_nullpointerexception();
643                 return NULL;
644         }
645         
646         c = LLNI_classinfo_unwrap(klass);
647
648         /* get annotations: */
649         annotations = class_get_annotations(c);
650
651         constantPool = 
652                 (sun_reflect_ConstantPool*)native_new_and_init(
653                         class_sun_reflect_ConstantPool);
654         
655         if(constantPool == NULL) {
656                 /* out of memory */
657                 return NULL;
658         }
659
660         LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
661
662         /* only resolve the method the first time */
663         if (m_parseAnnotationsIntoArray == NULL) {
664                 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
665                 utf_desc = utf_new_char(
666                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
667                         "[Ljava/lang/annotation/Annotation;");
668
669                 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
670                         /* out of memory */
671                         return NULL;
672                 }
673
674                 m_parseAnnotationsIntoArray = class_resolveclassmethod(
675                         class_sun_reflect_annotation_AnnotationParser,
676                         utf_parseAnnotationsIntoArray,
677                         utf_desc,
678                         class_java_lang_Class,
679                         true);
680
681                 if (m_parseAnnotationsIntoArray == NULL) {
682                         /* method not found */
683                         return NULL;
684                 }
685         }
686
687         return (java_handle_objectarray_t*)vm_call_method(
688                 m_parseAnnotationsIntoArray, NULL,
689                 annotations, constantPool, klass);
690 }
691 #endif
692
693
694 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
695
696    Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
697    _Jv_java_lang_Class_getEnclosingMethod.
698
699 *******************************************************************************/
700
701 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
702 {
703         constant_nameandtype *cn;
704         classinfo            *ec;
705         methodinfo           *m;
706
707         /* get enclosing class and method */
708
709         ec = class_get_enclosingclass(c);
710         cn = c->enclosingmethod;
711
712         /* check for enclosing class and method */
713
714         if (ec == NULL)
715                 return NULL;
716
717         if (cn == NULL)
718                 return NULL;
719
720         /* find method in enclosing class */
721
722         m = class_findmethod(ec, cn->name, cn->descriptor);
723
724         if (m == NULL) {
725                 exceptions_throw_internalerror("Enclosing method doesn't exist");
726                 return NULL;
727         }
728
729         return m;
730 }
731
732
733 /*
734  * Class:     java/lang/Class
735  * Method:    getEnclosingConstructor
736  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
737  */
738 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
739 {
740         classinfo                     *c;
741         methodinfo                    *m;
742         java_lang_reflect_Constructor *rc;
743
744         c = LLNI_classinfo_unwrap(klass);
745
746         /* get enclosing method */
747
748         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
749
750         if (m == NULL)
751                 return NULL;
752
753         /* check for <init> */
754
755         if (m->name != utf_init)
756                 return NULL;
757
758         /* create Constructor object */
759
760         rc = reflect_constructor_new(m);
761
762         return rc;
763 }
764
765
766 /*
767  * Class:     java/lang/Class
768  * Method:    getEnclosingMethod
769  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
770  */
771 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
772 {
773         classinfo                *c;
774         methodinfo               *m;
775         java_lang_reflect_Method *rm;
776
777         c = LLNI_classinfo_unwrap(klass);
778
779         /* get enclosing method */
780
781         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
782
783         if (m == NULL)
784                 return NULL;
785
786         /* check for <init> */
787
788         if (m->name == utf_init)
789                 return NULL;
790
791         /* create java.lang.reflect.Method object */
792
793         rm = reflect_method_new(m);
794
795         return rm;
796 }
797
798
799 /*
800  * Class:     java/lang/Class
801  * Method:    getClassSignature
802  * Signature: (Ljava/lang/Class;)Ljava/lang/String;
803  */
804 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
805 {
806         classinfo     *c;
807         java_handle_t *o;
808
809         c = LLNI_classinfo_unwrap(klass);
810
811         if (c->signature == NULL)
812                 return NULL;
813
814         o = javastring_new(c->signature);
815
816         /* in error case o is NULL */
817
818         return (java_lang_String *) o;
819 }
820
821 #endif /* ENABLE_JAVASE */
822
823
824 /*
825  * These are local overrides for various environment variables in Emacs.
826  * Please do not remove this and leave it at the end of the file, where
827  * Emacs will automagically detect them.
828  * ---------------------------------------------------------------------
829  * Local variables:
830  * mode: c
831  * indent-tabs-mode: t
832  * c-basic-offset: 4
833  * tab-width: 4
834  * End:
835  * vim:noexpandtab:sw=4:ts=4:
836  */