This commit introduces C++ wrapper classes for Java heap objects.
[cacao.git] / src / vm / properties.c
1 /* src/vm/properties.c - handling commandline properties
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
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.
12
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.
17
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
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include <unistd.h>
34 #include <sys/utsname.h>
35
36 #include "mm/memory.h"
37
38 #include "native/jni.h"
39 #include "native/llni.h"
40
41 #include "toolbox/list.h"
42 #include "toolbox/util.h"
43
44 #include "vm/global.h"
45 #include "vm/properties.h"
46 #include "vm/string.hpp"
47 #include "vm/vm.hpp"
48
49 #include "vm/jit/asmpart.h"
50
51 #include "vmcore/class.h"
52 #include "vmcore/method.h"
53 #include "vmcore/options.h"
54 #include "vmcore/os.hpp"
55
56
57 /* internal property structure ************************************************/
58
59 typedef struct list_properties_entry_t list_properties_entry_t;
60
61 struct list_properties_entry_t {
62         const char* key;
63         const char* value;
64         listnode_t  linkage;
65 };
66
67
68 /* global variables ***********************************************************/
69
70 static list_t *list_properties = NULL;
71
72
73 /* properties_init *************************************************************
74
75    Initialize the properties list and fill the list with default
76    values.
77
78 *******************************************************************************/
79
80 void properties_init(void)
81 {
82         TRACESUBSYSTEMINITIALIZATION("properties_init");
83
84         list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
85 }
86
87
88 /* properties_set **************************************************************
89
90    Fill the properties list with default values.
91
92 *******************************************************************************/
93
94 void properties_set(void)
95 {
96         int             len;
97         char           *p;
98
99         char           *java_home;
100         char           *boot_class_path;
101
102 #if defined(ENABLE_JAVASE)
103         char           *class_path;
104         char           *boot_library_path;
105         char           *extdirs;
106         char           *endorseddirs;
107
108 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
109         char           *cwd;
110         char           *env_user;
111         char           *env_home;
112         char           *env_lang;
113         char           *lang;
114         char           *country;
115         struct utsname *utsnamebuf;
116
117         char           *java_library_path;
118 # endif
119 #endif
120
121 #if defined(ENABLE_JRE_LAYOUT)
122         /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
123
124         p = MNEW(char, 4096);
125
126         if (readlink("/proc/self/exe", p, 4095) == -1)
127                 vm_abort("properties_set: readlink failed: %s\n", strerror(errno));
128
129         /* We have a path like:
130
131            /path/to/executable/bin/java
132
133            or
134            
135            /path/to/executeable/jre/bin/java
136
137            Now let's strip two levels. */
138
139         p = os_dirname(p);
140         p = os_dirname(p);
141
142 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
143
144         /* Set java.home. */
145
146         java_home = strdup(p);
147
148         /* Set the path to Java core native libraries. */
149
150         len = strlen(java_home) + strlen("/lib/classpath") + strlen("0");
151
152         boot_library_path = MNEW(char, len);
153
154         strcpy(boot_library_path, java_home);
155         strcat(boot_library_path, "/lib/classpath");
156
157 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
158
159         /* Find correct java.home.  We check if there is a JRE
160            co-located. */
161
162         /* NOTE: We use the server VM here as it should be available on
163            all architectures. */
164
165         len =
166                 strlen(p) +
167                 strlen("/jre/lib/"JAVA_ARCH"/server/libjvm.so") +
168                 strlen("0");
169
170         java_home = MNEW(char, len);
171
172         strcpy(java_home, p);
173         strcat(java_home, "/jre/lib/"JAVA_ARCH"/server/libjvm.so");
174
175         /* Check if that libjvm.so exists. */
176
177         if (os_access(java_home, F_OK) == 0) {
178                 /* Yes, we add /jre to java.home. */
179
180                 strcpy(java_home, p);
181                 strcat(java_home, "/jre");
182         }
183         else {
184                 /* No, java.home is parent directory. */
185
186                 strcpy(java_home, p);
187         }
188
189         /* Set the path to Java core native libraries. */
190
191         len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
192
193         boot_library_path = MNEW(char, len);
194
195         strcpy(boot_library_path, java_home);
196         strcat(boot_library_path, "/lib/"JAVA_ARCH);
197
198 # else
199 #  error unknown classpath configuration
200 # endif
201
202         /* Free path. */
203
204         MFREE(p, char, len);
205
206 #else
207         java_home         = CACAO_PREFIX;
208
209 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
210
211         boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR"/classpath";
212
213 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
214
215         boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR;
216
217 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
218
219         /* No boot_library_path required. */
220
221 # else
222 #  error unknown classpath configuration
223 # endif
224 #endif
225
226         properties_add("java.home", java_home);
227
228         /* Set the bootclasspath. */
229
230         p = getenv("BOOTCLASSPATH");
231
232         if (p != NULL) {
233                 boot_class_path = MNEW(char, strlen(p) + strlen("0"));
234                 strcpy(boot_class_path, p);
235         }
236         else {
237 #if defined(ENABLE_JRE_LAYOUT)
238 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
239
240                 len =
241                         strlen(java_home) + strlen("/share/cacao/vm.zip:") +
242                         strlen(java_home) + strlen("/share/classpath/glibj.zip") +
243                         strlen("0");
244
245                 boot_class_path = MNEW(char, len);
246
247                 strcpy(boot_class_path, java_home);
248                 strcat(boot_class_path, "/share/cacao/vm.zip");
249                 strcat(boot_class_path, ":");
250                 strcat(boot_class_path, java_home);
251                 strcat(boot_class_path, "/share/classpath/glibj.zip");
252
253 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
254
255                 /* This is the bootclasspath taken from HotSpot (see
256                    hotspot/src/share/vm/runtime/os.cpp
257                    (os::set_boot_path)). */
258
259                 len =
260                         strlen(java_home) + strlen("/lib/resources.jar:") +
261                         strlen(java_home) + strlen("/lib/rt.jar:") +
262                         strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
263                         strlen(java_home) + strlen("/lib/jsse.jar:") +
264                         strlen(java_home) + strlen("/lib/jce.jar:") +
265                         strlen(java_home) + strlen("/lib/charsets.jar:") +
266                         strlen(java_home) + strlen("/classes") +
267                         strlen("0");
268
269                 boot_class_path = MNEW(char, len);
270
271                 strcpy(boot_class_path, java_home);
272                 strcat(boot_class_path, "/lib/resources.jar:");
273                 strcat(boot_class_path, java_home);
274                 strcat(boot_class_path, "/lib/rt.jar:");
275                 strcat(boot_class_path, java_home);
276                 strcat(boot_class_path, "/lib/sunrsasign.jar:");
277                 strcat(boot_class_path, java_home);
278                 strcat(boot_class_path, "/lib/jsse.jar:");
279                 strcat(boot_class_path, java_home);
280                 strcat(boot_class_path, "/lib/jce.jar:");
281                 strcat(boot_class_path, java_home);
282                 strcat(boot_class_path, "/lib/charsets.jar:");
283                 strcat(boot_class_path, java_home);
284                 strcat(boot_class_path, "/classes");
285
286 # else
287 #  error unknown classpath configuration
288 # endif
289 #else
290 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
291
292                 len =
293                         strlen(CACAO_VM_ZIP) +
294                         strlen(":") +
295                         strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
296                         strlen("0");
297
298                 boot_class_path = MNEW(char, len);
299
300                 strcpy(boot_class_path, CACAO_VM_ZIP);
301                 strcat(boot_class_path, ":");
302                 strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
303
304 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
305
306                 /* This is the bootclasspath taken from HotSpot (see
307                    hotspot/src/share/vm/runtime/os.cpp
308                    (os::set_boot_path)). */
309
310                 len =
311                         strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:") +
312                         strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:") +
313                         strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:") +
314                         strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:") +
315                         strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:") +
316                         strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:") +
317                         strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/classes") +
318                         strlen("0");
319
320                 boot_class_path = MNEW(char, len);
321
322                 strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:");
323                 strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:");
324                 strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:");
325                 strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:");
326                 strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:");
327                 strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:");
328                 strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/classes");
329
330 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
331
332                 len =
333                         strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
334                         strlen("0");
335
336                 boot_class_path = MNEW(char, len);
337
338                 strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
339
340 # else
341 #  error unknown classpath configuration
342 # endif
343 #endif
344         }
345
346         properties_add("sun.boot.class.path", boot_class_path);
347         properties_add("java.boot.class.path", boot_class_path);
348
349 #if defined(ENABLE_JAVASE)
350
351         /* Set the classpath. */
352
353         p = getenv("CLASSPATH");
354
355         if (p != NULL) {
356                 class_path = MNEW(char, strlen(p) + strlen("0"));
357                 strcpy(class_path, p);
358         }
359         else {
360                 class_path = MNEW(char, strlen(".") + strlen("0"));
361                 strcpy(class_path, ".");
362         }
363
364         properties_add("java.class.path", class_path);
365
366         /* Add java.vm properties. */
367
368         properties_add("java.vm.specification.version", "1.0");
369         properties_add("java.vm.specification.vendor", "Sun Microsystems Inc.");
370         properties_add("java.vm.specification.name", "Java Virtual Machine Specification");
371         properties_add("java.vm.version", VERSION);
372         properties_add("java.vm.vendor", "CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
373         properties_add("java.vm.name", "CACAO");
374
375 # if defined(ENABLE_INTRP)
376         if (opt_intrp) {
377                 /* XXX We don't support java.lang.Compiler */
378 /*              properties_add("java.compiler", "cacao.intrp"); */
379                 properties_add("java.vm.info", "interpreted mode");
380         }
381         else
382 # endif
383         {
384                 /* XXX We don't support java.lang.Compiler */
385 /*              properties_add("java.compiler", "cacao.jit"); */
386                 properties_add("java.vm.info", "JIT mode");
387         }
388
389 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
390
391         /* Get properties from system. */
392
393         cwd      = _Jv_getcwd();
394
395         env_user = getenv("USER");
396         env_home = getenv("HOME");
397         env_lang = getenv("LANG");
398
399         utsnamebuf = NEW(struct utsname);
400
401         uname(utsnamebuf);
402
403         properties_add("java.runtime.version", VERSION);
404         properties_add("java.runtime.name", "CACAO");
405
406         properties_add("java.specification.version", "1.5");
407         properties_add("java.specification.vendor", "Sun Microsystems Inc.");
408         properties_add("java.specification.name", "Java Platform API Specification");
409
410         properties_add("java.version", JAVA_VERSION);
411         properties_add("java.vendor", "GNU Classpath");
412         properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
413
414         properties_add("java.class.version", CLASS_VERSION);
415
416         properties_add("gnu.classpath.boot.library.path", boot_library_path);
417
418         /* Get and set java.library.path. */
419
420         java_library_path = getenv("LD_LIBRARY_PATH");
421
422         if (java_library_path == NULL)
423                 java_library_path = "";
424
425         properties_add("java.library.path", java_library_path);
426
427         properties_add("java.io.tmpdir", "/tmp");
428
429 #  if defined(ENABLE_INTRP)
430         if (opt_intrp) {
431                 properties_add("gnu.java.compiler.name", "cacao.intrp");
432         }
433         else
434 #  endif
435         {
436                 properties_add("gnu.java.compiler.name", "cacao.jit");
437         }
438
439         /* Set the java.ext.dirs property. */
440
441         len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
442
443         extdirs = MNEW(char, len);
444
445         sprintf(extdirs, "%s/jre/lib/ext", java_home);
446
447         properties_add("java.ext.dirs", extdirs);
448
449         /* Set the java.ext.endorsed property. */
450
451         len = strlen(java_home) + strlen("/jre/lib/endorsed") + strlen("0");
452
453         endorseddirs = MNEW(char, len);
454
455         sprintf(endorseddirs, "%s/jre/lib/endorsed", java_home);
456
457         properties_add("java.endorsed.dirs", endorseddirs);
458
459 #  if defined(DISABLE_GC)
460         /* When we disable the GC, we mmap the whole heap to a specific
461            address, so we can compare call traces. For this reason we have
462            to add the same properties on different machines, otherwise
463            more memory may be allocated (e.g. strlen("i386")
464            vs. strlen("alpha"). */
465
466         properties_add("os.arch", "unknown");
467         properties_add("os.name", "unknown");
468         properties_add("os.version", "unknown");
469 #  else
470         properties_add("os.arch", JAVA_ARCH);
471         properties_add("os.name", utsnamebuf->sysname);
472         properties_add("os.version", utsnamebuf->release);
473 #  endif
474
475 #  if WORDS_BIGENDIAN == 1
476         properties_add("gnu.cpu.endian", "big");
477 #  else
478         properties_add("gnu.cpu.endian", "little");
479 #  endif
480
481         properties_add("file.separator", "/");
482         properties_add("path.separator", ":");
483         properties_add("line.separator", "\n");
484
485         properties_add("user.name", env_user ? env_user : "null");
486         properties_add("user.home", env_home ? env_home : "null");
487         properties_add("user.dir", cwd ? cwd : "null");
488
489         /* get locale */
490
491         if (env_lang != NULL) {
492                 /* get the local stuff from the environment */
493
494                 if (strlen(env_lang) <= 2) {
495                         properties_add("user.language", env_lang);
496                 }
497                 else {
498                         if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
499                                 lang = MNEW(char, 3);
500                                 strncpy(lang, (char *) &env_lang[0], 2);
501                                 lang[2] = '\0';
502
503                                 country = MNEW(char, 3);
504                                 strncpy(country, (char *) &env_lang[3], 2);
505                                 country[2] = '\0';
506
507                                 properties_add("user.language", lang);
508                                 properties_add("user.country", country);
509                         }
510                 }
511         }
512         else {
513                 /* if no default locale was specified, use `en_US' */
514
515                 properties_add("user.language", "en");
516                 properties_add("user.country", "US");
517         }
518
519 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
520
521         /* Actually this property is set by OpenJDK, but we need it in
522            nativevm_preinit(). */
523
524         properties_add("sun.boot.library.path", boot_library_path);
525
526         /* Set the java.ext.dirs property. */
527
528         len =
529                 strlen(java_home) + strlen("/lib/ext") +
530                 strlen(":") +
531                 strlen("/usr/java/packages/lib/ext") +
532                 strlen("0");
533
534         extdirs = MNEW(char, len);
535
536         sprintf(extdirs, "%s/lib/ext:/usr/java/packages/lib/ext", java_home);
537
538         properties_add("java.ext.dirs", extdirs);
539
540         /* Set the java.ext.endorsed property. */
541
542         len = strlen(java_home) + strlen("/lib/endorsed") + strlen("0");
543
544         endorseddirs = MNEW(char, len);
545
546         sprintf(endorseddirs, "%s/lib/endorsed", java_home);
547
548         properties_add("java.endorsed.dirs", endorseddirs);
549
550 # else
551
552 #  error unknown classpath configuration
553
554 # endif
555
556 #elif defined(ENABLE_JAVAME_CLDC1_1)
557
558     properties_add("microedition.configuration", "CLDC-1.1");
559     properties_add("microedition.platform", "generic");
560     properties_add("microedition.encoding", "ISO8859_1");
561     properties_add("microedition.profiles", "");
562
563 #else
564
565 # error unknown Java configuration
566
567 #endif
568 }
569
570
571 /* properties_add **************************************************************
572
573    Adds a property entry to the internal property list.  If there's
574    already an entry with the same key, replace it.
575
576 *******************************************************************************/
577
578 void properties_add(const char *key, const char *value)
579 {
580         list_properties_entry_t *pe;
581
582         /* search for the entry */
583
584         for (pe = list_first(list_properties); pe != NULL;
585                  pe = list_next(list_properties, pe)) {
586                 if (strcmp(pe->key, key) == 0) {
587                         /* entry was found, replace the value */
588
589 #if !defined(NDEBUG)
590                         if (opt_DebugProperties) {
591                                 printf("[properties_add: key=%s, old value=%s, new value=%s]\n",
592                                            key, pe->value, value);
593                         }
594 #endif
595
596                         pe->value = value;
597
598                         return;
599                 }
600         }
601
602         /* entry was not found, insert a new one */
603
604 #if !defined(NDEBUG)
605         if (opt_DebugProperties) {
606                 printf("[properties_add: key=%s, value=%s]\n", key, value);
607         }
608 #endif
609
610         pe = NEW(list_properties_entry_t);
611
612         pe->key   = key;
613         pe->value = value;
614
615         list_add_last(list_properties, pe);
616 }
617
618
619 /* properties_get **************************************************************
620
621    Get a property entry from the internal property list.
622
623 *******************************************************************************/
624
625 const char *properties_get(const char *key)
626 {
627         list_properties_entry_t *pe;
628
629         for (pe = list_first(list_properties); pe != NULL;
630                  pe = list_next(list_properties, pe)) {
631                 if (strcmp(pe->key, key) == 0)
632                         return pe->value;
633         }
634
635         return NULL;
636 }
637
638
639 /* properties_system_add *******************************************************
640
641    Adds a given property to the Java system properties.
642
643 *******************************************************************************/
644
645 void properties_system_add(java_handle_t *p, const char *key, const char *value)
646 {
647         classinfo     *c;
648         methodinfo    *m;
649         java_handle_t *k;
650         java_handle_t *v;
651
652         /* search for method to add properties */
653
654         LLNI_class_get(p, c);
655
656         m = class_resolveclassmethod(c,
657                                                                  utf_put,
658                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
659                                                                  NULL,
660                                                                  true);
661
662         if (m == NULL)
663                 return;
664
665         /* add to the Java system properties */
666
667         k = javastring_new_from_utf_string(key);
668         v = javastring_new_from_utf_string(value);
669
670         (void) vm_call_method(m, p, k, v);
671 }
672
673
674 /* properties_system_add_all ***************************************************
675
676    Adds all properties from the properties list to the Java system
677    properties.
678
679    ARGUMENTS:
680        p.... is actually a java_util_Properties structure
681
682 *******************************************************************************/
683
684 #if defined(ENABLE_JAVASE)
685 void properties_system_add_all(java_handle_t *p)
686 {
687         list_properties_entry_t *pe;
688         classinfo               *c;
689         methodinfo              *m;
690         java_handle_t           *key;
691         java_handle_t           *value;
692
693         /* search for method to add properties */
694
695         LLNI_class_get(p, c);
696
697         m = class_resolveclassmethod(c,
698                                                                  utf_put,
699                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
700                                                                  NULL,
701                                                                  true);
702
703         if (m == NULL)
704                 return;
705
706         /* process all properties stored in the internal table */
707
708         for (pe = list_first(list_properties); pe != NULL;
709                  pe = list_next(list_properties, pe)) {
710                 /* add to the Java system properties */
711
712                 key   = javastring_new_from_utf_string(pe->key);
713                 value = javastring_new_from_utf_string(pe->value);
714
715                 (void) vm_call_method(m, (java_handle_t *) p, key, value);
716         }
717 }
718 #endif /* defined(ENABLE_JAVASE) */
719
720
721 /* properties_dump *************************************************************
722
723    Dump all property entries.
724
725 *******************************************************************************/
726
727 void properties_dump(void)
728 {
729         list_t                  *l;
730         list_properties_entry_t *pe;
731
732         /* For convenience. */
733
734         l = list_properties;
735
736         for (pe = list_first(l); pe != NULL; pe = list_next(l, pe)) {
737                 log_println("[properties_dump: key=%s, value=%s]", pe->key, pe->value);
738         }
739 }
740
741
742 /*
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  * ---------------------------------------------------------------------
747  * Local variables:
748  * mode: c
749  * indent-tabs-mode: t
750  * c-basic-offset: 4
751  * tab-width: 4
752  * End:
753  */