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