1 /* src/vm/properties.c - handling commandline properties
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 #include <sys/utsname.h>
37 #include "mm/memory.h"
39 #include "native/jni.h"
40 #include "native/llni.h"
42 #include "vm/global.h" /* required by java_lang_String.h */
43 #include "native/include/java_lang_String.h"
45 #include "toolbox/list.h"
46 #include "toolbox/util.h"
48 #include "vm/properties.h"
49 #include "vm/stringlocal.h"
52 #include "vm/jit/asmpart.h"
54 #include "vmcore/class.h"
55 #include "vmcore/method.h"
56 #include "vmcore/options.h"
57 #include "vmcore/system.h"
60 /* internal property structure ************************************************/
62 typedef struct list_properties_entry_t list_properties_entry_t;
64 struct list_properties_entry_t {
71 /* global variables ***********************************************************/
73 static list_t *list_properties = NULL;
76 /* properties_init *************************************************************
78 Initialize the properties list and fill the list with default
81 *******************************************************************************/
83 void properties_init(void)
85 list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
89 /* properties_set **************************************************************
91 Fill the properties list with default values.
93 *******************************************************************************/
95 void properties_set(void)
101 char *boot_class_path;
103 #if defined(ENABLE_JAVASE)
105 char *boot_library_path;
109 # if defined(WITH_CLASSPATH_GNU)
116 struct utsname *utsnamebuf;
118 char *java_library_path;
122 #if defined(WITH_JRE_LAYOUT)
123 /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
125 p = MNEW(char, 4096);
127 if (readlink("/proc/self/exe", p, 4095) == -1)
128 vm_abort("properties_set: readlink failed: %s\n", strerror(errno));
130 /* We have a path like:
132 /path/to/executable/bin/java
136 /path/to/executeable/jre/bin/java
138 Now let's strip two levels. */
140 p = system_dirname(p);
141 p = system_dirname(p);
143 # if defined(WITH_CLASSPATH_GNU)
147 java_home = strdup(p);
149 /* Set the path to Java core native libraries. */
151 len = strlen(java_home) + strlen("/lib/classpath") + strlen("0");
153 boot_library_path = MNEW(char, len);
155 strcpy(boot_library_path, java_home);
156 strcat(boot_library_path, "/lib/classpath");
158 # elif defined(WITH_CLASSPATH_SUN)
160 /* Find correct java.home. We check if there is a JRE
163 /* NOTE: We use the server VM here as it should be available on
164 all architectures. */
168 strlen("/jre/lib/"JAVA_ARCH"/server/libjvm.so") +
171 java_home = MNEW(char, len);
173 strcpy(java_home, p);
174 strcat(java_home, "/jre/lib/"JAVA_ARCH"/server/libjvm.so");
176 /* Check if that libjvm.so exists. */
178 if (access(java_home, F_OK) == 0) {
179 /* Yes, we add /jre to java.home. */
181 strcpy(java_home, p);
182 strcat(java_home, "/jre");
185 /* No, java.home is parent directory. */
187 strcpy(java_home, p);
190 /* Set the path to Java core native libraries. */
192 len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
194 boot_library_path = MNEW(char, len);
196 strcpy(boot_library_path, java_home);
197 strcat(boot_library_path, "/lib/"JAVA_ARCH);
200 # error unknown classpath configuration
208 java_home = CACAO_PREFIX;
210 # if defined(WITH_CLASSPATH_GNU)
212 boot_library_path = CLASSPATH_LIBDIR"/classpath";
214 # elif defined(WITH_CLASSPATH_SUN)
216 boot_library_path = CLASSPATH_LIBDIR;
218 # elif defined(WITH_CLASSPATH_CLDC1_1)
220 /* No boot_library_path required. */
223 # error unknown classpath configuration
227 properties_add("java.home", java_home);
229 /* Set the bootclasspath. */
231 p = getenv("BOOTCLASSPATH");
234 boot_class_path = MNEW(char, strlen(p) + strlen("0"));
235 strcpy(boot_class_path, p);
238 #if defined(WITH_JRE_LAYOUT)
239 # if defined(WITH_CLASSPATH_GNU)
242 strlen(java_home) + strlen("/share/cacao/vm.zip:") +
243 strlen(java_home) + strlen("/share/classpath/glibj.zip") +
246 boot_class_path = MNEW(char, len);
248 strcpy(boot_class_path, java_home);
249 strcat(boot_class_path, "/share/cacao/vm.zip");
250 strcat(boot_class_path, ":");
251 strcat(boot_class_path, java_home);
252 strcat(boot_class_path, "/share/classpath/glibj.zip");
254 # elif defined(WITH_CLASSPATH_SUN)
256 /* This is the bootclasspath taken from HotSpot (see
257 hotspot/src/share/vm/runtime/os.cpp
258 (os::set_boot_path)). */
261 strlen(java_home) + strlen("/lib/resources.jar:") +
262 strlen(java_home) + strlen("/lib/rt.jar:") +
263 strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
264 strlen(java_home) + strlen("/lib/jsse.jar:") +
265 strlen(java_home) + strlen("/lib/jce.jar:") +
266 strlen(java_home) + strlen("/lib/charsets.jar:") +
267 strlen(java_home) + strlen("/classes") +
270 boot_class_path = MNEW(char, len);
272 strcpy(boot_class_path, java_home);
273 strcat(boot_class_path, "/lib/resources.jar:");
274 strcat(boot_class_path, java_home);
275 strcat(boot_class_path, "/lib/rt.jar:");
276 strcat(boot_class_path, java_home);
277 strcat(boot_class_path, "/lib/sunrsasign.jar:");
278 strcat(boot_class_path, java_home);
279 strcat(boot_class_path, "/lib/jsse.jar:");
280 strcat(boot_class_path, java_home);
281 strcat(boot_class_path, "/lib/jce.jar:");
282 strcat(boot_class_path, java_home);
283 strcat(boot_class_path, "/lib/charsets.jar:");
284 strcat(boot_class_path, java_home);
285 strcat(boot_class_path, "/classes");
288 # error unknown classpath configuration
291 # if defined(WITH_CLASSPATH_GNU)
294 strlen(CACAO_VM_ZIP) +
296 strlen(CLASSPATH_CLASSES) +
299 boot_class_path = MNEW(char, len);
301 strcpy(boot_class_path, CACAO_VM_ZIP);
302 strcat(boot_class_path, ":");
303 strcat(boot_class_path, CLASSPATH_CLASSES);
305 # elif defined(WITH_CLASSPATH_SUN)
307 /* This is the bootclasspath taken from HotSpot (see
308 hotspot/src/share/vm/runtime/os.cpp
309 (os::set_boot_path)). */
312 strlen(CLASSPATH_PREFIX"/lib/resources.jar:") +
313 strlen(CLASSPATH_PREFIX"/lib/rt.jar:") +
314 strlen(CLASSPATH_PREFIX"/lib/sunrsasign.jar:") +
315 strlen(CLASSPATH_PREFIX"/lib/jsse.jar:") +
316 strlen(CLASSPATH_PREFIX"/lib/jce.jar:") +
317 strlen(CLASSPATH_PREFIX"/lib/charsets.jar:") +
318 strlen(CLASSPATH_PREFIX"/classes") +
321 boot_class_path = MNEW(char, len);
323 strcpy(boot_class_path, CLASSPATH_PREFIX"/lib/resources.jar:");
324 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/rt.jar:");
325 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/sunrsasign.jar:");
326 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jsse.jar:");
327 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jce.jar:");
328 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/charsets.jar:");
329 strcat(boot_class_path, CLASSPATH_PREFIX"/classes");
331 # elif defined(WITH_CLASSPATH_CLDC1_1)
334 strlen(CLASSPATH_CLASSES) +
337 boot_class_path = MNEW(char, len);
339 strcpy(boot_class_path, CLASSPATH_CLASSES);
342 # error unknown classpath configuration
347 properties_add("sun.boot.class.path", boot_class_path);
348 properties_add("java.boot.class.path", boot_class_path);
350 #if defined(ENABLE_JAVASE)
352 /* Set the classpath. */
354 p = getenv("CLASSPATH");
357 class_path = MNEW(char, strlen(p) + strlen("0"));
358 strcpy(class_path, p);
361 class_path = MNEW(char, strlen(".") + strlen("0"));
362 strcpy(class_path, ".");
365 properties_add("java.class.path", class_path);
367 /* Add java.vm properties. */
369 properties_add("java.vm.specification.version", "1.0");
370 properties_add("java.vm.specification.vendor", "Sun Microsystems Inc.");
371 properties_add("java.vm.specification.name", "Java Virtual Machine Specification");
372 properties_add("java.vm.version", VERSION);
373 properties_add("java.vm.vendor", "CACAO Team");
374 properties_add("java.vm.name", "CACAO");
376 # if defined(ENABLE_INTRP)
378 /* XXX We don't support java.lang.Compiler */
379 /* properties_add("java.compiler", "cacao.intrp"); */
380 properties_add("java.vm.info", "interpreted mode");
385 /* XXX We don't support java.lang.Compiler */
386 /* properties_add("java.compiler", "cacao.jit"); */
387 properties_add("java.vm.info", "JIT mode");
390 # if defined(WITH_CLASSPATH_GNU)
392 /* Get properties from system. */
396 env_user = getenv("USER");
397 env_home = getenv("HOME");
398 env_lang = getenv("LANG");
400 utsnamebuf = NEW(struct utsname);
404 properties_add("java.runtime.version", VERSION);
405 properties_add("java.runtime.name", "CACAO");
407 properties_add("java.specification.version", "1.5");
408 properties_add("java.specification.vendor", "Sun Microsystems Inc.");
409 properties_add("java.specification.name", "Java Platform API Specification");
411 properties_add("java.version", JAVA_VERSION);
412 properties_add("java.vendor", "GNU Classpath");
413 properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
415 properties_add("java.class.version", CLASS_VERSION);
417 properties_add("gnu.classpath.boot.library.path", boot_library_path);
419 /* Get and set java.library.path. */
421 java_library_path = getenv("LD_LIBRARY_PATH");
423 if (java_library_path == NULL)
424 java_library_path = "";
426 properties_add("java.library.path", java_library_path);
428 properties_add("java.io.tmpdir", "/tmp");
430 # if defined(ENABLE_INTRP)
432 properties_add("gnu.java.compiler.name", "cacao.intrp");
437 properties_add("gnu.java.compiler.name", "cacao.jit");
440 /* Set the java.ext.dirs property. */
442 len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
444 extdirs = MNEW(char, len);
446 sprintf(extdirs, "%s/jre/lib/ext", java_home);
448 properties_add("java.ext.dirs", extdirs);
450 /* Set the java.ext.endorsed property. */
452 len = strlen(java_home) + strlen("/jre/lib/endorsed") + strlen("0");
454 endorseddirs = MNEW(char, len);
456 sprintf(endorseddirs, "%s/jre/lib/endorsed", java_home);
458 properties_add("java.endorsed.dirs", endorseddirs);
460 # if defined(DISABLE_GC)
461 /* When we disable the GC, we mmap the whole heap to a specific
462 address, so we can compare call traces. For this reason we have
463 to add the same properties on different machines, otherwise
464 more memory may be allocated (e.g. strlen("i386")
465 vs. strlen("alpha"). */
467 properties_add("os.arch", "unknown");
468 properties_add("os.name", "unknown");
469 properties_add("os.version", "unknown");
471 properties_add("os.arch", JAVA_ARCH);
472 properties_add("os.name", utsnamebuf->sysname);
473 properties_add("os.version", utsnamebuf->release);
476 # if WORDS_BIGENDIAN == 1
477 properties_add("gnu.cpu.endian", "big");
479 properties_add("gnu.cpu.endian", "little");
482 properties_add("file.separator", "/");
483 properties_add("path.separator", ":");
484 properties_add("line.separator", "\n");
486 properties_add("user.name", env_user ? env_user : "null");
487 properties_add("user.home", env_home ? env_home : "null");
488 properties_add("user.dir", cwd ? cwd : "null");
492 if (env_lang != NULL) {
493 /* get the local stuff from the environment */
495 if (strlen(env_lang) <= 2) {
496 properties_add("user.language", env_lang);
499 if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
500 lang = MNEW(char, 3);
501 strncpy(lang, (char *) &env_lang[0], 2);
504 country = MNEW(char, 3);
505 strncpy(country, (char *) &env_lang[3], 2);
508 properties_add("user.language", lang);
509 properties_add("user.country", country);
514 /* if no default locale was specified, use `en_US' */
516 properties_add("user.language", "en");
517 properties_add("user.country", "US");
520 # elif defined(WITH_CLASSPATH_SUN)
522 /* Actually this property is set by OpenJDK, but we need it in
523 nativevm_preinit(). */
525 properties_add("sun.boot.library.path", boot_library_path);
527 /* Set the java.ext.dirs property. */
530 strlen(java_home) + strlen("/lib/ext") +
532 strlen("/usr/java/packages/lib/ext") +
535 extdirs = MNEW(char, len);
537 sprintf(extdirs, "%s/lib/ext:/usr/java/packages/lib/ext", java_home);
539 properties_add("java.ext.dirs", extdirs);
541 /* Set the java.ext.endorsed property. */
543 len = strlen(java_home) + strlen("/lib/endorsed") + strlen("0");
545 endorseddirs = MNEW(char, len);
547 sprintf(endorseddirs, "%s/lib/endorsed", java_home);
549 properties_add("java.endorsed.dirs", endorseddirs);
553 # error unknown classpath configuration
557 #elif defined(ENABLE_JAVAME_CLDC1_1)
559 properties_add("microedition.configuration", "CLDC-1.1");
560 properties_add("microedition.platform", "generic");
561 properties_add("microedition.encoding", "ISO8859_1");
562 properties_add("microedition.profiles", "");
566 # error unknown Java configuration
572 /* properties_add **************************************************************
574 Adds a property entry to the internal property list. If there's
575 already an entry with the same key, replace it.
577 *******************************************************************************/
579 void properties_add(char *key, char *value)
581 list_properties_entry_t *pe;
583 /* search for the entry */
585 for (pe = list_first_unsynced(list_properties); pe != NULL;
586 pe = list_next_unsynced(list_properties, pe)) {
587 if (strcmp(pe->key, key) == 0) {
588 /* entry was found, replace the value */
591 if (opt_DebugProperties) {
592 printf("[properties_add: key=%s, old value=%s, new value=%s]\n",
593 key, pe->value, value);
603 /* entry was not found, insert a new one */
606 if (opt_DebugProperties) {
607 printf("[properties_add: key=%s, value=%s]\n", key, value);
611 pe = NEW(list_properties_entry_t);
616 list_add_last_unsynced(list_properties, pe);
620 /* properties_get **************************************************************
622 Get a property entry from the internal property list.
624 *******************************************************************************/
626 char *properties_get(char *key)
628 list_properties_entry_t *pe;
630 for (pe = list_first_unsynced(list_properties); pe != NULL;
631 pe = list_next_unsynced(list_properties, pe)) {
632 if (strcmp(pe->key, key) == 0)
640 /* properties_system_add *******************************************************
642 Adds a given property to the Java system properties.
644 *******************************************************************************/
646 void properties_system_add(java_handle_t *p, char *key, char *value)
653 /* search for method to add properties */
655 LLNI_class_get(p, c);
657 m = class_resolveclassmethod(c,
659 utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
666 /* add to the Java system properties */
668 k = javastring_new_from_utf_string(key);
669 v = javastring_new_from_utf_string(value);
671 (void) vm_call_method(m, p, k, v);
675 /* properties_system_add_all ***************************************************
677 Adds all properties from the properties list to the Java system
681 p.... is actually a java_util_Properties structure
683 *******************************************************************************/
685 #if defined(ENABLE_JAVASE)
686 void properties_system_add_all(java_handle_t *p)
688 list_properties_entry_t *pe;
692 java_handle_t *value;
694 /* search for method to add properties */
696 LLNI_class_get(p, c);
698 m = class_resolveclassmethod(c,
700 utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
707 /* process all properties stored in the internal table */
709 for (pe = list_first(list_properties); pe != NULL;
710 pe = list_next(list_properties, pe)) {
711 /* add to the Java system properties */
713 key = javastring_new_from_utf_string(pe->key);
714 value = javastring_new_from_utf_string(pe->value);
716 (void) vm_call_method(m, (java_handle_t *) p, key, value);
719 #endif /* defined(ENABLE_JAVASE) */
722 /* properties_dump *************************************************************
724 Dump all property entries.
726 *******************************************************************************/
728 void properties_dump(void)
731 list_properties_entry_t *pe;
735 for (pe = list_first_unsynced(l); pe != NULL;
736 pe = list_next_unsynced(l, pe)) {
737 log_println("[properties_dump: key=%s, value=%s]", pe->key, pe->value);
743 * These are local overrides for various environment variables in Emacs.
744 * Please do not remove this and leave it at the end of the file, where
745 * Emacs will automagically detect them.
746 * ---------------------------------------------------------------------
749 * indent-tabs-mode: t