* Removed all Id tags.
[cacao.git] / src / vmcore / class.c
index 2f71a71800556ccfa46e84fa8fc9310f6c643ca4..3b2b0a377de732b4b2825bbc374ad81bef54b511 100644 (file)
@@ -22,8 +22,6 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: class.c 8277 2007-08-08 16:42:11Z michi $
-
 */
 
 
 
 #include "mm/memory.h"
 
+#include "native/llni.h"
+
 #include "threads/lock-common.h"
 
 #include "toolbox/logging.h"
 
+#include "vm/array.h"
+#include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
 #include "vm/resolve.h"
@@ -290,7 +292,7 @@ void class_postset_header_vftbl(void)
 
 *******************************************************************************/
 
-classinfo *class_define(utf *name, java_objectheader *cl, int32_t length, const uint8_t *data)
+classinfo *class_define(utf *name, classloader *cl, int32_t length, const uint8_t *data, java_handle_t *pd)
 {
        classinfo   *c;
        classinfo   *r;
@@ -356,6 +358,14 @@ classinfo *class_define(utf *name, java_objectheader *cl, int32_t length, const
                return NULL;
        }
 
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_SUN)
+       /* Store the protection domain. */
+
+       c->protectiondomain = pd;
+# endif
+#endif
+
        /* Store the newly defined class in the class cache. This call
           also checks whether a class of the same name has already been
           defined by the same defining loader, and if so, replaces the
@@ -516,11 +526,16 @@ static bool class_load_attribute_enclosingmethod(classbuffer *cb)
 
 bool class_load_attributes(classbuffer *cb)
 {
-       classinfo *c;
-       u4         i, j;
-       u2         attributes_count;
-       u2         attribute_name_index;
-       utf       *attribute_name;
+       classinfo             *c;
+       uint16_t               attributes_count;
+       uint16_t               attribute_name_index;
+       utf                   *attribute_name;
+       innerclassinfo        *info;
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *name;
+       uint16_t               flags;
+       int                    i, j;
 
        c = cb->class;
 
@@ -570,19 +585,45 @@ bool class_load_attributes(classbuffer *cb)
                        for (j = 0; j < c->innerclasscount; j++) {
                                /* The innerclass structure contains a class with an encoded
                                   name, its defining scope, its simple name and a bitmask of
-                                  the access flags. If an inner class is not a member, its
-                                  outer_class is NULL, if a class is anonymous, its name is
-                                  NULL. */
+                                  the access flags. */
                                                                
