// natVMVirtualMachine.cc - native support for VMVirtualMachine

/* Copyright (C) 2006 Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */

#include <config.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <jvmti.h>

#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Integer.h>
#include <java/lang/String.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/Thread.h>
#include <java/nio/ByteBuffer.h>
#include <java/util/ArrayList.h>
#include <java/util/Hashtable.h>
#include <java/util/Iterator.h>

#include <gnu/classpath/jdwp/VMFrame.h>
#include <gnu/classpath/jdwp/VMMethod.h>
#include <gnu/classpath/jdwp/VMVirtualMachine.h>
#include <gnu/classpath/jdwp/event/EventRequest.h>
#include <gnu/classpath/jdwp/exception/JdwpInternalErrorException.h>
#include <gnu/classpath/jdwp/util/MethodResult.h>

using namespace java::lang;
using namespace gnu::classpath::jdwp::event;
using namespace gnu::classpath::jdwp::util;

// JVMTI environment
static jvmtiEnv *_jdwp_jvmtiEnv;

void
gnu::classpath::jdwp::VMVirtualMachine::initialize ()
{
  _jdwp_suspend_counts = new ::java::util::Hashtable ();
  JavaVM *vm = _Jv_GetJavaVM ();
  vm->GetEnv (reinterpret_cast<void **> (&_jdwp_jvmtiEnv), JVMTI_VERSION_1_0);
}

void
gnu::classpath::jdwp::VMVirtualMachine ::suspendThread (Thread *thread)
{
  jint value;
  Integer *count;
  {
    JvSynchronize dummy (_jdwp_suspend_counts);
    count = reinterpret_cast<Integer *> (_jdwp_suspend_counts->get (thread));
    if (count == NULL)
      {
	// New -- suspend thread
	value = 0;
      }
    else
      {
	// Thread already suspended
	value = count->intValue ();
      }

    count = Integer::valueOf (++value);
    _jdwp_suspend_counts->put (thread, count);
  }

  if (value == 1)
    {
      // Suspend the thread
      jvmtiError err = _jdwp_jvmtiEnv->SuspendThread (thread);
      if (err != JVMTI_ERROR_NONE)
	{
	  using namespace gnu::classpath::jdwp::exception;
	  char *reason;
	  _jdwp_jvmtiEnv->GetErrorName (err, &reason);
	  ::java::lang::String *txt
	      = JvNewStringLatin1 ("could not suspend thread: ");
	  ::java::lang::StringBuffer *msg
	      = new ::java::lang::StringBuffer (txt);
	  msg->append (JvNewStringLatin1 (reason));
	  _jdwp_jvmtiEnv->Deallocate ((unsigned char *) reason);
	  throw new JdwpInternalErrorException (msg->toString ());
	}
    }
}

void
gnu::classpath::jdwp::VMVirtualMachine::resumeThread (Thread *thread)
{
  jint value;
  {
    JvSynchronize dummy (_jdwp_suspend_counts);
    Integer *count
      = reinterpret_cast<Integer *> (_jdwp_suspend_counts->get (thread));
    if (count == NULL)
      {
	// Thread not suspended: ThreadReference.Resume says to ignore it.
	return;
      }
    else
      {
	// Decrement suspend count
	value = count->intValue () - 1;
      }

    if (value == 0)
      {
	// Thread will be resumed, remove from table
	_jdwp_suspend_counts->remove (thread);
      }
    else
      {
	// Thread stays suspended: record new suspend count
	count = Integer::valueOf (value);
	_jdwp_suspend_counts->put (thread, count);
      }
  }

  if (value == 0)
    {
      jvmtiError err = _jdwp_jvmtiEnv->ResumeThread (thread);
      if (err != JVMTI_ERROR_NONE)
	{
	  using namespace gnu::classpath::jdwp::exception;
	  char *reason;
	  _jdwp_jvmtiEnv->GetErrorName (err, &reason);
	  ::java::lang::String *txt 
	      = JvNewStringLatin1 ("could not resume thread: ");
	  ::java::lang::StringBuffer *msg
	      = new ::java::lang::StringBuffer (txt);
	  msg->append (JvNewStringLatin1 (reason));
	  _jdwp_jvmtiEnv->Deallocate ((unsigned char *) reason);
	  throw new JdwpInternalErrorException (msg->toString ());
	}
    }
}

jint
gnu::classpath::jdwp::VMVirtualMachine::getSuspendCount (Thread *thread)
{
  jint suspensions = 0;
  Integer *count
    = reinterpret_cast<Integer *> (_jdwp_suspend_counts->get (thread));
  if (count != NULL)
    suspensions = count->intValue ();
  return suspensions;
}

