/* -*- Mode: C; c-file-style: "gnu" -*-
   object.c -- native methods for java/lang/Object.
   Created: Chris Toshok <toshok@hungry.com>, 28-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 "native-threads.h"
#include "interp.h"
#include "objects.h"
#include "ClazzFile.h"
#include "exceptions.h"

JNIEXPORT jobject JNICALL
Java_java_lang_Object_getClass(JNIEnv *env,
			       jobject obj)
{
  jclass clazz = (*env)->GetObjectClass(env, obj);

  return clazz;
}

/* For Classpath, not JDK */
JNIEXPORT jobject JNICALL
Java_java_lang_VMObject_getClass(JNIEnv *env,
                                 jclass this_class,
                                 jobject obj)
{
  return(Java_java_lang_Object_getClass(env, obj));
}

JNIEXPORT jint JNICALL
Java_java_lang_Object_hashCode(JNIEnv *env,
			       jobject obj)
{
  japhar_object* jobj;

  obj_to_object(obj, jobj);

  return jobj->hash_code;
}

JNIEXPORT jobject JNICALL
Java_java_lang_Object_clone(JNIEnv *env,
			    jobject obj)
{

  return (jobject)clone_object(env, (japhar_obj)obj);
}

/*
 * For Classpath, not JDK
 */ 
JNIEXPORT jobject JNICALL
Java_java_lang_VMObject_clone(JNIEnv *env,
                              jclass this_class,
                              jobject obj_to_clone)
{
  return(Java_java_lang_Object_clone(env, obj_to_clone));
}
                              

JNIEXPORT void JNICALL
Java_java_lang_Object_notify(JNIEnv *env,
			     jobject obj)
{
  japhar_object* jobj;
  HMonitor my_monitor;

  obj_to_object(obj, jobj);

  my_monitor = jobj->monitor;

  if ( ! MONITOR_notifyOne(my_monitor) )
    {
      throw_Exception(env, "java/lang/IllegalMonitorStateException",
		      "not monitor owner!");
      return;
    }      
}

/*
 * For Classpath, not JDK
 */
JNIEXPORT void JNICALL
Java_java_lang_VMObject_notify(JNIEnv *env,
                               jclass this_class,
                               jobject obj)
{
  Java_java_lang_Object_notify(env, obj);
}

JNIEXPORT void JNICALL
Java_java_lang_Object_notifyAll(JNIEnv *env,
				jobject obj)
{
  japhar_object* jobj;
  HMonitor my_monitor;

  obj_to_object(obj, jobj);

  my_monitor = jobj->monitor;

  if ( ! MONITOR_notifyAll(my_monitor) )
    {
      throw_Exception(env, "java/lang/IllegalMonitorStateException",
		      "not monitor owner!");
      return;
    }      
}

/*
 * For Classpath, not JDK
 */
JNIEXPORT void JNICALL
Java_java_lang_VMObject_notifyAll(JNIEnv *env,
                                  jclass this_class,
                                  jobject obj)
{
  Java_java_lang_Object_notifyAll(env, obj);
}

/* XXX Should throw InterruptedException if interrupted */
JNIEXPORT void JNICALL
Java_java_lang_Object_wait(JNIEnv *env,
			   jobject obj,
			   jlong timeout)
{
  japhar_object* jobj;
  HMonitor my_monitor;

  obj_to_object(obj, jobj);

  my_monitor = jobj->monitor;

  if (0 > timeout)
    {
      throw_Exception(env, "java/lang/IllegalArgumentException",
		      "negative timeout");
      return;
    }      

  if ( ! MONITOR_timedWait(my_monitor, timeout) )
    {
      throw_Exception(env, "java/lang/IllegalMonitorStateException",
		      "not monitor owner!");
      return;
    }      
}

/*
 * For Classpath, not JDK
 */
JNIEXPORT void JNICALL
Java_java_lang_VMObject_wait(JNIEnv *env,
                             jclass this_class,
                             jobject obj,
                             jlong timeout,
                             jint timeout_ms)
{
  Java_java_lang_Object_wait(env, obj, timeout);
}

/* JDK 1.2 uses registration of native methods... */
static JNINativeMethod obj_native_methods[] = {
  { "hashCode",		"()I",	(void*)Java_java_lang_Object_hashCode },
  { "notify",		"()V",	(void*)Java_java_lang_Object_notify },
  { "notifyAll",	"()V",	(void*)Java_java_lang_Object_notifyAll },
  /*  { "registerNatives",	"()V",	(void*)Java_java_lang_Object_registerNatives }, XXX */
  { "wait",		"(J)V", (void*)Java_java_lang_Object_wait }
};
static int num_obj_native_methods = sizeof(obj_native_methods) / sizeof(obj_native_methods[0]);

JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env,
				      jclass cls)
{
#ifdef HAVE_LIBFFI
  (*env)->RegisterNatives(env, cls,
			  obj_native_methods,
			  num_obj_native_methods);
#endif
}
