2005/5/9

     
 

acdk2java.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_java/src/acdk/java/acdk2java.cpp,v 1.22 2005/04/25 13:20:46 kommer Exp $
#include "acdk2java.h"
#include <acdk/lang/Boolean.h>
#include <acdk/lang/Integer.h>
#include <acdk/lang/Character.h>
#include <acdk/lang/Byte.h>
#include <acdk/lang/Short.h>
#include <acdk/lang/Long.h>
#include <acdk/lang/Float.h>
#include <acdk/lang/Double.h>

#include <acdk/lang/Error.h>
#include <acdk/lang/NoSuchMethodException.h>
#include <acdk/lang/ClassNotFoundException.h>
#include <acdk/lang/IllegalAccessException.h>
#include <acdk/lang/NullPointerException.h>
#include <acdk/lang/IndexOutOfBoundsException.h>

#include "JavaObject.h"
#include <acdk/lang/dmi/ScriptVar.h>
#include <acdk/io/EOFException.h>


namespace acdk {
namespace java {

using namespace ::acdk::lang::dmi;

jclass 
getAcdkObjectClass(JNIEnv *env)
{
  return env->FindClass("acdk/java/AcdkObject");
}

acdk::lang::Object* getObjectHandle(JNIEnv* env, jobject obj)
{
  static JField jfield(env, env->GetObjectClass(obj), "objectHandle", "I");
  int handle = jfield.getInt(obj);
  // ### if handle == 0
  return (acdk::lang::Object*)handle;
}

void setObjectHandle(JNIEnv* env, jobject jobj, IN(acdk::lang::Object) obj)
{
  acdk::lang::Object* optr = obj;
  if (optr != 0)
    optr->addRef();
  static JField jfield(env, env->GetObjectClass(jobj), "objectHandle", "I");
  jfield.setInt(jobj, (int)optr);
}

jobject createNewAcdkObject(JNIEnv* env, jclass jcls, IN(acdk::lang::Object) obj)
{
  jvalue jargs[1]; 
  static JMethod AcdkObject_AcdkObject(env, jcls, "<init>", "()V");
  jobject jobj = env->NewObjectA(jcls, AcdkObject_AcdkObject.methodId(), jargs);
  setObjectHandle(env, jobj, obj);
  return jobj;
}

void
java2acdk(JNIEnv *env, jobject jobj, ScriptVar& sa)
{
  if (env->IsSameObject(jobj, 0) == JNI_TRUE)
  {
    sa = Nil;
    return;
  }
  JClass cls(env, env->GetObjectClass(jobj));
  RString cname = cls.getName();
  //std::cerr << "jarg: " << cname->toString()->c_str() << sys::eofl;
  if (cname->equals("java.lang.String") == true)
  {
    JString jstr(env, (jstring)jobj);
    RString str = jstr.toString();
    sa = (acdk::lang::Object)str;
    return;
  } 
  
  if (cname->equals("java.lang.Boolean") == true) {
    static JMethod getValue(env, jobj, "booleanValue", "()Z");
    acdk::lang::Object obj = new Boolean(getValue.callBooleanMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("java.lang.Character") == true) {
    static JMethod getValue(env, jobj, "charValue", "()C");
    acdk::lang::Object obj = new Character(getValue.callCharMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("java.lang.Byte") == true) {
    static JMethod getValue(env, jobj, "byteValue", "()B");
    acdk::lang::Object obj = new Character(getValue.callByteMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("java.lang.Short") == true) {
    static JMethod getValue(env, jobj, "shortValue", "()S");
    acdk::lang::Object obj = new Short(getValue.callShortMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("java.lang.Integer") == true) {
    static JMethod getInt(env, jobj, "intValue", "()I");
    acdk::lang::Object obj = new Integer(getInt.callIntMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("java.lang.Long") == true) {
    static JMethod getValue(env, jobj, "longValue", "()J");
    acdk::lang::Object obj = new Long(getValue.callLongMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("java.lang.Float") == true) {
    static JMethod getValue(env, jobj, "floatValue", "()F");
    acdk::lang::Object obj = new Float(getValue.callFloatMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("java.lang.Double") == true) {
    static JMethod getValue(env, jobj, "DoubleValue", "()D");
    acdk::lang::Object obj = new Double(getValue.callDoubleMethod(jobj));
    sa = obj;
    return;
  }
  if (cname->equals("acdk.java.AcdkObject") == true) {
    JClass jcls = JClass::getObjectClass(env, jobj);
    static JField objectHandle(env, jcls, "objectHandle", "I", false);
    int oh = objectHandle.getInt(jobj);
    acdk::lang::Object obj = (acdk::lang::Object*)oh;
    sa  = obj;
    return;
  }
  acdk::lang::Object obj = new JavaObject(getJavaInterpreter(), jobj);
  sa = obj;
}


acdk::lang::Object 
jobject2aobject(JNIEnv *env, jobject jobj)
{
  ScriptVar erg;
  java2acdk(env, jobj, erg);
  return erg.getObjectVar();
}


jobject aobject2jobject(JNIEnv* env, IN(acdk::lang::Object) obj)
{
  if (instanceof(obj, String) == true)
  {
    RString str = (RString)obj;
    JString jstr(env, str);
    return jstr;
  }
  if (instanceof(obj, JavaObject) == true)
  {
    RJavaObject aobj = (RJavaObject)obj;
    return aobj->javaObject();
  }
  if (instanceof(obj, Boolean) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Boolean");
    static JMethod constructor(env, jcls, "<init>", "(Z)V");
    jvalue jargs[2]; 
    jargs[0].z = RBoolean(obj)->booleanValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  if (instanceof(obj, Character) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Character");
    static JMethod constructor(env, jcls, "<init>", "(C)V");
    jvalue jargs[2]; 
    jargs[0].c = RCharacter(obj)->charValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  if (instanceof(obj, Byte) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Byte");
    static JMethod constructor(env, jcls, "<init>", "(B)V");
    jvalue jargs[2]; 
    jargs[0].b = RByte(obj)->byteValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  if (instanceof(obj, Short) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Short");
    static JMethod constructor(env, jcls, "<init>", "(S)V");
    jvalue jargs[2]; 
    jargs[0].s = RShort(obj)->shortValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  if (instanceof(obj, Integer) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Integer");
    static JMethod constructor(env, jcls, "<init>", "(I)V");
    jvalue jargs[2]; 
    jargs[0].i = RInteger(obj)->intValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  if (instanceof(obj, Long) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Long");
    static JMethod constructor(env, jcls, "<init>", "(J)V");
    jvalue jargs[2]; 
    jargs[0].j = RLong(obj)->longValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  if (instanceof(obj, Float) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Float");
    static JMethod constructor(env, jcls, "<init>", "(F)V");
    jvalue jargs[2]; 
    jargs[0].f = RFloat(obj)->floatValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  if (instanceof(obj, Double) == true)
  {
    JClass jcls = JClass::findClass(env, "java/lang/Double");
    static JMethod constructor(env, jcls, "<init>", "(D)V");
    jvalue jargs[2]; 
    jargs[0].d = RDouble(obj)->doubleValue();
    return env->NewObjectA(jcls, constructor.methodId(), jargs);
  }
  
  if (instanceof(obj, JavaObject) == true)
  {
    return RJavaObject(obj)->javaObject();
  }
  return createNewAcdkObject(env, getAcdkObjectClass(env), obj);
}

jobject 
acdk2jobject(JNIEnv *env, const ScriptVar& sa)
{
  switch (sa.type) 
  {
  case ScriptVar::UnknownType: return 0;
  
  case ScriptVar::BoolType:
  case ScriptVar::BoolRefType:
  {
    jvalue jargs[2]; 
    jargs[0].z = sa.getBoolVar();
    jclass jcls = env->FindClass("java/lang/Boolean");
    static JMethod NewJObjectFunc(env, jcls, "<init>", "(Z)V", true);
    return env->NewObjectA(jcls, NewJObjectFunc.methodId(), jargs);
  }
  case ScriptVar::CharType:
  case ScriptVar::CharRefType:
  {
    jvalue jargs[2]; 
    jargs[0].c = (short)sa.getCharVar();
    jclass jcls = env->FindClass("java/lang/Character");
    static JMethod NewJObjectFunc(env, jcls, "<init>", "(C)V", true);
    return env->NewObjectA(jcls, NewJObjectFunc.methodId(), jargs);
  }
  case ScriptVar::ByteType:
  case ScriptVar::ByteRefType:
  {
    jvalue jargs[2]; 
    jargs[0].b = sa.getByteVar();
    jclass jcls = env->FindClass("java/lang/Byte");
    static JMethod NewJObjectFunc(env, jcls, "<init>", "(B)V", true);
    return env->NewObjectA(jcls, NewJObjectFunc.methodId(), jargs);
  }
  case ScriptVar::ShortType:
  case ScriptVar::ShortRefType:
  {
    jvalue jargs[2]; 
    jargs[0].s = sa.getShortVar();
    jclass jcls = env->FindClass("java/lang/Short");
    static JMethod NewJObjectFunc(env, jcls, "<init>", "(S)V", true);
    return env->NewObjectA(jcls, NewJObjectFunc.methodId(), jargs);
  }
  case ScriptVar::IntType:
  case ScriptVar::IntRefType:
  {
    jvalue jargs[2]; 
    jargs[0].i = sa.getIntVar();
    jclass jcls = env->FindClass("java/lang/Integer");
    static JMethod AcdkObject_AcdkObject(env, jcls, "<init>", "(I)V", true);
    return env->NewObjectA(jcls, AcdkObject_AcdkObject.methodId(), jargs);
  }
  case ScriptVar::LongType:
  case ScriptVar::LongRefType:
  {
    jvalue jargs[2]; 
    jargs[0].j = sa.getLongVar();
    jclass jcls = env->FindClass("java/lang/Long");
    static JMethod AcdkObject_AcdkObject(env, jcls, "<init>", "(J)V", true);
    return env->NewObjectA(jcls, AcdkObject_AcdkObject.methodId(), jargs);
  }
  case ScriptVar::FloatType:
  case ScriptVar::FloatRefType:
  {
    jvalue jargs[2]; 
    jargs[0].f = sa.getFloatVar();
    jclass jcls = env->FindClass("java/lang/Float");
    static JMethod NewJObjectFunc(env, jcls, "<init>", "(F)V", true);
    return env->NewObjectA(jcls, NewJObjectFunc.methodId(), jargs);
  }
  case ScriptVar::DoubleType:
  case ScriptVar::DoubleRefType:
  {
    jvalue jargs[2]; 
    jargs[0].d = sa.getDoubleVar();
    jclass jcls = env->FindClass("java/lang/Double");
    static JMethod NewJObjectFunc(env, jcls, "<init>", "(D)V", true);
    return env->NewObjectA(jcls, NewJObjectFunc.methodId(), jargs);
  }
  case ScriptVar::ObjectType: 
  case ScriptVar::ObjectRefType:
    return aobject2jobject(env, sa.getObjectVar());
  default:
    // ####
    return 0;
  }
}

void 
java2acdk(JNIEnv *env, JObjectArray& arguments, ScriptVarArray& sargs)
{
  for (int i = 0; i < sargs.size(); ++i)
  {
    java2acdk(env, arguments[i], sargs[i]);
  }
}

bool acdk2java(JNIEnv *jenv, jclass jcls, ScriptVar& marg, jvalue& jarg)
{
  JClass cls(jenv, jcls);
  RString jtypenam = cls.getName();
  
  if (jtypenam->equals("boolean") == true) {
    jarg.z = marg.getBoolVar();
    return true;
  }
  if (jtypenam->equals("char") == true) {
    jarg.c = marg.getCharVar();
    return true;
  }
  if (jtypenam->equals("byte") == true) {
    jarg.b = marg.getByteVar();
    return true;
  }
  if (jtypenam->equals("short") == true) {
    jarg.s = marg.getShortVar();
    return true;
  }
   
  if (jtypenam->equals("int") == true) {
    jarg.i = marg.getIntVar();
    return true;
  }
  if (jtypenam->equals("long") == true) {
    jarg.j = marg.getLongVar();
    return true;
  }
  if (jtypenam->equals("float") == true) {
    jarg.f = marg.getFloatVar();
    return true;
  }
  if (jtypenam->equals("double") == true) {
    jarg.d = marg.getDoubleVar();
    return true;
  }
  if (marg.type == ScriptVar::ObjectType) {
    acdk::lang::Object obj = marg.getObjectVar();
    if (instanceof(obj, String) == true) {
      jarg.l = jenv->NewStringUTF(RString(obj)->c_str());
      return true;
    }
    if (instanceof(obj, JavaObject) == true) {
      jarg.l = RJavaObject(obj)->javaObject();
      return true;
    }
  }
  return false;
}

bool
acdk2java(JNIEnv *jenv, jobjectArray classarray, ScriptVarArray& margs, jvalue* jargs)
{
  
  for (int i = 0; i < margs.size(); i++) {
    jclass param = (jclass)jenv->GetObjectArrayElement(classarray, i);          
    if (acdk2java(jenv, param, margs[i], jargs[i]) == false)
      return false;
  }
  return true;
}

bool
acdk2java(JNIEnv *env, ScriptVar& marg, jvalue& jarg)
{
  switch (marg.type) {
  case ScriptVar::BoolType : jarg.z = marg.var.boolVal; return true;
  case ScriptVar::BoolRefType : jarg.z = *marg.var.boolRef; return true;
  case ScriptVar::CharType : jarg.c = marg.var.charVal; return true;
  case ScriptVar::CharRefType : jarg.c = *marg.var.charRef; return true;
  case ScriptVar::UcCharType : jarg.c = marg.var.uccharVal; return true;
  case ScriptVar::UcCharRefType : jarg.c = *marg.var.uccharRef; return true;
  case ScriptVar::ByteType : jarg.b = marg.var.byteVal; return true; 
  case ScriptVar::ByteRefType : jarg.b = *marg.var.byteRef; return true; 
  case ScriptVar::ShortType : jarg.s = marg.var.shortVal; return true;
  case ScriptVar::ShortRefType : jarg.s = *marg.var.shortRef; return true;
  case ScriptVar::IntType : jarg.i = marg.var.intVal; return true; 
  case ScriptVar::IntRefType : jarg.i = *marg.var.intRef; return true; 
  case ScriptVar::LongType : jarg.j = marg.var.longVal; return true; 
  case ScriptVar::LongRefType : jarg.j = *marg.var.longRef; return true; 
  case ScriptVar::FloatType : jarg.f = marg.var.floatVal; return true;
  case ScriptVar::FloatRefType : jarg.f = *marg.var.floatRef; return true;
  case ScriptVar::DoubleType : jarg.d = marg.var.doubleVal; return true;
  case ScriptVar::DoubleRefType : jarg.d = *marg.var.doubleRef; return true;
  case ScriptVar::ObjectRefType :
  case ScriptVar::ObjectType : {
    acdk::lang::Object obj = marg.getObjectRef();
    if (obj == Nil) {
      jarg.l = 0;
      return true;
    }
    if (instanceof(obj, String) == true) {
      jarg.l = env->NewStringUTF(RString(obj)->c_str());
      return true;
    }
    if (instanceof(obj, JavaObject) == true) {
      jarg.l = RJavaObject(obj)->javaObject();
      return true;
    }
    // has no wrapper at the moment for ACDK
    return false;
  }
  case ScriptVar::UnknownType :
    // oops;
    break;
  }
  return false;

}

bool 
acdk2java(JNIEnv *env, ScriptVarArray& margs, jvalue* jargs)
{
  for (int i = 0; i < margs.size(); i++) {
    if (acdk2java(env, margs[i], jargs[i]) == false)
      return false;
  }
  return true;
}

#if 0

//virtual 
int 
JavaDmiClient::typeDistance(const ScriptVar& arg, const ClazzInfo* toType)
{
   return typeDistance(arg.getClazzInfo(), toType);

  int erg = AcdkDmiClient::typeDistance(arg, toType);
  if (erg != -1)
    return erg;
  if (arg.isObjectType() == false)
    return -1;
  acdk::lang::Object o = arg.getObjectVar();
  //if (instanceof(o, Acdk
  return -1;
}

//virtual 
int 
JavaDmiClient::typeDistance(const ClazzInfo* fromType, const ClazzInfo* toType)
{
  return AcdkDmiClient::typeDistance(fromType, toType);
}

//virtual 
void 
JavaDmiClient::castTo(ScriptVar& value, const ::acdk::lang::dmi::ClazzInfo* toType)
{

}

#endif //0



#define MAP_J2AEXCEPTION(javaname, acdkns, acdkcn) \
  if (env->IsAssignableFrom(cls, JClass::findClass(env, #javaname))) \
    THROW1_FQ(acdkns, acdkcn, msg)

#define MAP_A2JEXCEPTION(acdkex, jex) \
do { \
  if (acdkex::clazzInfo()->assignableFrom(ex->getClazzInfo()) == true) { \
    env->ThrowNew(env->FindClass(#jex), msg); \
    return; \
  } \
} while (false)


void mapException(JNIEnv* env, IN(RThrowable) ex)
{
  JString msg(env, ex->getMessage());
  MAP_A2JEXCEPTION(::acdk::io::EOFException, java/io/EOFException);
  MAP_A2JEXCEPTION(::acdk::io::IOException, java/io/IOException);

  MAP_A2JEXCEPTION(::acdk::lang::NoSuchMethodException, java/lang/NoSuchMethodException);
  MAP_A2JEXCEPTION(::acdk::lang::ClassNotFoundException, java/lang/ClassNotFoundException);
  MAP_A2JEXCEPTION(::acdk::lang::IllegalAccessException, java/lang/IllegalAccessException);
  MAP_A2JEXCEPTION(::acdk::lang::NullPointerException, java/lang/NullPointerException);
  MAP_A2JEXCEPTION(::acdk::lang::IndexOutOfBoundsException, java/lang/IndexOutOfBoundsException);
  MAP_A2JEXCEPTION(::acdk::lang::RuntimeException, java/lang/RuntimeException);
  MAP_A2JEXCEPTION(::acdk::lang::Exception, java/lang/Exception);
  //MAP_A2JEXCEPTION(::acdk::lang::Throwable, java/lang/Throwable);
  jclass thrcls = env->FindClass("java/lang/Exception");
  env->ThrowNew(thrcls, msg);
}

void 
handleJException(JNIEnv* env)
{
  
  JObjectImpl<jthrowable, JGlobalRes> throwable(env, env->ExceptionOccurred());
  //env->ExceptionDescribe();
  
  env->ExceptionClear();
  JMethod Throwable_getMessage(env, throwable, "getMessage", "()Ljava/lang/String;");
  
  JString jmsg(env, (jstring)Throwable_getMessage.callObjectMethod(throwable));
  if (env->ExceptionCheck() == 0)
  {
    sys::coreout << "rec ex" << sys::eofl;
  }
  RString msg = jmsg.toString();
  
  JClass cls = JClass::getObjectClass(env, throwable);

  RString cname = cls.getName();

  

  MAP_J2AEXCEPTION(java/io/EOFException, ::acdk::io::, EOFException);
  MAP_J2AEXCEPTION(java/io/IOException, ::acdk::io::, IOException);
  
  MAP_J2AEXCEPTION(java/lang/Error, ::acdk::lang::, Error);
  
  MAP_J2AEXCEPTION(java/lang/NoSuchMethodException, ::acdk::lang::, NoSuchMethodException);
  MAP_J2AEXCEPTION(java/lang/ClassNotFoundException, ::acdk::lang::, ClassNotFoundException);
  MAP_J2AEXCEPTION(java/lang/IllegalAccessException, ::acdk::lang::, IllegalAccessException);
  
  
  MAP_J2AEXCEPTION(java/lang/NullPointerException, ::acdk::lang::, NullPointerException);
  MAP_J2AEXCEPTION(java/lang/IndexOutOfBoundsException, ::acdk::lang::, IndexOutOfBoundsException);
  MAP_J2AEXCEPTION(java/lang/RuntimeException, ::acdk::lang::, RuntimeException);

  MAP_J2AEXCEPTION(java/lang/Exception, ::acdk::lang::, Exception);

  THROW1_FQ(::acdk::lang::, Throwable, msg);
  
}

} // namespace java 
} // namespace acdk