* src/vm/string.c (javastring_intern): 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 8357 2007-08-19 22:59:43Z 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
66 #if defined(ENABLE_JAVASE)
67 # include "native/vm/reflect.h"
68 #endif
69
70 #include "toolbox/logging.h"
71
72 #include "vm/builtin.h"
73 #include "vm/exceptions.h"
74 #include "vm/global.h"
75 #include "vm/initialize.h"
76 #include "vm/primitive.h"
77 #include "vm/resolve.h"
78 #include "vm/stringlocal.h"
79
80 #include "vmcore/class.h"
81 #include "vmcore/loader.h"
82
83 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
84 #include "vm/vm.h"
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_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 = (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 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
574         c = LLNI_classinfo_unwrap(klass);
575
576         return (java_lang_ClassLoader *) c->classloader;
577 }
578
579 #endif /* defined(ENABLE_JAVASE) */
580
581
582 /*
583  * Class:     java/lang/Class
584  * Method:    isArray
585  * Signature: ()Z
586  */
587 JNIEXPORT int32_t JNICALL _Jv_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
588 {
589         classinfo *c;
590
591         c = LLNI_classinfo_unwrap(this);
592
593         return class_is_array(c);
594 }
595
596
597 #if defined(ENABLE_JAVASE)
598
599 /*
600  * Class:     java/lang/Class
601  * Method:    throwException
602  * Signature: (Ljava/lang/Throwable;)V
603  */
604 void _Jv_java_lang_Class_throwException(java_lang_Throwable *t)
605 {
606         java_handle_t *o;
607
608         o = (java_handle_t *) t;
609
610         exceptions_set_exception(o);
611 }
612
613
614 #if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
615 /*
616  * Class:     java/lang/Class
617  * Method:    getDeclaredAnnotations
618  * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
619  */
620 java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
621 {
622         classinfo                *c               = LLNI_classinfo_unwrap(klass);
623         static methodinfo        *m_parseAnnotationsIntoArray   = NULL;
624         utf                      *utf_parseAnnotationsIntoArray = NULL;
625         utf                      *utf_desc        = NULL;
626         java_handle_bytearray_t  *annotations     = NULL;
627         sun_reflect_ConstantPool *constantPool    = NULL;
628         uint32_t                  size            = 0;
629         java_lang_Object         *constantPoolOop = (java_lang_Object*)klass;
630
631         if (c == NULL) {
632                 exceptions_throw_nullpointerexception();
633                 return NULL;
634         }
635         
636         /* Return null for arrays and primitives: */
637         if (class_is_primitive(c) || class_is_array(c)) {
638                 return NULL;
639         }
640
641         if (c->annotations != NULL) {
642                 size        = c->annotations->size;
643                 annotations = builtin_newarray_byte(size);
644
645                 if(annotations != NULL) {
646                         MCOPY(annotations->data, c->annotations->data, uint8_t, size);
647                 }
648         }
649
650         constantPool = 
651                 (sun_reflect_ConstantPool*)native_new_and_init(
652                         class_sun_reflect_ConstantPool);
653         
654         if(constantPool == NULL) {
655                 /* out of memory */
656                 return NULL;
657         }
658
659         LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
660
661         /* only resolve the method the first time */
662         if (m_parseAnnotationsIntoArray == NULL) {
663                 utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
664                 utf_desc = utf_new_char(
665                         "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
666                         "[Ljava/lang/annotation/Annotation;");
667
668                 if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
669                         /* out of memory */
670                         return NULL;
671                 }
672
673                 m_parseAnnotationsIntoArray = class_resolveclassmethod(
674                         class_sun_reflect_annotation_AnnotationParser,
675                         utf_parseAnnotationsIntoArray,
676                         utf_desc,
677                         class_java_lang_Class,
678                         true);
679
680                 if (m_parseAnnotationsIntoArray == NULL) {
681                         /* method not found */
682                         return NULL;
683                 }
684         }
685
686         return (java_handle_objectarray_t*)vm_call_method(
687                 m_parseAnnotationsIntoArray, NULL,
688                 annotations, constantPool, klass);
689 }
690 #endif
691
692
693 /* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
694
695    Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
696    _Jv_java_lang_Class_getEnclosingMethod.
697
698 *******************************************************************************/
699
700 static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
701 {
702         constant_nameandtype *cn;
703         classinfo            *ec;
704         methodinfo           *m;
705
706         /* get enclosing class and method */
707
708         ec = class_get_enclosingclass(c);
709         cn = c->enclosingmethod;
710
711         /* check for enclosing class and method */
712
713         if (ec == NULL)
714                 return NULL;
715
716         if (cn == NULL)
717                 return NULL;
718
719         /* find method in enclosing class */
720
721         m = class_findmethod(ec, cn->name, cn->descriptor);
722
723         if (m == NULL) {
724                 exceptions_throw_internalerror("Enclosing method doesn't exist");
725                 return NULL;
726         }
727
728         return m;
729 }
730
731
732 /*
733  * Class:     java/lang/Class
734  * Method:    getEnclosingConstructor
735  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
736  */
737 java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
738 {
739         classinfo                     *c;
740         methodinfo                    *m;
741         java_lang_reflect_Constructor *rc;
742
743         c = LLNI_classinfo_unwrap(klass);
744
745         /* get enclosing method */
746
747         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
748
749         if (m == NULL)
750                 return NULL;
751
752         /* check for <init> */
753
754         if (m->name != utf_init)
755                 return NULL;
756
757         /* create Constructor object */
758
759         rc = reflect_constructor_new(m);
760
761         return rc;
762 }
763
764
765 /*
766  * Class:     java/lang/Class
767  * Method:    getEnclosingMethod
768  * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
769  */
770 java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
771 {
772         classinfo                *c;
773         methodinfo               *m;
774         java_lang_reflect_Method *rm;
775
776         c = LLNI_classinfo_unwrap(klass);
777
778         /* get enclosing method */
779
780         m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
781
782         if (m == NULL)
783                 return NULL;
784
785         /* check for <init> */
786
787         if (m->name == utf_init)
788                 return NULL;
789
790         /* create java.lang.reflect.Method object */
791
792         rm = reflect_method_new(m);
793
794         return rm;
795 }
796
797
798 /*
799  * Class:     java/lang/Class
800  * Method:    getClassSignature
801  * Signature: (Ljava/lang/Class;)Ljava/lang/String;
802  */
803 java_lang_String *_Jv_java_lang_Class_getClassSignature(java_lang_Class* klass)
804 {
805         classinfo     *c;
806         java_handle_t *o;
807
808         c = LLNI_classinfo_unwrap(klass);
809
810         if (c->signature == NULL)
811                 return NULL;
812
813         o = javastring_new(c->signature);
814
815         /* in error case o is NULL */
816
817         return (java_lang_String *) o;
818 }
819
820 #endif /* ENABLE_JAVASE */
821
822
823 /*
824  * These are local overrides for various environment variables in Emacs.
825  * Please do not remove this and leave it at the end of the file, where
826  * Emacs will automagically detect them.
827  * ---------------------------------------------------------------------
828  * Local variables:
829  * mode: c
830  * indent-tabs-mode: t
831  * c-basic-offset: 4
832  * tab-width: 4
833  * End:
834  * vim:noexpandtab:sw=4:ts=4:
835  */