* Removed all Id tags.
[cacao.git] / src / vm / properties.c
index ba2935e520e69df2a869f0802c13ff557c923b1c..1eef3c8c036cf6296dbf5cb245e40a2f3a3c80dc 100644 (file)
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   $Id: properties.c 7234 2007-01-22 17:03:04Z twisti $
-
 */
 
 
 #include "config.h"
 
+#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/utsname.h>
 #include <time.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+#if defined(WITH_JRE_LAYOUT)
+# include <libgen.h>
+#endif
 
 #include "vm/types.h"
 
 #include "mm/memory.h"
 
-#include "vm/global.h"
-#include "native/include/java_lang_String.h"
+#include "native/jni.h"
 
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_util_Properties.h"
-#endif
+#include "vm/global.h"                      /* required by java_lang_String.h */
+#include "native/include/java_lang_String.h"
 
 #include "toolbox/list.h"
 #include "toolbox/util.h"
-#include "vm/method.h"
-#include "vm/options.h"
+
 #include "vm/properties.h"
 #include "vm/stringlocal.h"
 #include "vm/vm.h"
+
 #include "vm/jit/asmpart.h"
 
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
 
 /* internal property structure ************************************************/
 
-typedef struct list_properties_entry list_properties_entry;
+typedef struct list_properties_entry_t list_properties_entry_t;
 
