// natRuntime.cc - Implementation of native side of Runtime class.

/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  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 <platform.h>

#include <stdlib.h>

#include <gcj/cni.h>
#include <jvm.h>
#include <java-props.h>
#include <java-stack.h>
#include <java/lang/Long.h>
#include <java/lang/Runtime.h>
#include <java/lang/UnknownError.h>
#include <java/lang/UnsatisfiedLinkError.h>
#include <gnu/gcj/runtime/FinalizerThread.h>
#include <java/io/File.h>
#include <java/util/TimeZone.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/Process.h>
#include <java/lang/ClassLoader.h>

// It is convenient and safe to simply include all of these.
#include <java/lang/Win32Process.h>
#include <java/lang/EcosProcess.h>
#include <java/lang/PosixProcess.h>

#include <jni.h>

#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#include <errno.h>

#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif

#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif



#ifdef USE_LTDL
#include <ltdl.h>

/* FIXME: we don't always need this.  The next libtool will let us use
   AC_LTDL_PREOPEN to see if we do.  */
extern const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } };

struct lookup_data
{
  const char *symname;
  void *result;
};

static int
find_symbol (lt_dlhandle handle, lt_ptr data)
{
  lookup_data *ld = (lookup_data *) data;
  ld->result = lt_dlsym (handle, ld->symname);
  return ld->result != NULL;
}

void *
_Jv_FindSymbolInExecutable (const char *symname)
{
  lookup_data data;
  data.symname = symname;
  data.result = NULL;
  lt_dlforeach (find_symbol, (lt_ptr) &data);
  return data.result;
}

#else

void *
_Jv_FindSymbolInExecutable (const char *)
{
  return NULL;
}

#endif /* USE_LTDL */



void
java::lang::Runtime::runFinalizationForExit ()
{
  if (finalizeOnExit)
    _Jv_RunAllFinalizers ();
}

void
java::lang::Runtime::exitInternal (jint status)
{
  // Make status right for Unix.  This is perhaps strange.
  if (status < 0 || status > 255)
    status = 255;

  ::exit (status);
}

jlong
java::lang::Runtime::freeMemory (void)
{
  return _Jv_GCFreeMemory ();
}

void
java::lang::Runtime::gc (void)
{
  _Jv_RunGC ();
}

#ifdef USE_LTDL
// List of names for JNI_OnLoad.
static const char *onload_names[] = _Jv_platform_onload_names;
#endif

void
java::lang::Runtime::_load (jstring path, jboolean do_search)
{
  JvSynchronize sync (this);
  using namespace java::lang;
#ifdef USE_LTDL
  jint len = _Jv_GetStringUTFLength (path);
  char buf[len + 1 + strlen (_Jv_platform_solib_prefix)
	   + strlen (_Jv_platform_solib_suffix)];
  int offset = 0;
  if (do_search)
    {
      strcpy (buf, _Jv_platform_solib_prefix);
      offset = strlen (_Jv_platform_solib_prefix);
    }
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), &buf[offset]);
  buf[offset + total] = '\0';

  char *lib_name = buf;

  if (do_search)
    {
      ClassLoader *look = _Jv_StackTrace::GetFirstNonSystemClassLoader ();

      if (look != NULL)
	{
	  // Don't include solib prefix in string passed to
	  // findLibrary.
	  jstring name = look->findLibrary(JvNewStringUTF(&buf[offset]));
	  if (name != NULL)
	    {
	      len = _Jv_GetStringUTFLength (name);
	      lib_name = (char *) _Jv_AllocBytes(len + 1);
	      total = JvGetStringUTFRegion (name, 0,
					    name->length(), lib_name);
	      lib_name[total] = '\0';
	      // Don't append suffixes any more; we have the full file
	      // name.
	      do_search = false;
	    }
	}
    }

  lt_dlhandle h;
  // FIXME: make sure path is absolute.
  {
    // Synchronize on java.lang.Class. This is to protect the class chain from
    // concurrent modification by class registration calls which may be run
    // during the dlopen().
    JvSynchronize sync (&java::lang::Class::class$);
    h = do_search ? lt_dlopenext (lib_name) : lt_dlopen (lib_name);
  }
  if (h == NULL)
    {
      const char *msg = lt_dlerror ();
      jstring str = JvNewStringLatin1 (lib_name);
      str = str->concat (JvNewStringLatin1 (": "));
      str = str->concat (JvNewStringLatin1 (msg));
      throw new UnsatisfiedLinkError (str);
    }

  // Search for JNI_OnLoad function.
  void *onload = NULL;
  const char **name = onload_names;
  while (*name != NULL)
    {
      onload = lt_dlsym (h, *name);
      if (onload != NULL)
	break;
      ++name;
    }

  if (onload != NULL)
    {
      JavaVM *vm = _Jv_GetJavaVM ();
      if (vm == NULL)
	{
	  // FIXME: what?
	  return;
	}

      // Push a new frame so that JNI_OnLoad will get the right class
      // loader if it calls FindClass.
      ::java::lang::ClassLoader *loader
	  = _Jv_StackTrace::GetFirstNonSystemClassLoader();
      JNIEnv *env = _Jv_GetJNIEnvNewFrameWithLoader (loader);
      jint vers = ((jint (JNICALL *) (JavaVM *, void *)) onload) (vm, NULL);
      _Jv_JNI_PopSystemFrame (env);
      if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2
	  && vers != JNI_VERSION_1_4)
	{
	  // FIXME: unload the library.
	  throw new UnsatisfiedLinkError (JvNewStringLatin1 ("unrecognized version from JNI_OnLoad"));
	}
    }
