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