-struct list_properties_entry {
-       char     *key;
-       char     *value;
-       listnode linkage;
+struct list_properties_entry_t {
+       char       *key;
+       char       *value;
+       listnode_t  linkage;
 };
 
 
 /* global variables ***********************************************************/
 
-static list *list_properties = NULL;
+static list_t *list_properties = NULL;
 
 
 /* properties_init *************************************************************
@@ -78,126 +83,378 @@ static list *list_properties = NULL;
 
 *******************************************************************************/
 
-bool properties_init(void)
+void properties_init(void)
+{
+       list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
+}
+
+
+/* properties_set **************************************************************
+
+   Fill the properties list with default values.
+
+*******************************************************************************/
+
+void properties_set(void)
 {
+       int             len;
+       char           *p;
+
+       char           *java_home;
+       char           *boot_class_path;
+
 #if defined(ENABLE_JAVASE)
+       char           *class_path;
+       char           *boot_library_path;
+
+# if defined(WITH_CLASSPATH_GNU)
        char           *cwd;
-       char           *env_java_home;
        char           *env_user;
        char           *env_home;
        char           *env_lang;
-       char           *java_home;
        char           *extdirs;
        char           *lang;
        char           *country;
        struct utsname *utsnamebuf;
-       s4              len;
+
+       char           *java_library_path;
+# endif
 #endif
 
-       /* create the properties list */
+#if defined(WITH_JRE_LAYOUT)
+       /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
 
-       list_properties = list_create(OFFSET(list_properties_entry, linkage));
+       p = MNEW(char, 4096);
 
-#if defined(ENABLE_JAVASE)
-       /* get properties from system */
+       if (readlink("/proc/self/exe", p, 4095) == -1)
+               vm_abort("properties_set: readlink failed: %s\n", strerror(errno));
 
-       cwd           = _Jv_getcwd();
-       env_java_home = getenv("JAVA_HOME");
-       env_user      = getenv("USER");
-       env_home      = getenv("HOME");
-       env_lang      = getenv("LANG");
+       /* Get the path of the current executable. */
 
-       utsnamebuf = NEW(struct utsname);
+       p = dirname(p);
 
-       uname(utsnamebuf);
+# if defined(WITH_CLASSPATH_GNU)
 
-       /* set JAVA_HOME to default prefix if not defined */
+       /* Set java.home. */
 
-       if (env_java_home == NULL)
-               env_java_home = cacao_prefix;
+       len = strlen(path) + strlen("/..") + strlen("0");
 
-       /* fill in system properties */
+       java_home = MNEW(char, len);
 
-       properties_add("java.version", JAVA_VERSION);
-       properties_add("java.vendor", "GNU Classpath");
-       properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
+       strcpy(java_home, p);
+       strcat(java_home, "/..");
+
+       /* Set the path to Java core native libraries. */
+
+       len = strlen(cacao_prefix) + strlen("/lib/classpath") + strlen("0");
+
+       boot_library_path = MNEW(char, len);
+
+       strcpy(boot_library_path, java_home);
+       strcat(boot_library_path, "/lib/classpath");
+
+# elif defined(WITH_CLASSPATH_SUN)
 
-       /* add /jre to java.home property */
+       /* Find correct java.home.  We check if there is a JRE
+          co-located. */
 
-       len = strlen(env_java_home) + strlen("/jre") + strlen("0");
+       /* NOTE: We use the server VM here as it should be available on
+          all architectures. */
+
+       len =
+               strlen(p) +
+               strlen("/../jre/lib/"JAVA_ARCH"/server/libjvm.so") +
+               strlen("0");
 
        java_home = MNEW(char, len);
 
-       strcpy(java_home, env_java_home);
-       strcat(java_home, "/jre");
+       strcpy(java_home, p);
+       strcat(java_home, "/../jre/lib/"JAVA_ARCH"/server/libjvm.so");
+
+       /* Check if that libjvm.so exists. */
+
+       if (access(java_home, F_OK) == 0) {
+               /* Yes, we add /jre to java.home. */
+
+               strcpy(java_home, p);
+               strcat(java_home, "/../jre");
+       }
+       else {
+               /* No, java.home is parent directory. */
+
+               strcpy(java_home, p);
+               strcat(java_home, "/..");
+       }
+
+       /* Set the path to Java core native libraries. */
+
+       len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
+
+       boot_library_path = MNEW(char, len);
+
+       strcpy(boot_library_path, java_home);
+       strcat(boot_library_path, "/lib/"JAVA_ARCH);
+
+# else
+#  error unknown classpath configuration
+# endif
+
+       /* Free path. */
+
+       MFREE(p, char, len);
+
+#else
+       java_home         = CACAO_PREFIX;
+
+# if defined(WITH_CLASSPATH_GNU)
+
+       boot_library_path = CLASSPATH_LIBDIR"/classpath";
+
+# elif defined(WITH_CLASSPATH_SUN)
+
+       boot_library_path = CLASSPATH_LIBDIR;
+
+# elif defined(WITH_CLASSPATH_CLDC1_1)
+
+       /* No boot_library_path required. */
+
+# else
+#  error unknown classpath configuration
+# endif
+#endif
 
        properties_add("java.home", java_home);
 
+       /* Set the bootclasspath. */
+
+       p = getenv("BOOTCLASSPATH");
+
+       if (p != NULL) {
+               boot_class_path = MNEW(char, strlen(p) + strlen("0"));
+               strcpy(boot_class_path, p);
+       }
+       else {
+#if defined(WITH_JRE_LAYOUT)
+# if defined(WITH_CLASSPATH_GNU)
+
+               len =
+                       strlen(java_home) + strlen("/share/cacao/vm.zip:") +
+                       strlen(java_home) + strlen("/share/classpath/glibj.zip") +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, java_home);
+               strcat(boot_class_path, "/share/cacao/vm.zip");
+               strcat(boot_class_path, ":");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/share/classpath/glibj.zip");
+
+# elif defined(WITH_CLASSPATH_SUN)
+
+               /* This is the bootclasspath taken from HotSpot (see
+                  hotspot/src/share/vm/runtime/os.cpp
+                  (os::set_boot_path)). */
+
+               len =
+                       strlen(java_home) + strlen("/lib/resources.jar:") +
+                       strlen(java_home) + strlen("/lib/rt.jar:") +
+                       strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
+                       strlen(java_home) + strlen("/lib/jsse.jar:") +
+                       strlen(java_home) + strlen("/lib/jce.jar:") +
+                       strlen(java_home) + strlen("/lib/charsets.jar:") +
+                       strlen(java_home) + strlen("/classes") +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/resources.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/rt.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/sunrsasign.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/jsse.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/jce.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/lib/charsets.jar:");
+               strcat(boot_class_path, java_home);
+               strcat(boot_class_path, "/classes");
+
+# else
+#  error unknown classpath configuration
+# endif
+#else
+# if defined(WITH_CLASSPATH_GNU)
+
+               len =
+                       strlen(CACAO_VM_ZIP) +
+                       strlen(":") +
+                       strlen(CLASSPATH_CLASSES) +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, CACAO_VM_ZIP);
+               strcat(boot_class_path, ":");
+               strcat(boot_class_path, CLASSPATH_CLASSES);
+
+# elif defined(WITH_CLASSPATH_SUN)
+
+               /* This is the bootclasspath taken from HotSpot (see
+                  hotspot/src/share/vm/runtime/os.cpp
+                  (os::set_boot_path)). */
+
+               len =
+                       strlen(CLASSPATH_PREFIX"/lib/resources.jar:") +
+                       strlen(CLASSPATH_PREFIX"/lib/rt.jar:") +
+                       strlen(CLASSPATH_PREFIX"/lib/sunrsasign.jar:") +
+                       strlen(CLASSPATH_PREFIX"/lib/jsse.jar:") +
+                       strlen(CLASSPATH_PREFIX"/lib/jce.jar:") +
+                       strlen(CLASSPATH_PREFIX"/lib/charsets.jar:") +
+                       strlen(CLASSPATH_PREFIX"/classes") +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, CLASSPATH_PREFIX"/lib/resources.jar:");
+               strcat(boot_class_path, CLASSPATH_PREFIX"/lib/rt.jar:");
+               strcat(boot_class_path, CLASSPATH_PREFIX"/lib/sunrsasign.jar:");
+               strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jsse.jar:");
+               strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jce.jar:");
+               strcat(boot_class_path, CLASSPATH_PREFIX"/lib/charsets.jar:");
+               strcat(boot_class_path, CLASSPATH_PREFIX"/classes");
+
+# elif defined(WITH_CLASSPATH_CLDC1_1)
+
+               len =
+                       strlen(CLASSPATH_CLASSES) +
+                       strlen("0");
+
+               boot_class_path = MNEW(char, len);
+
+               strcpy(boot_class_path, CLASSPATH_CLASSES);
+
+# else
+#  error unknown classpath configuration
+# endif
+#endif
+       }
+
+       properties_add("sun.boot.class.path", boot_class_path);
+       properties_add("java.boot.class.path", boot_class_path);
+
+#if defined(ENABLE_JAVASE)
+
+       /* Set the classpath. */
+
+       p = getenv("CLASSPATH");
+
+       if (p != NULL) {
+               class_path = MNEW(char, strlen(p) + strlen("0"));
+               strcpy(class_path, p);
+       }
+       else {
+               class_path = MNEW(char, strlen(".") + strlen("0"));
+               strcpy(class_path, ".");
+       }
+
+       properties_add("java.class.path", class_path);
+
+       /* Add java.vm properties. */
+
        properties_add("java.vm.specification.version", "1.0");
        properties_add("java.vm.specification.vendor", "Sun Microsystems Inc.");
        properties_add("java.vm.specification.name", "Java Virtual Machine Specification");
        properties_add("java.vm.version", VERSION);
        properties_add("java.vm.vendor", "CACAO Team");
        properties_add("java.vm.name", "CACAO");