#else
  throw new UnknownError
    (JvNewStringLatin1 (do_search
			? "Runtime.loadLibrary not implemented"
			: "Runtime.load not implemented"));
#endif /* USE_LTDL */
}

jboolean
java::lang::Runtime::loadLibraryInternal (jstring lib)
{
  JvSynchronize sync (this);
  using namespace java::lang;
#ifdef USE_LTDL
  jint len = _Jv_GetStringUTFLength (lib);
  char buf[len + 1];
  jsize total = JvGetStringUTFRegion (lib, 0, lib->length(), buf);
  buf[total] = '\0';
  // FIXME: make sure path is absolute.
  lt_dlhandle h = lt_dlopenext (buf);
  return h != NULL;
#else
  return false;
#endif /* USE_LTDL */
}

void
java::lang::Runtime::init (void)
{
#ifdef USE_LTDL
  lt_dlinit ();
  // Set module load path.
  lt_dlsetsearchpath (_Jv_Module_Load_Path);
  // Make sure self is opened.
  lt_dlopen (NULL);
#endif
}

void
java::lang::Runtime::runFinalization (void)
{
  gnu::gcj::runtime::FinalizerThread::finalizerReady ();
}

jlong
java::lang::Runtime::totalMemory (void)
{
  return _Jv_GCTotalMemory ();
}

jlong
java::lang::Runtime::maxMemory (void)
{
  // We don't have a maximum.  FIXME: we might if we ask the GC for
  // one.
  return Long::MAX_VALUE;
}

void
java::lang::Runtime::traceInstructions (jboolean)
{
  // Do nothing.
}

void
java::lang::Runtime::traceMethodCalls (jboolean)
{
  // Do nothing.
}

java::lang::Process *
java::lang::Runtime::execInternal (jstringArray cmd,
				   jstringArray env,
				   java::io::File *dir)
{
  return new _Jv_platform_process (cmd, env, dir, false);
}

jint
java::lang::Runtime::availableProcessors (void)
{
  // FIXME: find the real value.
  return 1;
}

jstring
java::lang::Runtime::nativeGetLibname (jstring pathname, jstring libname)
{
  java::lang::StringBuffer *sb = new java::lang::StringBuffer ();
  sb->append(pathname);
  if (pathname->length() > 0)
    sb->append (_Jv_platform_file_separator);

  sb->append (JvNewStringLatin1 (_Jv_platform_solib_prefix));
  sb->append(libname);
  sb->append (JvNewStringLatin1 (_Jv_platform_solib_suffix));

  return sb->toString();
}
