2005/5/9

     
 

Class.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/Class.cpp,v 1.75 2005/04/15 14:51:18 kommer Exp $

#include <acdk.h>

#include "Integer.h"
#include "Boolean.h"
#include "Character.h"
#include "Byte.h"
#include "Long.h"
#include "Short.h"
#include "Float.h"
#include "Double.h"
#include "Package.h"

#include "System.h"

#include "ObjectArrayImpl.h"
#include "ClassLoader.h"

#ifndef ACDK_NOMETAINFO
//extern dmi::ClazzInfo ObjectArray_clazzInfo;
extern dmi::ClazzInfo BasicArray_clazzInfo;
#endif// ACDK_NOMETAINFO

#include "ClassNotFoundException.h"
#include "Exception.h"
#include "IllegalArgumentException.h"
#include "InstantiationException.h"
#include "UnsupportedOperationException.h"
#include "ParamsMismatchException.h"
#include "reflect/Method.h"
#include "reflect/Unit.h"
#include <acdk/io/ObjectWriter.h>
#include <acdk/io/ObjectReader.h>
#include <acdk/lang/dmi/AcdkStdWeakTypeDmiClient.h>

namespace acdk {
namespace lang {
namespace dmi {

#ifndef ACDK_NOMETAINFO
extern ClazzInfo* _arrayClazzRoot;
#endif //ACDK_NOMETAINFO

} // dmi
}
}