-       properties_add("java.specification.version", "1.5");
-       properties_add("java.specification.vendor", "Sun Microsystems Inc.");
-       properties_add("java.specification.name", "Java Platform API Specification");
-       properties_add("java.class.version", CLASS_VERSION);
-       properties_add("java.class.path", _Jv_classpath);
+
+# if defined(ENABLE_INTRP)
+       if (opt_intrp) {
+               /* XXX We don't support java.lang.Compiler */
+/*             properties_add("java.compiler", "cacao.intrp"); */
+               properties_add("java.vm.info", "interpreted mode");
+       }
+       else
+# endif
+       {
+               /* XXX We don't support java.lang.Compiler */
+/*             properties_add("java.compiler", "cacao.jit"); */
+               properties_add("java.vm.info", "JIT mode");
+       }
+
+# if defined(WITH_CLASSPATH_GNU)
+
+       /* Get properties from system. */
+
+       cwd      = _Jv_getcwd();
+
+       env_user = getenv("USER");
+       env_home = getenv("HOME");
+       env_lang = getenv("LANG");
+
+       utsnamebuf = NEW(struct utsname);
+
+       uname(utsnamebuf);
 
        properties_add("java.runtime.version", VERSION);
        properties_add("java.runtime.name", "CACAO");
 
-       /* Set bootclasspath properties. One for GNU classpath and the
-          other for compatibility with Sun (required by most
-          applications). */
+       properties_add("java.specification.version", "1.5");
+       properties_add("java.specification.vendor", "Sun Microsystems Inc.");
+       properties_add("java.specification.name", "Java Platform API Specification");
 
-       properties_add("java.boot.class.path", _Jv_bootclasspath);
-       properties_add("sun.boot.class.path", _Jv_bootclasspath);
+       properties_add("java.version", JAVA_VERSION);
+       properties_add("java.vendor", "GNU Classpath");
+       properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
+
+       properties_add("java.class.version", CLASS_VERSION);
 
