* src/vm/properties.c (list_properties_entry): Renamed to
[cacao.git] / src / vm / properties.c
1 /* src/vm/properties.c - handling commandline properties
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: properties.c 8399 2007-08-22 18:24:23Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 #include <unistd.h>
36 #include <sys/utsname.h>
37
38 #include "vm/types.h"
39
40 #include "mm/memory.h"
41
42 #include "native/jni.h"
43
44 #include "vm/global.h"                      /* required by java_lang_String.h */
45 #include "native/include/java_lang_String.h"
46
47 #include "toolbox/list.h"
48 #include "toolbox/util.h"
49
50 #include "vm/properties.h"
51 #include "vm/stringlocal.h"
52 #include "vm/vm.h"
53
54 #include "vm/jit/asmpart.h"
55
56 #include "vmcore/method.h"
57 #include "vmcore/options.h"
58
59
60 /* internal property structure ************************************************/
61
62 typedef struct list_properties_entry_t list_properties_entry_t;
63
64 struct list_properties_entry_t {
65         char       *key;
66         char       *value;
67         listnode_t  linkage;
68 };
69
70
71 /* global variables ***********************************************************/
72
73 static list_t *list_properties = NULL;
74
75
76 /* properties_init *************************************************************
77
78    Initialize the properties list and fill the list with default
79    values.
80
81 *******************************************************************************/
82
83 void properties_init(void)
84 {
85         list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
86 }
87
88
89 /* properties_set **************************************************************
90
91    Fill the properties list with default values.
92
93 *******************************************************************************/
94
95 void properties_set(void)
96 {
97 #if defined(ENABLE_JAVASE)
98         int             len;
99         char           *p;
100
101         char           *java_home;
102         char           *boot_library_path;
103         char           *boot_class_path;
104         char           *class_path;
105
106 # if defined(WITH_CLASSPATH_GNU)
107         char           *cwd;
108         char           *env_user;
109         char           *env_home;
110         char           *env_lang;
111         char           *extdirs;
112         char           *lang;
113         char           *country;
114         struct utsname *utsnamebuf;
115
116         char           *java_library_path;
117 # endif
118 #endif
119
120 #if defined(WITH_JRE_LAYOUT)
121         /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
122
123         p = MNEW(char, 4096);
124
125         if (readlink("/proc/self/exe", p, 4095) == -1)
126                 vm_abort("properties_set: readlink failed: %s\n", strerror(errno));
127
128         /* Get the path of the current executable. */
129
130         p = dirname(p);
131
132 # if defined(WITH_CLASSPATH_GNU)
133
134         /* Set java.home. */
135
136         len = strlen(path) + strlen("/..") + strlen("0");
137
138         java_home = MNEW(char, len);
139
140         strcpy(java_home, p);
141         strcat(java_home, "/..");
142
143         /* Set the path to Java core native libraries. */
144
145         len = strlen(cacao_prefix) + strlen("/lib/classpath") + strlen("0");
146
147         boot_library_path = MNEW(char, len);
148
149         strcpy(boot_library_path, java_home);
150         strcat(boot_library_path, "/lib/classpath");
151
152 # elif defined(WITH_CLASSPATH_SUN)
153
154         /* Find correct java.home.  We check if there is a JRE
155            co-located. */
156
157         /* NOTE: We use the server VM here as it should be available on
158            all architectures. */
159
160         len =
161                 strlen(p) +
162                 strlen("/../jre/lib/"JAVA_ARCH"/server/libjvm.so") +
163                 strlen("0");
164
165         java_home = MNEW(char, len);
166
167         strcpy(java_home, p);
168         strcat(java_home, "/../jre/lib/"JAVA_ARCH"/server/libjvm.so");
169
170         /* Check if that libjvm.so exists. */
171
172         if (access(java_home, F_OK) == 0) {
173                 /* Yes, we add /jre to java.home. */
174
175                 strcpy(java_home, p);
176                 strcat(java_home, "/../jre");
177         }
178         else {
179                 /* No, java.home is parent directory. */
180
181                 strcpy(java_home, p);
182                 strcat(java_home, "/..");
183         }
184
185 # else
186 #  error unknown classpath configuration
187 # endif
188
189         /* Free path. */
190
191         MFREE(p, char, len);
192
193 #else
194         java_home         = CACAO_PREFIX;
195
196 # if defined(WITH_CLASSPATH_GNU)
197         boot_library_path = CLASSPATH_LIBDIR"/classpath";
198 # else
199         boot_library_path = CLASSPATH_LIBDIR;
200 # endif
201 #endif
202
203         properties_add("java.home", java_home);
204
205         /* Set the bootclasspath. */
206
207         p = getenv("BOOTCLASSPATH");
208
209         if (p != NULL) {
210                 boot_class_path = MNEW(char, strlen(p) + strlen("0"));
211                 strcpy(boot_class_path, p);
212         }
213         else {
214 #if defined(WITH_JRE_LAYOUT)
215 # if defined(WITH_CLASSPATH_GNU)
216
217                 len =
218                         strlen(java_home) + strlen("/share/cacao/vm.zip:") +
219                         strlen(java_home) + strlen("/share/classpath/glibj.zip") +
220                         strlen("0");
221
222                 boot_class_path = MNEW(char, len);
223
224                 strcpy(boot_class_path, java_home);
225                 strcat(boot_class_path, "/share/cacao/vm.zip");
226                 strcat(boot_class_path, ":");
227                 strcat(boot_class_path, java_home);
228                 strcat(boot_class_path, "/share/classpath/glibj.zip");
229
230 # elif defined(WITH_CLASSPATH_SUN)
231
232                 /* This is the bootclasspath taken from HotSpot (see
233                    hotspot/src/share/vm/runtime/os.cpp
234                    (os::set_boot_path)). */
235
236                 len =
237                         strlen(java_home) + strlen("/lib/resources.jar:") +
238                         strlen(java_home) + strlen("/lib/rt.jar:") +
239                         strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
240                         strlen(java_home) + strlen("/lib/jsse.jar:") +
241                         strlen(java_home) + strlen("/lib/jce.jar:") +
242                         strlen(java_home) + strlen("/lib/charsets.jar:") +
243                         strlen(java_home) + strlen("/classes") +
244                         strlen("0");
245
246                 boot_class_path = MNEW(char, len);
247
248                 strcpy(boot_class_path, java_home);
249                 strcat(boot_class_path, "/lib/resources.jar:");
250                 strcat(boot_class_path, java_home);
251                 strcat(boot_class_path, "/lib/rt.jar:");
252                 strcat(boot_class_path, java_home);
253                 strcat(boot_class_path, "/lib/sunrsasign.jar:");
254                 strcat(boot_class_path, java_home);
255                 strcat(boot_class_path, "/lib/jsse.jar:");
256                 strcat(boot_class_path, java_home);
257                 strcat(boot_class_path, "/lib/jce.jar:");
258                 strcat(boot_class_path, java_home);
259                 strcat(boot_class_path, "/lib/charsets.jar:");
260                 strcat(boot_class_path, java_home);
261                 strcat(boot_class_path, "/classes");
262
263 # else
264 #  error unknown classpath configuration
265 # endif
266 #else
267 # if defined(WITH_CLASSPATH_GNU)
268
269                 len =
270                         strlen(CACAO_VM_ZIP) +
271                         strlen(":") +
272                         strlen(CLASSPATH_CLASSES) +
273                         strlen("0");
274
275                 boot_class_path = MNEW(char, len);
276
277                 strcpy(boot_class_path, CACAO_VM_ZIP);
278                 strcat(boot_class_path, ":");
279                 strcat(boot_class_path, CLASSPATH_CLASSES);
280
281 # elif defined(WITH_CLASSPATH_SUN)
282
283                 /* This is the bootclasspath taken from HotSpot (see
284                    hotspot/src/share/vm/runtime/os.cpp
285                    (os::set_boot_path)). */
286
287                 len =
288                         strlen(CLASSPATH_PREFIX"/lib/resources.jar:") +
289                         strlen(CLASSPATH_PREFIX"/lib/rt.jar:") +
290                         strlen(CLASSPATH_PREFIX"/lib/sunrsasign.jar:") +
291                         strlen(CLASSPATH_PREFIX"/lib/jsse.jar:") +
292                         strlen(CLASSPATH_PREFIX"/lib/jce.jar:") +
293                         strlen(CLASSPATH_PREFIX"/lib/charsets.jar:") +
294                         strlen(CLASSPATH_PREFIX"/classes") +
295                         strlen("0");
296
297                 boot_class_path = MNEW(char, len);
298
299                 strcpy(boot_class_path, CLASSPATH_PREFIX"/lib/resources.jar:");
300                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/rt.jar:");
301                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/sunrsasign.jar:");
302                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jsse.jar:");
303                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jce.jar:");
304                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/charsets.jar:");
305                 strcat(boot_class_path, CLASSPATH_PREFIX"/classes");
306
307 # elif defined(WITH_CLASSPATH_CLDC1_1)
308
309                 len =
310                         strlen(CLASSPATH_CLASSES) +
311                         strlen("0");
312
313                 boot_class_path = MNEW(char, len);
314
315                 strcat(boot_class_path, CLASSPATH_CLASSES);
316
317 # else
318 #  error unknown classpath configuration
319 # endif
320 #endif
321         }
322
323         properties_add("java.boot.class.path", boot_class_path);
324         properties_add("sun.boot.class.path", boot_class_path);
325
326         /* Set the classpath. */
327
328         p = getenv("CLASSPATH");
329
330         if (p != NULL) {
331                 class_path = MNEW(char, strlen(p) + strlen("0"));
332                 strcpy(class_path, p);
333         }
334         else {
335                 class_path = MNEW(char, strlen(".") + strlen("0"));
336                 strcpy(class_path, ".");
337         }
338
339         properties_add("java.class.path", class_path);
340
341 #if defined(ENABLE_JAVASE)
342
343         /* get properties from system */
344
345         p = getenv("JAVA_HOME");
346
347         /* fill in system properties */
348
349         properties_add("java.vm.specification.version", "1.0");
350         properties_add("java.vm.specification.vendor", "Sun Microsystems Inc.");
351         properties_add("java.vm.specification.name", "Java Virtual Machine Specification");
352         properties_add("java.vm.version", VERSION);
353         properties_add("java.vm.vendor", "CACAO Team");
354         properties_add("java.vm.name", "CACAO");
355
356 # if defined(ENABLE_INTRP)
357         if (opt_intrp) {
358                 /* XXX We don't support java.lang.Compiler */
359 /*              properties_add("java.compiler", "cacao.intrp"); */
360                 properties_add("java.vm.info", "interpreted mode");
361         }
362         else
363 # endif
364         {
365                 /* XXX We don't support java.lang.Compiler */
366 /*              properties_add("java.compiler", "cacao.jit"); */
367                 properties_add("java.vm.info", "JIT mode");
368         }
369
370 # if defined(WITH_CLASSPATH_GNU)
371
372         /* Get properties from system. */
373
374         cwd      = _Jv_getcwd();
375
376         env_user = getenv("USER");
377         env_home = getenv("HOME");
378         env_lang = getenv("LANG");
379
380         utsnamebuf = NEW(struct utsname);
381
382         uname(utsnamebuf);
383
384         properties_add("java.runtime.version", VERSION);
385         properties_add("java.runtime.name", "CACAO");
386
387         properties_add("java.specification.version", "1.5");
388         properties_add("java.specification.vendor", "Sun Microsystems Inc.");
389         properties_add("java.specification.name", "Java Platform API Specification");
390
391         properties_add("java.version", JAVA_VERSION);
392         properties_add("java.vendor", "GNU Classpath");
393         properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
394
395         properties_add("java.class.version", CLASS_VERSION);
396
397 #  if defined(WITH_STATIC_CLASSPATH)
398         properties_add("gnu.classpath.boot.library.path", ".");
399         properties_add("java.library.path" , ".");
400 #  else
401         properties_add("gnu.classpath.boot.library.path", boot_library_path);
402
403         /* Get and set java.library.path. */
404
405         java_library_path = getenv("LD_LIBRARY_PATH");
406
407         if (java_library_path == NULL)
408                 java_library_path = "";
409
410         properties_add("java.library.path", java_library_path);
411 #  endif
412
413         properties_add("java.io.tmpdir", "/tmp");
414
415 #  if defined(ENABLE_INTRP)
416         if (opt_intrp) {
417                 properties_add("gnu.java.compiler.name", "cacao.intrp");
418         }
419         else
420 #  endif
421         {
422                 properties_add("gnu.java.compiler.name", "cacao.jit");
423         }
424
425         /* set the java.ext.dirs property */
426
427         len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
428
429         extdirs = MNEW(char, len);
430
431         strcpy(extdirs, java_home);
432         strcat(extdirs, "/jre/lib/ext");
433
434         properties_add("java.ext.dirs", extdirs);
435
436         properties_add("java.endorsed.dirs", ""CACAO_PREFIX"/jre/lib/endorsed");
437
438 #  if defined(DISABLE_GC)
439         /* When we disable the GC, we mmap the whole heap to a specific
440            address, so we can compare call traces. For this reason we have
441            to add the same properties on different machines, otherwise
442            more memory may be allocated (e.g. strlen("i386")
443            vs. strlen("alpha"). */
444
445         properties_add("os.arch", "unknown");
446         properties_add("os.name", "unknown");
447         properties_add("os.version", "unknown");
448 #  else
449         properties_add("os.arch", JAVA_ARCH);
450         properties_add("os.name", utsnamebuf->sysname);
451         properties_add("os.version", utsnamebuf->release);
452 #  endif
453
454 #  if defined(WITH_STATIC_CLASSPATH)
455         /* This is just for debugging purposes and can cause troubles in
456        GNU Classpath. */
457
458         properties_add("gnu.cpu.endian", "unknown");
459 #  else
460 #   if WORDS_BIGENDIAN == 1
461         properties_add("gnu.cpu.endian", "big");
462 #   else
463         properties_add("gnu.cpu.endian", "little");
464 #   endif
465 #  endif
466
467         properties_add("file.separator", "/");
468         properties_add("path.separator", ":");
469         properties_add("line.separator", "\n");
470
471         properties_add("user.name", env_user ? env_user : "null");
472         properties_add("user.home", env_home ? env_home : "null");
473         properties_add("user.dir", cwd ? cwd : "null");
474
475         /* get locale */
476
477         if (env_lang != NULL) {
478                 /* get the local stuff from the environment */
479
480                 if (strlen(env_lang) <= 2) {
481                         properties_add("user.language", env_lang);
482                 }
483                 else {
484                         if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
485                                 lang = MNEW(char, 3);
486                                 strncpy(lang, (char *) &env_lang[0], 2);
487                                 lang[2] = '\0';
488
489                                 country = MNEW(char, 3);
490                                 strncpy(country, (char *) &env_lang[3], 2);
491                                 country[2] = '\0';
492
493                                 properties_add("user.language", lang);
494                                 properties_add("user.country", country);
495                         }
496                 }
497         }
498         else {
499                 /* if no default locale was specified, use `en_US' */
500
501                 properties_add("user.language", "en");
502                 properties_add("user.country", "US");
503         }
504
505 # elif defined(WITH_CLASSPATH_SUN)
506
507         /* Nothing to do. */
508
509 # else
510
511 #  error unknown classpath configuration
512
513 # endif
514
515 #elif defined(ENABLE_JAVAME_CLDC1_1)
516
517     properties_add("microedition.configuration", "CLDC-1.1");
518     properties_add("microedition.platform", "generic");
519     properties_add("microedition.encoding", "ISO8859_1");
520     properties_add("microedition.profiles", "");
521
522 #else
523
524 # error unknown Java configuration
525
526 #endif
527 }
528
529
530 /* properties_add **************************************************************
531
532    Adds a property entry to the internal property list.  If there's
533    already an entry with the same key, replace it.
534
535 *******************************************************************************/
536
537 void properties_add(char *key, char *value)
538 {
539         list_properties_entry_t *pe;
540
541         /* search for the entry */
542
543         for (pe = list_first_unsynced(list_properties); pe != NULL;
544                  pe = list_next_unsynced(list_properties, pe)) {
545                 if (strcmp(pe->key, key) == 0) {
546                         /* entry was found, replace the value */
547
548                         pe->value = value;
549
550                         return;
551                 }
552         }
553
554         /* entry was not found, insert a new one */
555
556         pe = NEW(list_properties_entry_t);
557
558         pe->key   = key;
559         pe->value = value;
560
561         list_add_last_unsynced(list_properties, pe);
562 }
563
564
565 /* properties_get **************************************************************
566
567    Get a property entry from the internal property list.
568
569 *******************************************************************************/
570
571 char *properties_get(char *key)
572 {
573         list_properties_entry_t *pe;
574
575         for (pe = list_first_unsynced(list_properties); pe != NULL;
576                  pe = list_next_unsynced(list_properties, pe)) {
577                 if (strcmp(pe->key, key) == 0)
578                         return pe->value;
579         }
580
581         return NULL;
582 }
583
584
585 /* properties_system_add *******************************************************
586
587    Adds a given property to the Java system properties.
588
589 *******************************************************************************/
590
591 void properties_system_add(java_handle_t *p, char *key, char *value)
592 {
593         methodinfo    *m;
594         java_handle_t *k;
595         java_handle_t *v;
596
597         /* search for method to add properties */
598
599         m = class_resolveclassmethod(p->vftbl->class,
600                                                                  utf_put,
601                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
602                                                                  NULL,
603                                                                  true);
604
605         if (m == NULL)
606                 return;
607
608         /* add to the Java system properties */
609
610         k = javastring_new_from_utf_string(key);
611         v = javastring_new_from_utf_string(value);
612
613         (void) vm_call_method(m, p, k, v);
614 }
615
616
617 /* properties_system_add_all ***************************************************
618
619    Adds all properties from the properties list to the Java system
620    properties.
621
622    ARGUMENTS:
623        p.... is actually a java_util_Properties structure
624
625 *******************************************************************************/
626
627 #if defined(ENABLE_JAVASE)
628 void properties_system_add_all(java_handle_t *p)
629 {
630         list_properties_entry_t *pe;
631         methodinfo              *m;
632         java_handle_t           *key;
633         java_handle_t           *value;
634
635         /* search for method to add properties */
636
637         m = class_resolveclassmethod(p->vftbl->class,
638                                                                  utf_put,
639                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
640                                                                  NULL,
641                                                                  true);
642
643         if (m == NULL)
644                 return;
645
646         /* process all properties stored in the internal table */
647
648         for (pe = list_first(list_properties); pe != NULL;
649                  pe = list_next(list_properties, pe)) {
650                 /* add to the Java system properties */
651
652                 key   = javastring_new_from_utf_string(pe->key);
653                 value = javastring_new_from_utf_string(pe->value);
654
655                 (void) vm_call_method(m, (java_handle_t *) p, key, value);
656         }
657 }
658 #endif /* defined(ENABLE_JAVASE) */
659
660
661 /*
662  * These are local overrides for various environment variables in Emacs.
663  * Please do not remove this and leave it at the end of the file, where
664  * Emacs will automagically detect them.
665  * ---------------------------------------------------------------------
666  * Local variables:
667  * mode: c
668  * indent-tabs-mode: t
669  * c-basic-offset: 4
670  * tab-width: 4
671  * End:
672  */