/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode:nil -*-
   jniobj.c -- Java Native Interface methods relating to objects.
   Created: Chris Toshok <toshok@hungry.com>, 26-Jul-1997
 */
/*
  This file is part of Japhar, the GNU Virtual Machine for Java Bytecodes.
  Japhar is a project of The Hungry Programmers, GNU, and OryxSoft.

  Copyright (C) 1997, 1998, 1999 The Hungry Programmers

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  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 GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "jniint.h"
#include "ClazzFile.h"
#include "qop.h"
#include "compat.h"

jobject
JNIFUNC(AllocObject)(JNIEnv *env,
                     jclass clazz)
{
  HungryEnv *henv = JNIEnvToHEnv(env);
  ClazzFile *cls = jclass_to_clazzfile(henv, clazz);
  jobject new_obj = NULL;

  if (NULL == cls || (cls->access_flags & (ACC_INTERFACE | ACC_ABSTRACT) ) )
    {
      HVM_ExceptionThrow(henv, java_lang_InstantiationException,
                         "Unable to allocate object");
      return NULL;
    }
  else
    {
      new_obj = HVM_ObjectNew(henv, cls);

      return new_obj;
    }
}

jobject
JNIFUNC(NewObject)(JNIEnv *env,
                   jclass clazz,
                   jmethodID methodID,
                   ...)
{
  jobject object;
  va_list varargs;

  va_start(varargs, methodID);
  object = JNIFUNC(NewObjectV)(env, clazz, methodID, varargs);
  va_end(varargs);

  return object;
}

jobject
JNIFUNC(NewObjectA)(JNIEnv *env,
                    jclass clazz,
                    jmethodID methodID,
                    jvalue *args)
{
  jobject object = (*env)->AllocObject(env, clazz);

  if (object == NULL)
    return NULL;

  JNIFUNC(CallNonvirtualVoidMethodA)(env, object, methodID, args);

  if ((*env)->ExceptionOccurred(env))
    {
      HungryEnv *henv = JNIEnvToHEnv(env);
      char buf[1024];
      ClazzFile *cf = jclass_to_clazzfile(henv, clazz);
      jclass exception = (*env)->FindClass(env,
                                           java_lang_InstantiationException);
      PR_DELETE(object);
      
      PR_snprintf(buf, sizeof(buf),
               "in JNI NewClass, for class %s",
               getClassName(env, cf));

      /* clear the old exception */
      (*env)->ExceptionClear(env);
      /* and throw our new one */
      (*env)->ThrowNew(env, exception, buf);

      return NULL;
    }
  
  return object;
}

jobject
JNIFUNC(NewObjectV)(JNIEnv *env,
                    jclass clazz,
                    jmethodID methodID,
                    va_list args)
{
  jobject object = (*env)->AllocObject(env, clazz);

  if (object == NULL)
    return NULL;

  JNIFUNC(CallNonvirtualVoidMethodV)(env, object, methodID, args);

  if ((*env)->ExceptionOccurred(env))
    {
      HungryEnv *henv = JNIEnvToHEnv(env);
      char buf[1024];
      ClazzFile *cf = jclass_to_clazzfile(henv, clazz);
      jclass exception = (*env)->FindClass(env,
                                           java_lang_InstantiationException);
      PR_DELETE(object);
      
      PR_snprintf(buf, sizeof(buf),
               "in JNI NewClass, for class %s",
               getClassName(env, cf));

      /* clear the old exception */
      (*env)->ExceptionClear(env);
      /* and throw our new one */
      (*env)->ThrowNew(env, exception, buf);

      return NULL;
    }
  
  return object;
}

jclass
JNIFUNC(GetObjectClass)(JNIEnv *env,
                        jobject obj)
{
  HungryEnv *henv = JNIEnvToHEnv(env);
  japhar_object* o = (japhar_object*)obj;

  return (jclass)clazzfile_to_jclass(henv, o->clazz);
}

jboolean
JNIFUNC(IsInstanceOf)(JNIEnv *env,
                      jobject obj,
                      jclass cls)
{
  HungryEnv *henv = JNIEnvToHEnv(env);
  ClazzFile *clazz;

  /* a null object can be cast to any class */
  if (NULL == obj)
    return JNI_TRUE;

  clazz = jclass_to_clazzfile(henv, cls);
  return HVM_ObjectIsInstanceOf(henv, obj, clazz);
}

jboolean
JNIFUNC(IsSameObject)(JNIEnv *env,
                      jobject ref,
                      jobject ref2)
{
  return ref == ref2;
}