-#if defined(WITH_STATIC_CLASSPATH)
+#  if defined(WITH_STATIC_CLASSPATH)
        properties_add("gnu.classpath.boot.library.path", ".");
        properties_add("java.library.path" , ".");
-#else
-       /* fill gnu.classpath.boot.library.path with GNU Classpath library
-       path */
+#  else
+       properties_add("gnu.classpath.boot.library.path", boot_library_path);
 
-       properties_add("gnu.classpath.boot.library.path", classpath_libdir);
-       properties_add("java.library.path", _Jv_java_library_path);
-#endif
+       /* Get and set java.library.path. */
+
+       java_library_path = getenv("LD_LIBRARY_PATH");
+
+       if (java_library_path == NULL)
+               java_library_path = "";
+
+       properties_add("java.library.path", java_library_path);
+#  endif
 
        properties_add("java.io.tmpdir", "/tmp");
 
-#if defined(ENABLE_INTRP)
+#  if defined(ENABLE_INTRP)
        if (opt_intrp) {
-               /* XXX We don't support java.lang.Compiler */
-/*             properties_add("java.compiler", "cacao.intrp"); */
-               properties_add("java.vm.info", "interpreted mode");
                properties_add("gnu.java.compiler.name", "cacao.intrp");
        }
        else
-#endif
+#  endif
        {
-               /* XXX We don't support java.lang.Compiler */
-/*             properties_add("java.compiler", "cacao.jit"); */
-               properties_add("java.vm.info", "JIT mode");
                properties_add("gnu.java.compiler.name", "cacao.jit");
        }
 
        /* set the java.ext.dirs property */
 
-       len = strlen(env_java_home) + strlen("/jre/lib/ext") + strlen("0");
+       len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
 
        extdirs = MNEW(char, len);
 
-       strcpy(extdirs, env_java_home);
+       strcpy(extdirs, java_home);
        strcat(extdirs, "/jre/lib/ext");
 
        properties_add("java.ext.dirs", extdirs);
 
        properties_add("java.endorsed.dirs", ""CACAO_PREFIX"/jre/lib/endorsed");
 
-#if defined(DISABLE_GC)
+#  if defined(DISABLE_GC)
        /* When we disable the GC, we mmap the whole heap to a specific
           address, so we can compare call traces. For this reason we have
           to add the same properties on different machines, otherwise
@@ -207,46 +464,32 @@ bool properties_init(void)
        properties_add("os.arch", "unknown");
        properties_add("os.name", "unknown");
        properties_add("os.version", "unknown");
-#else
-       /* We need to set the os.arch hardcoded to be compatible with SUN. */
-
-# if defined(__I386__)
-       /* map all x86 architectures (i386, i486, i686) to i386 */
-
-       properties_add("os.arch", "i386");
-# elif defined(__POWERPC__)
-       properties_add("os.arch", "ppc");
-# elif defined(__X86_64__)
-       properties_add("os.arch", "amd64");
-# else
-       /* default to what uname returns */
-
-       properties_add("os.arch", utsnamebuf->machine);
-# endif
-
+#  else
+       properties_add("os.arch", JAVA_ARCH);
        properties_add("os.name", utsnamebuf->sysname);
        properties_add("os.version", utsnamebuf->release);
-#endif
-
-       properties_add("file.separator", "/");
-       properties_add("path.separator", ":");
-       properties_add("line.separator", "\n");
-       properties_add("user.name", env_user ? env_user : "null");
-       properties_add("user.home", env_home ? env_home : "null");
-       properties_add("user.dir", cwd ? cwd : "null");
+#  endif
 
-#if defined(WITH_STATIC_CLASSPATH)
+#  if defined(WITH_STATIC_CLASSPATH)
        /* This is just for debugging purposes and can cause troubles in
        GNU Classpath. */
 
        properties_add("gnu.cpu.endian", "unknown");
-#else
-# if WORDS_BIGENDIAN == 1
+#  else
+#   if WORDS_BIGENDIAN == 1
        properties_add("gnu.cpu.endian", "big");
-# else
+#   else
        properties_add("gnu.cpu.endian", "little");
-# endif
-#endif
+#   endif
+#  endif
+
+       properties_add("file.separator", "/");
+       properties_add("path.separator", ":");
+       properties_add("line.separator", "\n");
+
+       properties_add("user.name", env_user ? env_user : "null");
+       properties_add("user.home", env_home ? env_home : "null");
+       properties_add("user.dir", cwd ? cwd : "null");
 
        /* get locale */
 