-                               innerclassinfo *info = c->innerclass + j;
-
-                               info->inner_class.ref =
-                                       innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
-                               info->outer_class.ref =
-                                       innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
-                               info->name =
-                                       innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
-                               info->flags = suck_u2(cb);
+                               info = c->innerclass + j;
+
+                               inner.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               outer.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               name      = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+                               flags     = suck_u2(cb);
+
+                               /* If the current inner-class is the currently loaded
+                                  class check for some special flags. */
+
+                               if (inner.ref->name == c->name) {
+                                       /* If an inner-class is not a member, its
+                                          outer-class is NULL. */
+
+                                       if (outer.ref != NULL) {
+                                               c->flags |= ACC_CLASS_MEMBER;
+
+                                               /* A member class doesn't have an
+                                                  EnclosingMethod attribute, so set the
+                                                  enclosing-class to be the same as the
+                                                  declaring-class. */
+
+                                               c->declaringclass = outer;
+                                               c->enclosingclass = outer;
+                                       }
+
+                                       /* If an inner-class is anonymous, its name is
+                                          NULL. */
+
+                                       if (name == NULL)
+                                               c->flags |= ACC_CLASS_ANONYMOUS;
+                               }
+
+                               info->inner_class = inner;
+                               info->outer_class = outer;
+                               info->name        = name;
+                               info->flags       = flags;
                        }
                }
                else if (attribute_name == utf_SourceFile) {
@@ -822,8 +863,8 @@ void class_free(classinfo *c)
 
 *******************************************************************************/
 
-static classinfo *get_array_class(utf *name,java_objectheader *initloader,
-                                                                                       java_objectheader *defloader,bool link)
+static classinfo *get_array_class(utf *name,classloader *initloader,
+                                                                                       classloader *defloader,bool link)
 {
        classinfo *c;
        
@@ -863,7 +904,7 @@ static classinfo *get_array_class(utf *name,java_objectheader *initloader,
 
 classinfo *class_array_of(classinfo *component, bool link)
 {
-       java_objectheader *cl;
+       classloader       *cl;
     s4                 namelen;
     char              *namebuf;
        utf               *u;
@@ -1498,11 +1539,12 @@ static classinfo *class_resolve_superclass(classinfo *c)
        if (c->super.any == NULL)
                return NULL;
 
-       /* Do we have a super class reference or is it already
-          resolved? */
+       /* Check if the super class is a reference. */
 
        if (IS_CLASSREF(c->super)) {
+               /* XXX I'm very sure this is not correct. */
                super = resolve_classref_or_classinfo_eager(c->super, true);
+/*             super = resolve_classref_or_classinfo_eager(c->super, false); */
 
                if (super == NULL)
                        return NULL;
@@ -1531,7 +1573,13 @@ bool class_issubclass(classinfo *sub, classinfo *super)
                if (sub == super)
                        return true;
 
-               sub = class_resolve_superclass(sub);
+/*             sub = class_resolve_superclass(sub); */
+               if (sub->super.any == NULL)
+                       return false;
+
+               assert(IS_CLASSREF(sub->super) == 0);
+
+               sub = sub->super.cls;
        }
 }
 
@@ -1601,6 +1649,21 @@ bool class_is_primitive(classinfo *c)
 }
 
 
+/* class_is_anonymousclass *****************************************************
+
+   Checks if the given class is an anonymous class.
+
+*******************************************************************************/
+
+bool class_is_anonymousclass(classinfo *c)
+{
+       if (c->flags & ACC_CLASS_ANONYMOUS)
+               return true;
+
+       return false;
+}
+
+
 /* class_is_array **************************************************************
 
    Checks if the given class is an array class.
@@ -1632,6 +1695,36 @@ bool class_is_interface(classinfo *c)
 }
 
 
+/* class_is_localclass *********************************************************
+
+   Checks if the given class is a local class.
+
+*******************************************************************************/
+
+bool class_is_localclass(classinfo *c)
+{
+       if ((c->enclosingmethod != NULL) && !class_is_anonymousclass(c))
+               return true;
+
+       return false;
+}
+
+
+/* class_is_memberclass ********************************************************
+
+   Checks if the given class is a member class.
+
+*******************************************************************************/
+
+bool class_is_memberclass(classinfo *c)
+{
+       if (c->flags & ACC_CLASS_MEMBER)
+               return true;
+
+       return false;
+}
+
+
 /* class_get_superclass ********************************************************
 
    Return the super class of the given class.  If the super-field is a
@@ -1662,6 +1755,127 @@ classinfo *class_get_superclass(classinfo *c)
 }
 
 
+/* class_get_componenttype *****************************************************
+
+   Return the component class of the given class.  If the given class
+   is not an array, return NULL.
+
+*******************************************************************************/
+
+classinfo *class_get_componenttype(classinfo *c)
+{
+       classinfo       *component;
+       arraydescriptor *ad;
+       
+       /* XXX maybe we could find a way to do this without linking. */
+       /* This way should be safe and easy, however.                */
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+
+       ad = c->vftbl->arraydesc;
+       
+       if (ad == NULL)
+               return NULL;
+       
+       if (ad->arraytype == ARRAYTYPE_OBJECT)
+               component = ad->componentvftbl->class;
+       else
+               component = primitive_class_get_by_type(ad->arraytype);
+               
+       return component;
+}
+
+
+/* class_get_declaredclasses ***************************************************
+
+   Return an array of declared classes of the given class.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
+{
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *outername;
+       int                    declaredclasscount;  /* number of declared classes */
+       int                    pos;                     /* current declared class */
+       java_handle_objectarray_t *oa;               /* array of declared classes */
+       int                    i;
+       classinfo             *ic;
+
+       declaredclasscount = 0;
+
+       if (!class_is_primitive(c) && !class_is_array(c)) {
+               /* Determine number of declared classes. */
+
+               for (i = 0; i < c->innerclasscount; i++) {
+                       /* Get outer-class.  If the inner-class is not a member
+                          class, the outer-class is NULL. */
+
+                       outer = c->innerclass[i].outer_class;
+
+                       if (outer.any == NULL)
+                               continue;
+
+                       /* Check if outer-class is a classref or a real class and
+               get the class name from the structure. */
+
+                       outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+                       /* Outer class is this class. */
+
+                       if ((outername == c->name) &&
+                               ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
+                               declaredclasscount++;
+               }
+       }
+
+       /* Allocate Class[] and check for OOM. */
+
+       oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
+
+       if (oa == NULL)
+               return NULL;
+
+       for (i = 0, pos = 0; i < c->innerclasscount; i++) {
+               inner = c->innerclass[i].inner_class;
+               outer = c->innerclass[i].outer_class;
+
+               /* Get outer-class.  If the inner-class is not a member class,
+                  the outer-class is NULL. */
+
+               if (outer.any == NULL)
+                       continue;
+
+               /* Check if outer_class is a classref or a real class and get
+                  the class name from the structure. */
+
+               outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+               /* Outer class is this class. */
+
+               if ((outername == c->name) &&
+                       ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
+
+                       ic = resolve_classref_or_classinfo_eager(inner, false);
+
+                       if (ic == NULL)
+                               return NULL;
+
+                       if (!(ic->state & CLASS_LINKED))
+                               if (!link_class(ic))
+                                       return NULL;
+
+                       LLNI_array_direct(oa, pos++) = (java_object_t *) ic;
+               }
+       }
+
+       return oa;
+}
+
+
 /* class_get_declaringclass ****************************************************
 
    If the class or interface given is a member of another class,
@@ -1672,52 +1886,137 @@ classinfo *class_get_superclass(classinfo *c)
 
 classinfo *class_get_declaringclass(classinfo *c)
 {
-       classref_or_classinfo  innercr;
-       utf                   *innername;
-       classref_or_classinfo  outercr;
-       classinfo             *outer;
-       int16_t                i;
+       classref_or_classinfo  cr;
+       classinfo             *dc;
+
+       /* Get declaring class. */
+
+       cr = c->declaringclass;
+
+       if (cr.any == NULL)
+               return NULL;
+
+       /* Resolve the class if necessary. */
+
+       if (IS_CLASSREF(cr)) {
+/*             dc = resolve_classref_eager(cr.ref); */
+               dc = resolve_classref_or_classinfo_eager(cr, true);
+
+               if (dc == NULL)
+                       return NULL;
+
+               /* Store the resolved class in the class structure. */
+
+               cr.cls = dc;
+       }
+
+       dc = cr.cls;
+
+       return dc;
+}
+
+
+/* class_get_enclosingclass ****************************************************
+
+   Return the enclosing class for the given class.
+
+*******************************************************************************/
+
+classinfo *class_get_enclosingclass(classinfo *c)
+{
+       classref_or_classinfo  cr;
+       classinfo             *ec;
+
+       /* Get enclosing class. */
 
-       /* return NULL for arrayclasses and primitive classes */
+       cr = c->enclosingclass;
 
-       if (class_is_primitive(c) || (c->name->text[0] == '['))
+       if (cr.any == NULL)
                return NULL;
 
-       /* no innerclasses exist */
+       /* Resolve the class if necessary. */
+
+       if (IS_CLASSREF(cr)) {
+/*             ec = resolve_classref_eager(cr.ref); */
+               ec = resolve_classref_or_classinfo_eager(cr, true);
+
+               if (ec == NULL)
+                       return NULL;
+
+               /* Store the resolved class in the class structure. */
+
+               cr.cls = ec;
+       }
+
+       ec = cr.cls;
+
+       return ec;
+}
+
+
+/* class_get_interfaces ********************************************************
+
+   Return an array of interfaces of the given class.
+
+*******************************************************************************/
 
-       if (c->innerclasscount == 0)
+java_handle_objectarray_t *class_get_interfaces(classinfo *c)
+{
+       classinfo                 *ic;
+       java_handle_objectarray_t *oa;
+       u4                         i;
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+
+       oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
+
+       if (oa == NULL)
                return NULL;
 
-       for (i = 0; i < c->innerclasscount; i++) {
-               /* Check if inner_class is a classref or a real class and get
-                  the class name from the structure. */
+       for (i = 0; i < c->interfacescount; i++) {
+               ic = c->interfaces[i].cls;
 
-               innercr = c->innerclass[i].inner_class;
+               LLNI_array_direct(oa, i) = (java_object_t *) ic;
+       }
 
-               innername = IS_CLASSREF(innercr) ?
-                       innercr.ref->name : innercr.cls->name;
+       return oa;
+}
 
-               /* Is the current innerclass this class? */
 
-               if (innername == c->name) {
-                       /* Maybe the outer class is not loaded yet. */
+/* class_get_annotations *******************************************************
 
-                       outercr = c->innerclass[i].outer_class;
+   Return the unparsed declared annotations in an byte array
+   of the given class (or NULL if there aren't any).
 
-                       outer = resolve_classref_or_classinfo_eager(outercr, false);
+*******************************************************************************/
 
-                       if (outer == NULL)
-                               return NULL;
+java_handle_bytearray_t *class_get_annotations(classinfo *c)
+{
+#if defined(ENABLE_ANNOTATIONS)
+       java_handle_bytearray_t  *annotations = NULL;
+       uint32_t                  size        = 0;
+       
+       /* Return null for arrays and primitives: */
+       if (class_is_primitive(c) || class_is_array(c)) {
+               return NULL;
+       }
 
-                       if (!(outer->state & CLASS_LINKED))
-                               if (!link_class(outer))
-                                       return NULL;
+       /* copy the annotations into a java byte array: */
+       if (c->annotations != NULL) {
+               size        = c->annotations->size;
+               annotations = builtin_newarray_byte(size);
 
-                       return outer;
+               if(annotations != NULL) {
+                       MCOPY(annotations->data, c->annotations->data, uint8_t, size);
                }
        }
 
+       return annotations;
+#else
        return NULL;
+#endif
 }