/* -*- Mode: C; c-file-style: "gnu" -*-
   jvmdicls.c -- JVMDI Class Information Functions
   Created: Hernan Otero <hernan_otero@bigfoot.com>, 18-Jul-1998.
 */
/*
  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) 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 "jvmdiint.h"
#include "objects.h"
#include "log.h"

#include <assert.h>

#define MYLOG "JVMDI"

JNIEXPORT jvmdiError JNICALL
JVMDI_GetClassName(JNIEnv *env, jclass clazz, char** namePtr)
{
  jstring name = NULL;

  /* the usual NULL check. */
  if (env == NULL
      || namePtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  if (clazz == NULL)
    return JVMDI_ERROR_INVALID_CLASS;

  name = (*env)->NewStringUTF(env, ((ClazzFile *) clazz)->class_name);

  if (name == NULL)
    {
      /* how do we free things?  it doesn't make sense to have the
	 same thread local objects for jvmdi methods like the JNI spec
	 does for native methods, does it?  I suppose, since these
	 objects were not changed into global refs, then they should
	 be collected the next time around, so we shouldn't worry. */
      return JVMDI_ERROR_OUT_OF_MEMORY;
    }

  *namePtr = name;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetSourcePath(JNIEnv *env, jclass clazz, char **sourcePathPtr)
{
  if (env == NULL || clazz == NULL || sourcePathPtr == NULL) {
    return JVMDI_ERROR_NULL_POINTER;
  }
  assert(0);
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetClassModifiers(JNIEnv *env, jclass clazz, jint *modifiersPtr)
{
  /* the usual NULL check. */
  if (env == NULL
      || modifiersPtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  if (clazz == NULL)
    return JVMDI_ERROR_INVALID_CLASS;

  *modifiersPtr = ((ClazzFile *) clazz)->access_flags;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetClassMethods(JNIEnv *env, jclass clazz, 
                      jint *methodCountPtr, jmethodID **methodsPtr)
{
  ClazzFile *c = (ClazzFile *) clazz;
  int i;

  if (env == NULL
      || methodCountPtr == NULL
      || methodsPtr == NULL) {
    return JVMDI_ERROR_NULL_POINTER;
  }

  if (c == NULL) {
    return JVMDI_ERROR_INVALID_CLASS;
  }

  *methodCountPtr = c->num_methods;
  if (JVMDI_Allocate(env,
		     c->num_methods * sizeof(jmethodID),
		     (jbyte**) methodsPtr) == JVMDI_ERROR_OUT_OF_MEMORY) {
    return JVMDI_ERROR_OUT_OF_MEMORY;
  }

  for (i = 0; i < c->num_methods; ++i) {
    (*methodsPtr)[i] = c->methods[i];
  }

  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetClassFields(JNIEnv *env, jclass clazz, 
                     jint *fieldCountPtr, jfieldID **fieldsPtr)
{
  ClazzFile *c = (ClazzFile *) clazz;
  int i;

  if (env == NULL
      || fieldCountPtr == NULL
      || fieldsPtr == NULL) {
    return JVMDI_ERROR_NULL_POINTER;
  }

  if (c == NULL) {
    return JVMDI_ERROR_INVALID_CLASS;
  }

  *fieldCountPtr = c->num_fields;
  if (JVMDI_Allocate(env,
		     c->num_fields * sizeof(jfieldID),
		     (jbyte**) fieldsPtr) == JVMDI_ERROR_OUT_OF_MEMORY) {
    return JVMDI_ERROR_OUT_OF_MEMORY;
  }

  for (i = 0; i < c->num_fields; ++i) {
    (*fieldsPtr)[i] = c->fields[i];
  }

  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_GetImplementedInterfaces(JNIEnv *env, jclass clazz,
                               jint *interfaceCountPtr, 
                               jclass **interfacesPtr)
{
  ClazzFile *c = jclass_to_clazzfile(env, clazz);
  int i;

  if (env == NULL
      || interfaceCountPtr == NULL
      || interfacesPtr == NULL) {
    return JVMDI_ERROR_NULL_POINTER;
  }

  if (c == NULL) {
    return JVMDI_ERROR_INVALID_CLASS;
  }

  *interfaceCountPtr = c->num_interfaces;
  if (JVMDI_Allocate(env,
		     c->num_interfaces * sizeof(jclass),
		     (jbyte**) interfacesPtr) == JVMDI_ERROR_OUT_OF_MEMORY) {
    return JVMDI_ERROR_OUT_OF_MEMORY;
  }

  for (i = 0; i < c->num_interfaces; ++i) {
    (*interfacesPtr)[i] = c->interfaces[ i ];
  }

  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_IsInterface(JNIEnv *env, jclass clazz, jboolean *isInterfacePtr)
{
  /* the usual NULL check. */
  if (env == NULL
      || isInterfacePtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  if (clazz == NULL)
    return JVMDI_ERROR_INVALID_CLASS;

  *isInterfacePtr =
    (((ClazzFile *) clazz)->access_flags & ACC_INTERFACE) != 0;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_IsArray(JNIEnv *env, jclass clazz, jboolean *isArrayPtr)
{
  /* the usual NULL check. */
  if (env == NULL
      || isArrayPtr == NULL)
    return JVMDI_ERROR_NULL_POINTER;

  if (clazz == NULL)
    return JVMDI_ERROR_INVALID_CLASS;

  *isArrayPtr =
    (((ClazzFile *) clazz)->access_flags & ACC_ARRAY) != 0;
  return JVMDI_ERROR_NONE;
}

JNIEXPORT jvmdiError JNICALL
JVMDI_ClassLoader(JNIEnv *env, jclass clazz, jobject *classloaderPtr)
{
  jmethodID getClassLoaderMethod;
  if (env == NULL
      || clazz == NULL
      || classloaderPtr == NULL) {
    return JVMDI_ERROR_NULL_POINTER;
  }

  if (clazz == NULL) {
    return JVMDI_ERROR_INVALID_CLASS;
  }

  getClassLoaderMethod = (*env)->GetMethodID(env, clazz,
					     "getClassLoader", "Ljava/lang/ClassLoader;(V)");
  assert(getClassLoaderMethod != NULL);
  *classloaderPtr = (*env)->CallObjectMethod(env, clazz,
					     getClassLoaderMethod);
  return JVMDI_ERROR_NONE;
}