@@ -277,39 +520,32 @@ bool properties_init(void)
                properties_add("user.language", "en");
                properties_add("user.country", "US");
        }
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-    properties_add("microedition.configuration", "CLDC-1.1");
-    properties_add("microedition.platform", "generic");
-    properties_add("microedition.encoding", "ISO8859_1");
-    properties_add("microedition.profiles", "");
-#else
-#error unknown Java configuration
-#endif
 
-       /* everything's ok */
+# elif defined(WITH_CLASSPATH_SUN)
 
-       return true;
-}
+       /* Actually this property is set by OpenJDK, but we need it in
+          nativevm_preinit(). */
 
+       properties_add("sun.boot.library.path", boot_library_path);
 
-/* properties_postinit *********************************************************
+# else
 
-   Re-set some properties that may have changed during command-line
-   parsing.
+#  error unknown classpath configuration
 
-*******************************************************************************/
+# endif
 
-bool properties_postinit(void)
-{
-#if defined(ENABLE_JAVASE)
-       properties_add("java.class.path", _Jv_classpath);
-       properties_add("java.boot.class.path", _Jv_bootclasspath);
-       properties_add("sun.boot.class.path", _Jv_bootclasspath);
-#endif
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+    properties_add("microedition.configuration", "CLDC-1.1");
+    properties_add("microedition.platform", "generic");
+    properties_add("microedition.encoding", "ISO8859_1");
+    properties_add("microedition.profiles", "");
+
+#else
 
-       /* everything's ok */
+# error unknown Java configuration
 
-       return true;
+#endif
 }
 
 
@@ -322,7 +558,7 @@ bool properties_postinit(void)
 
 void properties_add(char *key, char *value)
 {
-       list_properties_entry *pe;
+       list_properties_entry_t *pe;
 
        /* search for the entry */
 
@@ -339,7 +575,7 @@ void properties_add(char *key, char *value)
 
        /* entry was not found, insert a new one */
 
-       pe = NEW(list_properties_entry);
+       pe = NEW(list_properties_entry_t);
 
        pe->key   = key;
        pe->value = value;
@@ -356,7 +592,7 @@ void properties_add(char *key, char *value)
 
 char *properties_get(char *key)
 {
-       list_properties_entry *pe;
+       list_properties_entry_t *pe;
 
        for (pe = list_first_unsynced(list_properties); pe != NULL;
                 pe = list_next_unsynced(list_properties, pe)) {
@@ -374,11 +610,11 @@ char *properties_get(char *key)
 
 *******************************************************************************/
 
-void properties_system_add(java_objectheader *p, char *key, char *value)
+void properties_system_add(java_handle_t *p, char *key, char *value)
 {
-       methodinfo       *m;
-       java_lang_String *k;
-       java_lang_String *v;
+       methodinfo    *m;
+       java_handle_t *k;
+       java_handle_t *v;
 
        /* search for method to add properties */
 
@@ -405,19 +641,22 @@ void properties_system_add(java_objectheader *p, char *key, char *value)
    Adds all properties from the properties list to the Java system
    properties.
 
+   ARGUMENTS:
+       p.... is actually a java_util_Properties structure
+
 *******************************************************************************/
 
 #if defined(ENABLE_JAVASE)
-void properties_system_add_all(java_util_Properties *p)
+void properties_system_add_all(java_handle_t *p)
 {
-       list_properties_entry *pe;
-       methodinfo            *m;
-       java_lang_String      *key;
-       java_lang_String      *value;
+       list_properties_entry_t *pe;
+       methodinfo              *m;
+       java_handle_t           *key;
+       java_handle_t           *value;
 
        /* search for method to add properties */
 
-       m = class_resolveclassmethod(p->header.vftbl->class,
+       m = class_resolveclassmethod(p->vftbl->class,
                                                                 utf_put,
                                                                 utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
                                                                 NULL,
@@ -435,7 +674,7 @@ void properties_system_add_all(java_util_Properties *p)
                key   = javastring_new_from_utf_string(pe->key);
                value = javastring_new_from_utf_string(pe->value);
 
-               (void) vm_call_method(m, (java_objectheader *) p, key, value);
+               (void) vm_call_method(m, (java_handle_t *) p, key, value);
        }
 }
 #endif /* defined(ENABLE_JAVASE) */