namespace acdk {
namespace lang {


using dmi::ClazzInfo;
using dmi::ClazzMethodArgInfo;
using dmi::UnitInfo;



Class::Class(const ClazzInfo* clazzInfo)
: acdk::lang::Object()
, _objectClazzInfo(clazzInfo)
{
}

#ifdef ACDK_MT
sys::static_mutex _sysSingeltonMutex;
#endif // ACDK_MT

//static 
RClass 
Class::getSingeltonClass(const ClazzInfo* clazzInfo) 
{
  if (clazzInfo == 0)
    THROW0(IllegalArgumentException);
  acdk::lang::RClass tclass;
  if (clazzInfo->thisClass == 0) { 
#ifdef ACDK_MT
    LockedProxy<sys::static_mutex> _guard(&_sysSingeltonMutex);
#endif //ACDK_MT
    if (clazzInfo->thisClass == 0) { 
      const_cast<ClazzInfo*>(clazzInfo)->thisClass = new Class(clazzInfo); 
#ifndef ACDK_USE_EXT_REFERER // ## no mechanism to hold reference needed?
      const_cast<ClazzInfo*>(clazzInfo)->thisClass->addRef();
#endif
/FONT>
      tclass = clazzInfo->thisClass; 
      if (clazzInfo->isArray() && clazzInfo->userInfo == 0)
        clazzInfo->userInfo = Object::clazzInfo();
      acdk::lang::System::registerStaticReference(clazzInfo->thisClass); 
    } else
      tclass = clazzInfo->thisClass; 
  } else 
    tclass = clazzInfo->thisClass; 
  return tclass;
}


//static
 ClazzInfo* 
Class::getUnInitializedSingeltonArrayClazz(const ClazzInfo* elementinfo)
{
  ClazzInfo* ci = dmi::_arrayClazzRoot;
  for (; ci != 0; ci = ci->_next) 
  {
    if (ci->userInfo == (void*)elementinfo)
      return const_cast<ClazzInfo*>(ci);
  }
  if (ci == 0) 
  {
    if (elementinfo->isBasicClazz() == true)
      ci = ::new ClazzInfo(BasicArray_clazzInfo);
    else
      ci = ::new ClazzInfo(*ObjectArrayBase::clazzInfo());
    const_cast<ClazzInfo*>(ci)->userInfo = const_cast<ClazzInfo*>(elementinfo);
    ci->thisClass = 0;
    //ci->thisClass = ::new Class(ci); 
    //ci->thisClass->addRef();
    ClazzInfo::registerArrayClazzInfo(ci);
  }
  return ci;
}

//static
 ClazzInfo* 
Class::getSingeltonArrayClazz(const ClazzInfo* elementinfo)
{
#ifndef ACDK_NOMETAINFO
#ifdef ACDK_MT
  LockedProxy<sys::static_mutex> _guard(&_sysSingeltonMutex);
#endif
/FONT>
  if (elementinfo == 0)
    elementinfo = Object::clazzInfo();
  ClazzInfo* ci = const_cast<ClazzInfo*>(ClazzInfo::findArrayClazzInfo(elementinfo));

  if (ci != 0) 
    return ci;

  if (elementinfo->isBasicClazz() == true)
    ci = ::new ClazzInfo(BasicArray_clazzInfo);
  else
    ci = ::new ClazzInfo(*ObjectArrayBase::clazzInfo());
  const_cast<ClazzInfo*>(ci)->userInfo = const_cast<ClazzInfo*>(elementinfo);
  const_cast<ClazzInfo*>(ci)->thisClass = 0;
  ClazzInfo::registerArrayClazzInfo(ci);
  return ci;
#else 
  return 0;
#endif //ACDK_NOMETAINFO
}

//static 
RClass
Class::getSingeltonArrayClass(const ClazzInfo* elementinfo)
{
  const ClazzInfo* ci = getSingeltonArrayClazz(elementinfo);
  if (ci->thisClass == 0) 
  {
    const_cast<ClazzInfo*>(ci)->thisClass = new Class(ci); 
    ci->thisClass->addRef();
    //ClazzInfo::registerArrayClazzInfo(ci);
  }
  RClass tclass(ci->thisClass);
  return tclass;
}


RClass
Class::getClassByJType(IN(RString) sign) 
{
  switch(sign->charAt(0)) {
  case 'B':
    return Byte::getTYPE();
  case 'C':
    return Character::getTYPE();
  case 'Z':
    return Boolean::getTYPE();
  case 'S':
    return Short::getTYPE();
  case 'I':
    return Integer::getTYPE();
  case 'F':
    return Float::getTYPE();
  case 'D':
    return Double::getTYPE();
  case 'J':
    return Long::getTYPE();
  case '[' : {
    RClass cl = getClassByJType(sign->substr(1));
    return getSingeltonArrayClass(cl->objectClazzInfo());
  } 
  case 'L' : {
    if (sign->charAt(sign->length() - 1) != ';')
      THROW1(Exception, "Malformed JType: " + sign);
    RString cn = sign->substr(1, sign->length() - 1);
    int idx = cn->lastIndexOf('/');
    RString ns;
    if (idx != -1) {
      ns = cn->substr(0, idx);
      cn = cn->substr(idx + 1);
    }
    const ClazzInfo* ci = ClazzInfo::findClazzInfo(cn, ns == Nil ? String::emptyString() : ns);
    if (ci == 0)
      THROW1(Exception, "Type not found in ClazzInfo-DB: " + sign);
    return Class::getSingeltonClass(ci);
  }
  default:
    THROW1(Exception, "Malformed JType: " + sign);
    return Nil;
  }
}




Class::~Class()
{
  const_cast<ClazzInfo*>(_objectClazzInfo)->thisClass = 0;
}


void 
Class::finalize()
{
  if (_objectClazzInfo->thisClass) 
  {
    releaseRef();
    const_cast<ClazzInfo*>(_objectClazzInfo)->thisClass = 0;
  }
}

//virtual 
RString 
Class::getName()
{
  if (_objectClazzInfo->name[0] == '[') {
    return _objectClazzInfo->name + getSingeltonClass((const ClazzInfo*)_objectClazzInfo->userInfo)->getName();
  }
  if (_objectClazzInfo->ns != 0 && _objectClazzInfo->ns[0] != 0)
    return (RString) _objectClazzInfo->ns  + "/" + _objectClazzInfo->name;
  else
    return _objectClazzInfo->name;
}

RString 
Class::getClassName()
{
  return _objectClazzInfo->name;
}


RClassArray
Class::getClasses()
{
  return new ClassArray(0);
}

::acdk::lang::reflect::RUnit 
Class::getUnit()
{
  _objectClazzInfo->loadFullClazzInfo(false, false);
  if (_objectClazzInfo->_scopeParent == 0)
    return Nil;
  if (_objectClazzInfo->_scopeParent->isUnitInfo() == true)
    return new ::acdk::lang::reflect::Unit(reinterpret_cast<const UnitInfo*>(_objectClazzInfo->_scopeParent));
  return Nil;
}


RClass 
Class::getComponentType()
{
  if (isArray() == false)
    return Nil;
  return Class::getSingeltonClass((const ClazzInfo*)_objectClazzInfo->userInfo);
}


RClassArray
Class::getDeclaredClasses()
{
  return new ClassArray(0); 
}


RClass 
Class::getDeclaringClass()
{
  return Nil;
}


//virtual 
RClassArray
Class::getInterfaces()
{
  if (_objectClazzInfo->interfaces == 0)
    return new ClassArray(0);
  
  int count = _objectClazzInfo->getInterfacesCount();
  RClassArray ifaces = new ClassArray(count);

  for (int i = 0; i < count; i++) 
  {
    ifaces[i] = getSingeltonClass(_objectClazzInfo->interfaces[i]->type/*, _object*/);
  }
  return ifaces;
}


//virtual 
int 
Class::getModifiers()
{
  return _objectClazzInfo->flags;
}




RClass 
Class::getSuperclass()
{
  if (_objectClazzInfo->interfaces == 0 || _objectClazzInfo->interfaces[0] == 0 || _objectClazzInfo->interfaces[0]->type == 0)
    return Nil;
  return getSingeltonClass(_objectClazzInfo->interfaces[0]->type);
}

void
Class_getSuperClasses(IN(RClass) cclass, IN(RClassArray) supers)
{
  RClass superCls = cclass->getSuperclass();
  if (superCls != Nil)
    Class_getSuperClasses(superCls, supers);
  supers->append(cclass);
}

RClassArray 
Class::getSuperClasses()
{
  RClassArray classes = new ClassArray(0);
  Class_getSuperClasses(this, classes);
  return classes;
}

jlong 
Class::getSerialVersionUID()
{
  return _objectClazzInfo->getSerialVersionUID();
}


bool 
Class::isArray()
{
  return (_objectClazzInfo->flags & dmi::MiCiArray) == dmi::MiCiArray;
}

RClass 
Class::getArrayElementClass()
{
  if (isArray() == false)
    return Nil;
  if (_objectClazzInfo->userInfo == 0)
    return Nil;
  return getSingeltonClass((ClazzInfo*)_objectClazzInfo->userInfo);
}

//virtual 
bool 
Class::isAssignableFrom(IN(RClass) cls)
{
  return _objectClazzInfo->assignableFrom(cls->_objectClazzInfo);
}

//virtual 
bool 
Class::isInstance(IN(acdk::lang::Object) obj)
{
  return obj->getClazzInfo() == _objectClazzInfo;
}

//virtual 
bool 
Class::isInterface()
{
  return (_objectClazzInfo->flags & dmi::MiCiInterface) == dmi::MiCiInterface;
}

//virtual 
bool 
Class::isPrimitive()
{
  return (_objectClazzInfo->flags & dmi::MiCiBasicType) == dmi::MiCiBasicType;
}


//virtual 
acdk::lang::Object 
Class::newInstance() THROWS1(RInstantiationException)
{
  if (isArray() == false && _objectClazzInfo->creator != 0) 
    return _objectClazzInfo->creator();

  _objectClazzInfo->loadFullClazzInfo(false);

  if (isArray() == true) 
  {
    const ClazzInfo* memberclazz = (const ClazzInfo*)_objectClazzInfo->userInfo;
    if (memberclazz == Boolean::getTYPE()->objectClazzInfo()) 
      return new boolArray(0);
    if (memberclazz == Byte::getTYPE()->objectClazzInfo()) 
      return new byteArray(0);
    if (memberclazz == Character::getTYPE()->objectClazzInfo()) 
      return new charArray(0);
    if (memberclazz == Short::getTYPE()->objectClazzInfo()) 
      return new shortArray(0);
    if (memberclazz == Integer::getTYPE()->objectClazzInfo()) 
      return new intArray(0);
    if (memberclazz == Long::getTYPE()->objectClazzInfo()) 
      return new longArray(0);
    if (memberclazz == Float::getTYPE()->objectClazzInfo()) 
      return new floatArray(0);
    if (memberclazz == Double::getTYPE()->objectClazzInfo()) 
      return new doubleArray(0);
    
    if (((const ClazzInfo*)_objectClazzInfo->userInfo)->array_creator)
      return ((const ClazzInfo*)_objectClazzInfo->userInfo)->array_creator(0);
    return new ObjectArray((const ClazzInfo*)_objectClazzInfo->userInfo, 0);

  }
  
  // we try to use a standard constructor
  
  RClassArray ca = new ClassArray(0);
  reflect::RConstructor c = getDeclaredConstructor(ca);
  if (c != Nil) {
    RObjectArray args = new ObjectArray(0);
    acdk::lang::Object erg = c->newInstance(args);
    if (erg != Nil)
      return erg;
  }
  THROW1(InstantiationException, getName());
  return Nil;
}


static
RString 
getNameOfSig(IN(RString) str, bool& isBasic)
{
  isBasic = true;
  return str;
  /*
  if (str->length() > 1) {
    isBasic = false;
    return str;
  }
  isBasic = true;
  if (str->compareTo((RString)"Z") == 0)
    return "bool";
  if (str->compareTo((RString)"C") == 0)
    return "char";
  if (str->compareTo((RString)"B") == 0)
    return "byte";
  if (str->compareTo((RString)"S") == 0)
    return "short";
  if (str->compareTo((RString)"I") == 0)
    return "int";
  if (str->compareTo((RString)"J") == 0)
    return "jlong";
  if (str->compareTo((RString)"F") == 0)
    return "float";
  if (str->compareTo((RString)"D") == 0)
    return "double";
  if (str->compareTo("V") == 0 || )
    return "void";
  isBasic = false;
  return str;
  */
}

//virtual 
RString 
Class::toString()
{
  return _objectClazzInfo->toTypeString(dmi::TpFtAcdkType | dmi::TpFtFqName);
}
           
//static 
RClass 
Class::forName(IN(RString) className) THROWS1(RClassNotFoundException)
{
  return forName(className, true);
}

RClassLoader 
Class::getClassLoader()
{
  return ClassLoader::getSystemClassLoader();
}

//static 
RClass 
Class::forName(IN(RString) name, bool initialize) THROWS1(RClassNotFoundException)
{
  return ClassLoader::getSystemClassLoader()->findClass(name);
}

//static 
RClass 
Class::findClass(IN(RString) name)
{
  return ClassLoader::getSystemClassLoader()->findClass(name, true);
}


//static 
RClass 
Class::forName(IN(RString) name, bool initialize, IN(RClassLoader) loader)
{
  return loader->findClass(name);
}

//static 
RClass 
Class::_forName(IN(RString) name)
{
  const ClazzInfo* clazz = ClazzInfo::findClazzInfo(name, false);
  /*
  RString namesp;
  RString pcls = name->replace(".", "/");
  pcls = pcls->replace("::", "/");
  int pos;
  if ((pos = pcls->indexOf('/')) == 0) {
    pcls = pcls->substr(1);
  }
  
  const ClazzInfo* clazz = 0;
  if (pcls->c_str()[0] == '[') {
    clazz = ClazzInfo__findArrayClazzInfo(pcls->c_str() + 1);
  } else {
    if ((pos = pcls->lastIndexOf('/')) != -1) 
    {
      namesp = pcls->substr(0, pos);
      pcls = pcls->substr(pos + 1);
    }
    clazz = ClazzInfo::findClazzInfo(pcls->c_str(), namesp == Nil ? "" : namesp->c_str());
  }*/
  if (clazz == 0)
    return Nil;
  return Class::getSingeltonClass(clazz);
}


acdk::lang::reflect::RConstructor 
Class::getDeclaredConstructor(IN(RClassArray) parameterTypes) THROWS1(RNoSuchMethodException)
{
  ::acdk::lang::dmi::AcdkStdWeakTypeDmiClient dmiclient;
  ::acdk::lang::sys::core_vector<dmi::ClazzMethodArgInfo> vec(parameterTypes->length(), parameterTypes->length(), dmi::ClazzMethodArgInfo());
  for (int i = 0; i < vec.size(); ++i)
  {
    vec[i].type = parameterTypes[i]->objectClazzInfo();
    vec[i].name = "";
  }
  const ::acdk::lang::dmi::ClazzMethodInfo* cmi;
  try {
    const ClazzInfo* ci = _objectClazzInfo;
    cmi = 
    _lookupMethod(ci, ACDK_STACK_STR(ci->name), vec, Nil, 
                  dmiclient, 
                  ::acdk::lang::dmi::MiPublic | 
                  ::acdk::lang::dmi::MiMiConstructor);

  } catch (RParamsMismatchException ex) {
    THROW1(NoSuchMethodException, ex->getMessage());
  }
  if (cmi == 0)
    THROW1(NoSuchMethodException, toString() + "::" + _objectClazzInfo->name + "(" + parameterTypes->toString() + ")");

  return new ::acdk::lang::reflect::Constructor(_objectClazzInfo, cmi);
}

acdk::lang::reflect::RConstructorArray
Class::getDeclaredConstructors()
{
  int count = 0;
  int i;
  for (i = 0; _objectClazzInfo->methods[i]; ++i)
  {
    if (_objectClazzInfo->methods[i]->flags & ::acdk::lang::dmi::MiMiConstructor)
      ++count;
  }
  acdk::lang::reflect::RConstructorArray constructors = new acdk::lang::reflect::ConstructorArray(count);
  int ci = 0;
  for (i = 0; _objectClazzInfo->methods[i] != 0; ++i)
  {
    if (_objectClazzInfo->methods[i]->flags & ::acdk::lang::dmi::MiMiConstructor)
      constructors[ci++] = new ::acdk::lang::reflect::Constructor(_objectClazzInfo, _objectClazzInfo->methods[i]);

  }
  return constructors;
}

acdk::lang::reflect::RField 
Class::getDeclaredField(IN(RString) name) THROWS1(RNoSuchFieldException)
{
  reflect::RFieldArray tf = getDeclaredFields();
  int length = tf->length();
  if (length == 0)
    return Nil;
  for (int i = length - 1; i >= 0 ; i--) 
  {
    if (name->compareTo(tf[i]->getName()) == 0)
      return tf[i];
  }
  THROW1(NoSuchFieldException, "Field " + getName() + "::" + name  + " cannot be found");
  return Nil;
}

acdk::lang::reflect::RFieldArray
Class::getDeclaredFields()
{
  _objectClazzInfo->loadFullClazzInfo(false, false);
  int c = _objectClazzInfo->getFieldsCount();
  if (c == 0)
    return new acdk::lang::reflect::FieldArray(0);
  reflect::RFieldArray erg = new reflect::FieldArray(c);
  for (int i = 0; _objectClazzInfo->fields[i] != 0; i++)
    erg[i] = new reflect::Field(const_cast<ClazzInfo*>(_objectClazzInfo), _objectClazzInfo->fields[i]);
  return erg;
}



acdk::lang::reflect::RField 
Class::getField(IN(RString) name) THROWS1(RNoSuchFieldException)
{
  _objectClazzInfo->loadFullClazzInfo(true, false);
  reflect::RFieldArray tf = getFields();
  for (int i = 0; i < tf->length(); i++) 
  {
    if (name->compareTo(tf[i]->getName()) == 0)
      return tf[i];
  }
  THROW1(NoSuchFieldException, "Field " + getName() + "::" + name  + " cannot be found");
  return Nil;
}


acdk::lang::reflect::RFieldArray
Class::getFields()
{
  const ClazzInfo* clzinfo = _objectClazzInfo;
  
  int fieldcount = 0;
  while (clzinfo != 0) 
  {
    clzinfo->loadFullClazzInfo(false, false);
    if (clzinfo->fields != 0) {
      for (int i = 0; clzinfo->fields[i] != 0; i++)
        fieldcount++;
    }
    if (clzinfo->interfaces[0])
      clzinfo = clzinfo->interfaces[0]->type;
    else
      break;
  }
  if (fieldcount == 0)
    return new reflect::FieldArray(0);
  reflect::RFieldArray erg = new reflect::FieldArray(fieldcount);
  int currentfield = 0;
  clzinfo = _objectClazzInfo;
  while (clzinfo != 0) 
  {
    clzinfo->loadFullClazzInfo(false, false);
    if (clzinfo->fields != 0) {
      for (int i = 0; clzinfo->fields[i] != 0; i++)
        erg[currentfield++] = new reflect::Field(clzinfo, clzinfo->fields[i]);
    }
    if (clzinfo->interfaces[0])
      clzinfo = clzinfo->interfaces[0]->type;
    else
      break;
  }

  return erg;
}



acdk::lang::reflect::RMethod 
Class::getDeclaredMethod(IN(RString) name, IN(RClassArray) parameterTypes) THROWS1(RNoSuchMethodException)
{
  _objectClazzInfo->loadFullClazzInfo(false, false);

  ::acdk::lang::sys::core_vector<dmi::ClazzMethodArgInfo> vec(parameterTypes->length(), parameterTypes->length(), dmi::ClazzMethodArgInfo());
  for (int i = 0; i < vec.size(); ++i)
  {
    vec[i].type = parameterTypes[i]->objectClazzInfo();
    vec[i].name = "";
  }
  acdk::lang::dmi::AcdkStdWeakTypeDmiClient dmiclient;
  const dmi::ClazzMethodInfo* cmi = 0;
  try {
    const ClazzInfo* ci = _objectClazzInfo;
    cmi = acdk::lang::dmi::StdDispatch::_lookupMethod(ci, 
                                                          name,
                                                          vec,
                                                          Nil,
                                                          dmiclient,
                                                          acdk::lang::dmi::MiPublic | acdk::lang::dmi::MiIvDeclared);
  } catch (RParamsMismatchException ex) {
    THROW1(NoSuchMethodException, ex->getMessage());
  }
  if (cmi == 0)
    THROW1(NoSuchMethodException, toString() + "::" + name + "(" + parameterTypes->toString() + ")");
  return new acdk::lang::reflect::Method(_objectClazzInfo, cmi);
}


acdk::lang::reflect::RMethodArray
Class::getDeclaredMethods()
{
  if (_objectClazzInfo == 0)
    return Nil;

  _objectClazzInfo->loadFullClazzInfo(false, false);
  int count = _objectClazzInfo->getMethodsCount();
   reflect::RMethodArray ma = new reflect::MethodArray(count);
  
  for (int i = 0; i < count; i++) 
  {
    ma[i] = new reflect::Method(_objectClazzInfo, _objectClazzInfo->methods[i]);
  }
  return ma;
}

acdk::lang::reflect::RMethod 
Class::getMethod(IN(RString) name, IN(RClassArray) parameterTypes, IN(RStringArray) namedargs) THROWS1(RNoSuchMethodException)
{
  _objectClazzInfo->loadFullClazzInfo(true, false);
  ::acdk::lang::sys::core_vector<dmi::ClazzMethodArgInfo> vec(parameterTypes->length(), parameterTypes->length(), dmi::ClazzMethodArgInfo());
  for (int i = 0; i < vec.size(); ++i)
  {
    vec[i].type = parameterTypes[i]->objectClazzInfo();
    vec[i].name = "";
  }
  acdk::lang::dmi::AcdkStdWeakTypeDmiClient dmiclient;
  const dmi::ClazzMethodInfo* cmi = 0;
  try {
    const ClazzInfo* ci = _objectClazzInfo;
    cmi = acdk::lang::dmi::StdDispatch::_lookupMethod(ci, 
                                                          name,
                                                          vec,
                                                          namedargs,
                                                          dmiclient,
                                                          acdk::lang::dmi::MiPublic);
  } catch (RParamsMismatchException ex) {
    THROW1(NoSuchMethodException, ex->getMessage());
  }
  if (cmi == 0)
    THROW1(NoSuchMethodException, toString() + "::" + name + "(" + parameterTypes->toString() + ")");
  
  return new acdk::lang::reflect::Method(_objectClazzInfo, cmi);
}


reflect::RMethodArray
Class_getMethods(const ClazzInfo* clazz) 
{
  if (clazz == 0 || clazz->methods == 0)
    return Nil;
  clazz->loadFullClazzInfo(false, false);
  reflect::RMethodArray ma = new reflect::MethodArray(0);
  int i = 0;
  for (; clazz->methods[i] != 0; ++i) 
  {
    if (clazz->methods[i]->flags & dmi::MiPublic)
      ma->append(new reflect::Method(clazz, clazz->methods[i]));
  }
  for (i = 0; clazz->interfaces[i] != 0; ++i) 
  {
    reflect::RMethodArray sar = Class_getMethods(clazz->interfaces[i]->type);
    ma->concat(sar);
  }
  return ma;
}

acdk::lang::reflect::RMethodArray
Class::getMethods()
{
  return Class_getMethods(_objectClazzInfo);
}

RPackage 
Class::getPackage()
{
  _objectClazzInfo->loadFullClazzInfo(false, false);
  if (_objectClazzInfo->ns == 0)
    return Nil;
  return Package::getPackage(_objectClazzInfo->ns);
}



acdk::lang::Object 
Class::_getInstance()
{
  _objectClazzInfo->loadFullClazzInfo(false, false);
  if (_objectClazzInfo->creator == 0)
    return Nil;
  return _objectClazzInfo->creator();
}


//static
acdk::lang::Object
Class::create_arrayInstance(IN(RClass) component, int length) 
{
  if (component->isPrimitive() == true) {
    if (component->objectClazzInfo() == Boolean::getTYPE()->objectClazzInfo())
      return new ::BasicArray<bool>(length);
    if (component->objectClazzInfo() == Byte::getTYPE()->objectClazzInfo())
      return new BasicArray<byte>(length);
    if (component->objectClazzInfo() == Character::getTYPE()->objectClazzInfo())
      return new BasicArray<char>(length);
    if (component->objectClazzInfo() == Short::getTYPE()->objectClazzInfo())
      return new BasicArray<short>(length);
    if (component->objectClazzInfo() == Integer::getTYPE()->objectClazzInfo())
      return new BasicArray<int>(length);
    if (component->objectClazzInfo() == Long::getTYPE()->objectClazzInfo())
      return new BasicArray<jlong>(length);
    if (component->objectClazzInfo() == Float::getTYPE()->objectClazzInfo())
      return new BasicArray<float>(length);
    if (component->objectClazzInfo() == Double::getTYPE()->objectClazzInfo())
      return new BasicArray<double>(length);
    THROW1(ClassNotFoundException, "Basic Type not found: " + component->toString());
  } 
  if (component->objectClazzInfo()->array_creator != 0) // ### TODO array_creator is always 0
    return component->objectClazzInfo()->array_creator(length);
  return new ObjectArrayBase(component->objectClazzInfo(), length);
}

bool 
Class::isSerializable()
{
#if defined(ACDK_NOMETAINFO)
  return false;
#else
/FONT>
  if (_objectClazzInfo->flags & ::acdk::lang::dmi::MiCiSerializable)
    return true;
  return acdk::io::Serializable::clazzInfo()->assignableFrom(_objectClazzInfo);
#endif
/FONT>
}

bool 
Class::hasWriteObject()
{
#if defined(ACDK_NOMETAINFO)
  return false;
#else
/FONT>
  dmi::FunctionSignature signature;
  ClazzInfo* args[2];
  signature.size = 2;
  args[0] = ::acdk::io::ObjectWriter::clazzInfo();
  args[1] = Class::clazzInfo();
  signature.functionname = "writeObject";
  signature.args = (const ClazzInfo**)args;
  const ClazzInfo* ci = _objectClazzInfo;
  return findMethod(ci, signature) != 0;
#endif
/FONT>
}
  
bool 
Class::hasReadObject()
{
#if defined(ACDK_NOMETAINFO)
  return false;
#else
/FONT>
  dmi::FunctionSignature signature;
  ClazzInfo* args[2];
  signature.size = 2;
  args[0] = ::acdk::io::ObjectReader::clazzInfo();
  args[1] = Class::clazzInfo();
  signature.functionname = "readObject"; // ### TODO use hash-value of method inf for performance
  signature.args = (const ClazzInfo**)args;
  const ClazzInfo* ci = _objectClazzInfo;
  return findMethod(ci, signature) != 0;
#endif
/FONT>
}

bool 
Class::hasWriteReplace()
{
  dmi::FunctionSignature signature;
  signature.size = 0;
  signature.functionname = "writeReplace";
  const ClazzInfo* ci = _objectClazzInfo;
  return findMethod(ci, signature) != 0;
}

bool 
Class::hasReadResolve()
{
  dmi::FunctionSignature signature;
  signature.size = 0;
  signature.functionname = "readResolve";
  const ClazzInfo* ci = _objectClazzInfo;
  return findMethod(ci, signature) != 0;
}

acdk::lang::Object 
Class::createDmiProxy(IN(acdk::lang::Object) dmiTarget)
{
   if (ClassLoader::getSystemClassLoader()->loadDmiProxyLibrary(getName()) == false)
    return Nil;
  RString name = getName();
  if (name->endsWith("_DmiProxy") == false)
    name = name + "_DmiProxy";
  RClass dmiProxyClass = Class::forName(name);
  acdk::lang::Object obj = dmiProxyClass->newInstance();
  dmi::DmiProxyBase* dbase = dynamic_cast<dmi::DmiProxyBase*>(obj.impl());
  if (dbase != 0)
    dbase->setDmiTarget(dmiTarget);
  return obj;
}

bool 
Class::getDmiProxies(IN(RObjectArray) proxies, IN(acdk::lang::Object) dmiTarget, int flags)
{
  if (ClassLoader::getSystemClassLoader()->loadDmiProxyLibrary(getName()) == false)
    return false;
  
  acdk::lang::Object obj = newInstance(); // #### todo code really works??
  dmi::DmiProxyBase* dbase = dynamic_cast<dmi::DmiProxyBase*>(obj.impl());
  if (dbase != 0)
    dbase->setDmiTarget(dmiTarget);
  proxies->append(obj);
  return true;
}


} // lang
} //acdk