/* -*- Mode: C; c-file-style: "gnu" -*-
   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 "jni.h"
#include "jniint.h"
#include "ClazzFile.h"
#include "exceptions.h"
#include "qop.h"
#include "objects.h"
#include <stdlib.h>
#include <assert.h>

#include "compat.h"

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

  if (NULL == cls || (cls->access_flags & (ACC_INTERFACE | ACC_ABSTRACT) ) )
    {
      throw_Exception(env, "java/lang/InstantiationException",
		      "Unable to allocate object");
      return NULL;
    }
  else
    {
      new_obj = new_object(env, cls);

      return new_obj;
    }
}

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

  if (object == NULL)
    return NULL;

  va_start(varargs, methodID);
  JNIFUNC(CallNonvirtualVoidMethodV)(env, object, methodID, varargs);
  va_end(varargs);

  if ((*env)->ExceptionOccurred(env))
    {
      char buf[1024];
      ClazzFile *cf = jclass_to_clazzfile(env, clazz);
      jclass exception;

      /*      (*env)->ExceptionDescribe(env);*/

      /* clear the old exception */
      (*env)->ExceptionClear(env);

      exception = (*env)->FindClass(env,
				    "java/lang/InstantiationException");

      snprintf(buf, sizeof(buf),
	       "in JNI NewClass, for class %s",
	       getClassName(env, cf));

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

      return NULL;
    }

  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))
    {
      char buf[1024];
      ClazzFile *cf = jclass_to_clazzfile(env, clazz);
      jclass exception = (*env)->FindClass(env,
					   "java/lang/InstantiationException");
      free(object);
      
      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))
    {
      char buf[1024];
      ClazzFile *cf = jclass_to_clazzfile(env, clazz);
      jclass exception = (*env)->FindClass(env,
					   "java/lang/InstantiationException");
      free(object);
      
      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)
{
  japhar_obj o = (japhar_obj)obj;

  return clazzfile_to_jclass(env, *o);
}

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

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

  clazz = jclass_to_clazzfile(env, cls);
  return is_instance_of(env, obj, clazz);
}

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