void
gnu::classpath::jdwp::VMVirtualMachine::registerEvent (EventRequest *request)
{
  switch (request->getEventKind ())
    {
    case EventRequest::EVENT_SINGLE_STEP:
      break;

    case EventRequest::EVENT_BREAKPOINT:
      break;

    case EventRequest::EVENT_FRAME_POP:
      break;

    case EventRequest::EVENT_EXCEPTION:
      break;

    case EventRequest::EVENT_USER_DEFINED:
      break;

    case EventRequest::EVENT_THREAD_START:
      break;

    case EventRequest::EVENT_THREAD_END:
      break;

    case EventRequest::EVENT_CLASS_PREPARE:
      break;

    case EventRequest::EVENT_CLASS_LOAD:
      break;

    case EventRequest::EVENT_CLASS_UNLOAD:
      break;

    case EventRequest::EVENT_FIELD_ACCESS:
      break;

    case EventRequest::EVENT_FIELD_MODIFY:
      break;

    case EventRequest::EVENT_METHOD_ENTRY:
      break;

    case EventRequest::EVENT_METHOD_EXIT:
      break;

    case EventRequest::EVENT_VM_INIT:
      break;
      
    case EventRequest::EVENT_VM_DEATH:
      break;
    }
}

void
gnu::classpath::jdwp::VMVirtualMachine::unregisterEvent (EventRequest *request)
{
  switch (request->getEventKind ())
    {
    case EventRequest::EVENT_SINGLE_STEP:
      break;

    case EventRequest::EVENT_BREAKPOINT:
      break;

    case EventRequest::EVENT_FRAME_POP:
      break;

    case EventRequest::EVENT_EXCEPTION:
      break;

    case EventRequest::EVENT_USER_DEFINED:
      break;

    case EventRequest::EVENT_THREAD_START:
      break;

    case EventRequest::EVENT_THREAD_END:
      break;
	
    case EventRequest::EVENT_CLASS_PREPARE:
      break;

    case EventRequest::EVENT_CLASS_LOAD:
      break;

    case EventRequest::EVENT_CLASS_UNLOAD:
      break;

    case EventRequest::EVENT_FIELD_ACCESS:
      break;

    case EventRequest::EVENT_FIELD_MODIFY:
      break;

    case EventRequest::EVENT_METHOD_ENTRY:
      break;

    case EventRequest::EVENT_METHOD_EXIT:
      break;

    case EventRequest::EVENT_VM_INIT:
      break;
      
    case EventRequest::EVENT_VM_DEATH:
      break;
    }
}

void
gnu::classpath::jdwp::VMVirtualMachine::clearEvents (jbyte kind)
{
}

jint
gnu::classpath::jdwp::VMVirtualMachine::getAllLoadedClassesCount (void)
{
  return 0;
}

java::util::Iterator *
gnu::classpath::jdwp::VMVirtualMachine::getAllLoadedClasses (void)
{
  return NULL;
}

jint
gnu::classpath::jdwp::VMVirtualMachine::getClassStatus (jclass klass)
{
  return 0;
}

JArray<gnu::classpath::jdwp::VMMethod *> *
gnu::classpath::jdwp::VMVirtualMachine::getAllClassMethods (jclass klass)
{
  return NULL;
}

gnu::classpath::jdwp::VMMethod *
gnu::classpath::jdwp::VMVirtualMachine::getClassMethod (jclass klass, jlong id)
{
  return NULL;
}

java::util::ArrayList *
gnu::classpath::jdwp::VMVirtualMachine::getFrames (Thread *thread,
						   jint start,
						   jint length)
{
  return NULL;
}

gnu::classpath::jdwp::VMFrame *
gnu::classpath::jdwp::VMVirtualMachine::getFrame (Thread *thread,
						  ::java::nio::ByteBuffer *bb)
{
  return NULL;
}

jint
gnu::classpath::jdwp::VMVirtualMachine::getFrameCount (Thread *thread)
{
  return 0;
}

jint
gnu::classpath::jdwp::VMVirtualMachine::getThreadStatus (Thread *thread)
{
  return 0;
}

java::util::ArrayList *
gnu::classpath::jdwp::VMVirtualMachine::getLoadRequests (ClassLoader *cl)
{
  return NULL;
}

MethodResult *
gnu::classpath::jdwp::VMVirtualMachine::executeMethod (jobject obj,
						       Thread *thread,
						       jclass clazz,
						       reflect::Method *method,
						       jobjectArray values,
						       jboolean nonVirtual)
{
  return NULL;
}

jstring
gnu::classpath::jdwp::VMVirtualMachine::getSourceFile (jclass clazz)
{
  return NULL;
}
