1 /* System.java -- useful methods to interface with the system 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2012 3 Free Software Foundation, Inc. 4 5 This file is part of GNU Classpath. 6 7 GNU Classpath is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 GNU Classpath is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GNU Classpath; see the file COPYING. If not, write to the 19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-1301 USA. 21 22 Linking this library statically or dynamically with other modules is 23 making a combined work based on this library. Thus, the terms and 24 conditions of the GNU General Public License cover the whole 25 combination. 26 27 As a special exception, the copyright holders of this library give you 28 permission to link this library with independent modules to produce an 29 executable, regardless of the license terms of these independent 30 modules, and to copy and distribute the resulting executable under 31 terms of your choice, provided that you also meet, for each linked 32 independent module, the terms and conditions of the license of that 33 module. An independent module is a module which is not derived from 34 or based on this library. If you modify this library, you may extend 35 this exception to your version of the library, but you are not 36 obligated to do so. If you do not wish to do so, delete this 37 exception statement from your version. */ 38 39 40 package java.lang; 41 42 import gnu.classpath.SystemProperties; 43 import gnu.classpath.VMStackWalker; 44 45 import java.io.IOException; 46 import java.io.InputStream; 47 import java.io.PrintStream; 48 import java.io.Console; 49 import java.nio.channels.Channel; 50 import java.nio.channels.spi.SelectorProvider; 51 import java.util.AbstractCollection; 52 import java.util.Collection; 53 import java.util.Collections; 54 import java.util.HashMap; 55 import java.util.Iterator; 56 import java.util.List; 57 import java.util.Map; 58 import java.util.Set; 59 import java.util.Properties; 60 import java.util.PropertyPermission; 61 62 /** 63 * System represents system-wide resources; things that represent the 64 * general environment. As such, all methods are static. 65 * 66 * @author John Keiser 67 * @author Eric Blake (ebb9@email.byu.edu) 68 * @since 1.0 69 * @status still missing 1.4 functionality 70 */ 71 public final class System 72 { 73 // WARNING: System is a CORE class in the bootstrap cycle. See the comments 74 // in vm/reference/java/lang/Runtime for implications of this fact. 75 76 /** 77 * The standard InputStream. This is assigned at startup and starts its 78 * life perfectly valid. Although it is marked final, you can change it 79 * using {@link #setIn(InputStream)} through some hefty VM magic. 80 * 81 * <p>This corresponds to the C stdin and C++ cin variables, which 82 * typically input from the keyboard, but may be used to pipe input from 83 * other processes or files. That should all be transparent to you, 84 * however. 85 */ 86 public static final InputStream in = VMSystem.makeStandardInputStream(); 87 88 /** 89 * The standard output PrintStream. This is assigned at startup and 90 * starts its life perfectly valid. Although it is marked final, you can 91 * change it using {@link #setOut(PrintStream)} through some hefty VM magic. 92 * 93 * <p>This corresponds to the C stdout and C++ cout variables, which 94 * typically output normal messages to the screen, but may be used to pipe 95 * output to other processes or files. That should all be transparent to 96 * you, however. 97 */ 98 public static final PrintStream out = VMSystem.makeStandardOutputStream(); 99 100 private static final String LINE_SEPARATOR = SystemProperties.getProperty("line.separator"); 101 102 /** 103 * The standard output PrintStream. This is assigned at startup and 104 * starts its life perfectly valid. Although it is marked final, you can 105 * change it using {@link #setErr(PrintStream)} through some hefty VM magic. 106 * 107 * <p>This corresponds to the C stderr and C++ cerr variables, which 108 * typically output error messages to the screen, but may be used to pipe 109 * output to other processes or files. That should all be transparent to 110 * you, however. 111 */ 112 public static final PrintStream err = VMSystem.makeStandardErrorStream(); 113 114 /** 115 * A cached copy of the environment variable map. 116 */ 117 private static Map<String,String> environmentMap; 118 119 /** 120 * This class is uninstantiable. 121 */ System()122 private System() 123 { 124 } 125 126 /** 127 * Set {@link #in} to a new InputStream. This uses some VM magic to change 128 * a "final" variable, so naturally there is a security check, 129 * <code>RuntimePermission("setIO")</code>. 130 * 131 * @param in the new InputStream 132 * @throws SecurityException if permission is denied 133 * @since 1.1 134 */ setIn(InputStream in)135 public static void setIn(InputStream in) 136 { 137 SecurityManager sm = SecurityManager.current; // Be thread-safe. 138 if (sm != null) 139 sm.checkPermission(new RuntimePermission("setIO")); 140 141 VMSystem.setIn(in); 142 } 143 144 /** 145 * Set {@link #out} to a new PrintStream. This uses some VM magic to change 146 * a "final" variable, so naturally there is a security check, 147 * <code>RuntimePermission("setIO")</code>. 148 * 149 * @param out the new PrintStream 150 * @throws SecurityException if permission is denied 151 * @since 1.1 152 */ setOut(PrintStream out)153 public static void setOut(PrintStream out) 154 { 155 SecurityManager sm = SecurityManager.current; // Be thread-safe. 156 if (sm != null) 157 sm.checkPermission(new RuntimePermission("setIO")); 158 VMSystem.setOut(out); 159 } 160 161 /** 162 * Set {@link #err} to a new PrintStream. This uses some VM magic to change 163 * a "final" variable, so naturally there is a security check, 164 * <code>RuntimePermission("setIO")</code>. 165 * 166 * @param err the new PrintStream 167 * @throws SecurityException if permission is denied 168 * @since 1.1 169 */ setErr(PrintStream err)170 public static void setErr(PrintStream err) 171 { 172 SecurityManager sm = SecurityManager.current; // Be thread-safe. 173 if (sm != null) 174 sm.checkPermission(new RuntimePermission("setIO")); 175 VMSystem.setErr(err); 176 } 177 178 /** 179 * Set the current SecurityManager. If a security manager already exists, 180 * then <code>RuntimePermission("setSecurityManager")</code> is checked 181 * first. Since this permission is denied by the default security manager, 182 * setting the security manager is often an irreversible action. 183 * 184 * <STRONG>Spec Note:</STRONG> Don't ask me, I didn't write it. It looks 185 * pretty vulnerable; whoever gets to the gate first gets to set the policy. 186 * There is probably some way to set the original security manager as a 187 * command line argument to the VM, but I don't know it. 188 * 189 * @param sm the new SecurityManager 190 * @throws SecurityException if permission is denied 191 */ setSecurityManager(SecurityManager sm)192 public static synchronized void setSecurityManager(SecurityManager sm) 193 { 194 // Implementation note: the field lives in SecurityManager because of 195 // bootstrap initialization issues. This method is synchronized so that 196 // no other thread changes it to null before this thread makes the change. 197 if (SecurityManager.current != null) 198 SecurityManager.current.checkPermission 199 (new RuntimePermission("setSecurityManager")); 200 201 // java.security.Security's class initialiser loads and parses the 202 // policy files. If it hasn't been run already it will be run 203 // during the first permission check. That initialisation will 204 // fail if a very restrictive security manager is in force, so we 205 // preload it here. 206 if (SecurityManager.current == null) 207 { 208 try 209 { 210 Class.forName("java.security.Security"); 211 } 212 catch (ClassNotFoundException e) 213 { 214 } 215 } 216 217 SecurityManager.current = sm; 218 } 219 220 /** 221 * Get the current SecurityManager. If the SecurityManager has not been 222 * set yet, then this method returns null. 223 * 224 * @return the current SecurityManager, or null 225 */ getSecurityManager()226 public static SecurityManager getSecurityManager() 227 { 228 return SecurityManager.current; 229 } 230 231 /** 232 * Get the current time, measured in the number of milliseconds from the 233 * beginning of Jan. 1, 1970. This is gathered from the system clock, with 234 * any attendant incorrectness (it may be timezone dependent). 235 * 236 * @return the current time 237 * @see java.util.Date 238 */ currentTimeMillis()239 public static long currentTimeMillis() 240 { 241 return VMSystem.currentTimeMillis(); 242 } 243 244 /** 245 * <p> 246 * Returns the current value of a nanosecond-precise system timer. 247 * The value of the timer is an offset relative to some arbitrary fixed 248 * time, which may be in the future (making the value negative). This 249 * method is useful for timing events where nanosecond precision is 250 * required. This is achieved by calling this method before and after the 251 * event, and taking the difference betweent the two times: 252 * </p> 253 * <p> 254 * <code>long startTime = System.nanoTime();</code><br /> 255 * <code>... <emph>event code</emph> ...</code><br /> 256 * <code>long endTime = System.nanoTime();</code><br /> 257 * <code>long duration = endTime - startTime;</code><br /> 258 * </p> 259 * <p> 260 * Note that the value is only nanosecond-precise, and not accurate; there 261 * is no guarantee that the difference between two values is really a 262 * nanosecond. Also, the value is prone to overflow if the offset 263 * exceeds 2^63. 264 * </p> 265 * 266 * @return the time of a system timer in nanoseconds. 267 * @since 1.5 268 */ nanoTime()269 public static long nanoTime() 270 { 271 return VMSystem.nanoTime(); 272 } 273 274 /** 275 * Copy one array onto another from <code>src[srcStart]</code> ... 276 * <code>src[srcStart+len-1]</code> to <code>dest[destStart]</code> ... 277 * <code>dest[destStart+len-1]</code>. First, the arguments are validated: 278 * neither array may be null, they must be of compatible types, and the 279 * start and length must fit within both arrays. Then the copying starts, 280 * and proceeds through increasing slots. If src and dest are the same 281 * array, this will appear to copy the data to a temporary location first. 282 * An ArrayStoreException in the middle of copying will leave earlier 283 * elements copied, but later elements unchanged. 284 * 285 * @param src the array to copy elements from 286 * @param srcStart the starting position in src 287 * @param dest the array to copy elements to 288 * @param destStart the starting position in dest 289 * @param len the number of elements to copy 290 * @throws NullPointerException if src or dest is null 291 * @throws ArrayStoreException if src or dest is not an array, if they are 292 * not compatible array types, or if an incompatible runtime type 293 * is stored in dest 294 * @throws IndexOutOfBoundsException if len is negative, or if the start or 295 * end copy position in either array is out of bounds 296 */ arraycopy(Object src, int srcStart, Object dest, int destStart, int len)297 public static void arraycopy(Object src, int srcStart, 298 Object dest, int destStart, int len) 299 { 300 VMSystem.arraycopy(src, srcStart, dest, destStart, len); 301 } 302 303 /** 304 * Get a hash code computed by the VM for the Object. This hash code will 305 * be the same as Object's hashCode() method. It is usually some 306 * convolution of the pointer to the Object internal to the VM. It 307 * follows standard hash code rules, in that it will remain the same for a 308 * given Object for the lifetime of that Object. 309 * 310 * @param o the Object to get the hash code for 311 * @return the VM-dependent hash code for this Object 312 * @since 1.1 313 */ identityHashCode(Object o)314 public static int identityHashCode(Object o) 315 { 316 return VMSystem.identityHashCode(o); 317 } 318 319 /** 320 * Get all the system properties at once. A security check may be performed, 321 * <code>checkPropertiesAccess</code>. Note that a security manager may 322 * allow getting a single property, but not the entire group. 323 * 324 * <p>The required properties include: 325 * <dl> 326 * <dt>java.version</dt> <dd>Java version number</dd> 327 * <dt>java.vendor</dt> <dd>Java vendor specific string</dd> 328 * <dt>java.vendor.url</dt> <dd>Java vendor URL</dd> 329 * <dt>java.home</dt> <dd>Java installation directory</dd> 330 * <dt>java.vm.specification.version</dt> <dd>VM Spec version</dd> 331 * <dt>java.vm.specification.vendor</dt> <dd>VM Spec vendor</dd> 332 * <dt>java.vm.specification.name</dt> <dd>VM Spec name</dd> 333 * <dt>java.vm.version</dt> <dd>VM implementation version</dd> 334 * <dt>java.vm.vendor</dt> <dd>VM implementation vendor</dd> 335 * <dt>java.vm.name</dt> <dd>VM implementation name</dd> 336 * <dt>java.specification.version</dt> <dd>Java Runtime Environment version</dd> 337 * <dt>java.specification.vendor</dt> <dd>Java Runtime Environment vendor</dd> 338 * <dt>java.specification.name</dt> <dd>Java Runtime Environment name</dd> 339 * <dt>java.class.version</dt> <dd>Java class version number</dd> 340 * <dt>java.class.path</dt> <dd>Java classpath</dd> 341 * <dt>java.library.path</dt> <dd>Path for finding Java libraries</dd> 342 * <dt>java.io.tmpdir</dt> <dd>Default temp file path</dd> 343 * <dt>java.compiler</dt> <dd>Name of JIT to use</dd> 344 * <dt>java.ext.dirs</dt> <dd>Java extension path</dd> 345 * <dt>os.name</dt> <dd>Operating System Name</dd> 346 * <dt>os.arch</dt> <dd>Operating System Architecture</dd> 347 * <dt>os.version</dt> <dd>Operating System Version</dd> 348 * <dt>file.separator</dt> <dd>File separator ("/" on Unix)</dd> 349 * <dt>path.separator</dt> <dd>Path separator (":" on Unix)</dd> 350 * <dt>line.separator</dt> <dd>Line separator ("\n" on Unix)</dd> 351 * <dt>user.name</dt> <dd>User account name</dd> 352 * <dt>user.home</dt> <dd>User home directory</dd> 353 * <dt>user.dir</dt> <dd>User's current working directory</dd> 354 * </dl> 355 * 356 * In addition, gnu defines several other properties, where ? stands for 357 * each character in '0' through '9': 358 * <dl> 359 * <dt>gnu.classpath.home</dt> <dd>Path to the classpath libraries.</dd> 360 * <dt>gnu.classpath.version</dt> <dd>Version of the classpath libraries.</dd> 361 * <dt>gnu.classpath.vm.shortname</dt> <dd>Succinct version of the VM name; 362 * used for finding property files in file system</dd> 363 * <dt>gnu.classpath.home.url</dt> <dd> Base URL; used for finding 364 * property files in file system</dd> 365 * <dt>gnu.cpu.endian</dt> <dd>big or little</dd> 366 * <dt>gnu.java.io.encoding_scheme_alias.iso-8859-?</dt> <dd>8859_?</dd> 367 * <dt>gnu.java.io.encoding_scheme_alias.iso8859_?</dt> <dd>8859_?</dd> 368 * <dt>gnu.java.io.encoding_scheme_alias.iso-latin-_?</dt> <dd>8859_?</dd> 369 * <dt>gnu.java.io.encoding_scheme_alias.latin?</dt> <dd>8859_?</dd> 370 * <dt>gnu.java.io.encoding_scheme_alias.utf-8</dt> <dd>UTF8</dd> 371 * <dt>gnu.java.util.zoneinfo.dir</dt> <dd>Root of zoneinfo tree</dd> 372 * <dt>gnu.javax.print.server</dt> <dd>Hostname of external CUPS server.</dd> 373 * </dl> 374 * 375 * @return the system properties, will never be null 376 * @throws SecurityException if permission is denied 377 */ getProperties()378 public static Properties getProperties() 379 { 380 SecurityManager sm = SecurityManager.current; // Be thread-safe. 381 if (sm != null) 382 sm.checkPropertiesAccess(); 383 return SystemProperties.getProperties(); 384 } 385 386 /** 387 * Set all the system properties at once. A security check may be performed, 388 * <code>checkPropertiesAccess</code>. Note that a security manager may 389 * allow setting a single property, but not the entire group. An argument 390 * of null resets the properties to the startup default. 391 * 392 * @param properties the new set of system properties 393 * @throws SecurityException if permission is denied 394 */ setProperties(Properties properties)395 public static void setProperties(Properties properties) 396 { 397 SecurityManager sm = SecurityManager.current; // Be thread-safe. 398 if (sm != null) 399 sm.checkPropertiesAccess(); 400 SystemProperties.setProperties(properties); 401 } 402 403 /** 404 * Get a single system property by name. A security check may be performed, 405 * <code>checkPropertyAccess(key)</code>. 406 * 407 * @param key the name of the system property to get 408 * @return the property, or null if not found 409 * @throws SecurityException if permission is denied 410 * @throws NullPointerException if key is null 411 * @throws IllegalArgumentException if key is "" 412 */ getProperty(String key)413 public static String getProperty(String key) 414 { 415 SecurityManager sm = SecurityManager.current; // Be thread-safe. 416 if (sm != null) 417 sm.checkPropertyAccess(key); 418 if (key.length() == 0) 419 throw new IllegalArgumentException("key can't be empty"); 420 return SystemProperties.getProperty(key); 421 } 422 423 /** 424 * Get a single system property by name. A security check may be performed, 425 * <code>checkPropertyAccess(key)</code>. 426 * 427 * @param key the name of the system property to get 428 * @param def the default 429 * @return the property, or def if not found 430 * @throws SecurityException if permission is denied 431 * @throws NullPointerException if key is null 432 * @throws IllegalArgumentException if key is "" 433 */ getProperty(String key, String def)434 public static String getProperty(String key, String def) 435 { 436 SecurityManager sm = SecurityManager.current; // Be thread-safe. 437 if (sm != null) 438 sm.checkPropertyAccess(key); 439 // This handles both the null pointer exception and the illegal 440 // argument exception. 441 if (key.length() == 0) 442 throw new IllegalArgumentException("key can't be empty"); 443 return SystemProperties.getProperty(key, def); 444 } 445 446 /** 447 * Set a single system property by name. A security check may be performed, 448 * <code>checkPropertyAccess(key, "write")</code>. 449 * 450 * @param key the name of the system property to set 451 * @param value the new value 452 * @return the previous value, or null 453 * @throws SecurityException if permission is denied 454 * @throws NullPointerException if key is null 455 * @throws IllegalArgumentException if key is "" 456 * @since 1.2 457 */ setProperty(String key, String value)458 public static String setProperty(String key, String value) 459 { 460 SecurityManager sm = SecurityManager.current; // Be thread-safe. 461 if (sm != null) 462 sm.checkPermission(new PropertyPermission(key, "write")); 463 // This handles both the null pointer exception and the illegal 464 // argument exception. 465 if (key.length() == 0) 466 throw new IllegalArgumentException("key can't be empty"); 467 return SystemProperties.setProperty(key, value); 468 } 469 470 /** 471 * Remove a single system property by name. A security check may be 472 * performed, <code>checkPropertyAccess(key, "write")</code>. 473 * 474 * @param key the name of the system property to remove 475 * @return the previous value, or null 476 * @throws SecurityException if permission is denied 477 * @throws NullPointerException if key is null 478 * @throws IllegalArgumentException if key is "" 479 * @since 1.5 480 */ clearProperty(String key)481 public static String clearProperty(String key) 482 { 483 SecurityManager sm = SecurityManager.current; // Be thread-safe. 484 if (sm != null) 485 sm.checkPermission(new PropertyPermission(key, "write")); 486 // This handles both the null pointer exception and the illegal 487 // argument exception. 488 if (key.length() == 0) 489 throw new IllegalArgumentException("key can't be empty"); 490 return SystemProperties.remove(key); 491 } 492 493 /** 494 * Gets the value of an environment variable. 495 * 496 * @param name the name of the environment variable 497 * @return the string value of the variable or null when the 498 * environment variable is not defined. 499 * @throws NullPointerException 500 * @throws SecurityException if permission is denied 501 * @since 1.5 502 * @specnote This method was deprecated in some JDK releases, but 503 * was restored in 1.5. 504 */ getenv(String name)505 public static String getenv(String name) 506 { 507 if (name == null) 508 throw new NullPointerException(); 509 SecurityManager sm = SecurityManager.current; // Be thread-safe. 510 if (sm != null) 511 sm.checkPermission(new RuntimePermission("getenv." + name)); 512 return VMSystem.getenv(name); 513 } 514 515 /** 516 * <p> 517 * Returns an unmodifiable view of the system environment variables. 518 * If the underlying system does not support environment variables, 519 * an empty map is returned. 520 * </p> 521 * <p> 522 * The returned map is read-only and does not accept queries using 523 * null keys or values, or those of a type other than <code>String</code>. 524 * Attempts to modify the map will throw an 525 * <code>UnsupportedOperationException</code>, while attempts 526 * to pass in a null value will throw a 527 * <code>NullPointerException</code>. Types other than <code>String</code> 528 * throw a <code>ClassCastException</code>. 529 * </p> 530 * <p> 531 * As the returned map is generated using data from the underlying 532 * platform, it may not comply with the <code>equals()</code> 533 * and <code>hashCode()</code> contracts. It is also likely that 534 * the keys of this map will be case-sensitive. 535 * </p> 536 * <p> 537 * Use of this method may require a security check for the 538 * RuntimePermission "getenv.*". 539 * </p> 540 * 541 * @return a map of the system environment variables. 542 * @throws SecurityException if the checkPermission method of 543 * an installed security manager prevents access to 544 * the system environment variables. 545 * @since 1.5 546 */ getenv()547 public static Map<String, String> getenv() 548 { 549 SecurityManager sm = SecurityManager.current; // Be thread-safe. 550 if (sm != null) 551 sm.checkPermission(new RuntimePermission("getenv.*")); 552 553 if (environmentMap == null) 554 { 555 Map<String,String> variables = new EnvironmentMap(); 556 List<String> environ = (List<String>)VMSystem.environ(); 557 for (String envEntry : environ) 558 { 559 // avoid broken and null entries 560 if (envEntry != null && !envEntry.endsWith("=")) 561 { 562 // it's perfectly legal that some entries may be in the form 563 // key=value=value=value 564 int equalSignIndex = envEntry.indexOf('='); 565 String key = envEntry.substring(0, equalSignIndex); 566 String value = envEntry.substring(equalSignIndex + 1); 567 variables.put(key, value); 568 } 569 } 570 571 environmentMap = Collections.unmodifiableMap(variables); 572 } 573 574 return environmentMap; 575 } 576 577 /** 578 * Terminate the Virtual Machine. This just calls 579 * <code>Runtime.getRuntime().exit(status)</code>, and never returns. 580 * Obviously, a security check is in order, <code>checkExit</code>. 581 * 582 * @param status the exit status; by convention non-zero is abnormal 583 * @throws SecurityException if permission is denied 584 * @see Runtime#exit(int) 585 */ exit(int status)586 public static void exit(int status) 587 { 588 Runtime.getRuntime().exit(status); 589 } 590 591 /** 592 * Calls the garbage collector. This is only a hint, and it is up to the 593 * implementation what this hint suggests, but it usually causes a 594 * best-effort attempt to reclaim unused memory from discarded objects. 595 * This calls <code>Runtime.getRuntime().gc()</code>. 596 * 597 * @see Runtime#gc() 598 */ gc()599 public static void gc() 600 { 601 Runtime.getRuntime().gc(); 602 } 603 604 /** 605 * Runs object finalization on pending objects. This is only a hint, and 606 * it is up to the implementation what this hint suggests, but it usually 607 * causes a best-effort attempt to run finalizers on all objects ready 608 * to be reclaimed. This calls 609 * <code>Runtime.getRuntime().runFinalization()</code>. 610 * 611 * @see Runtime#runFinalization() 612 */ runFinalization()613 public static void runFinalization() 614 { 615 Runtime.getRuntime().runFinalization(); 616 } 617 618 /** 619 * Tell the Runtime whether to run finalization before exiting the 620 * JVM. This is inherently unsafe in multi-threaded applications, 621 * since it can force initialization on objects which are still in use 622 * by live threads, leading to deadlock; therefore this is disabled by 623 * default. There may be a security check, <code>checkExit(0)</code>. This 624 * calls <code>Runtime.runFinalizersOnExit()</code>. 625 * 626 * @param finalizeOnExit whether to run finalizers on exit 627 * @throws SecurityException if permission is denied 628 * @see Runtime#runFinalizersOnExit(boolean) 629 * @since 1.1 630 * @deprecated never rely on finalizers to do a clean, thread-safe, 631 * mop-up from your code 632 */ runFinalizersOnExit(boolean finalizeOnExit)633 public static void runFinalizersOnExit(boolean finalizeOnExit) 634 { 635 Runtime.runFinalizersOnExit(finalizeOnExit); 636 } 637 638 /** 639 * Load a code file using its explicit system-dependent filename. A security 640 * check may be performed, <code>checkLink</code>. This just calls 641 * <code>Runtime.getRuntime().load(filename)</code>. 642 * 643 * <p> 644 * The library is loaded using the class loader associated with the 645 * class associated with the invoking method. 646 * 647 * @param filename the code file to load 648 * @throws SecurityException if permission is denied 649 * @throws UnsatisfiedLinkError if the file cannot be loaded 650 * @see Runtime#load(String) 651 */ load(String filename)652 public static void load(String filename) 653 { 654 Runtime.getRuntime().load(filename, VMStackWalker.getCallingClassLoader()); 655 } 656 657 /** 658 * Load a library using its explicit system-dependent filename. A security 659 * check may be performed, <code>checkLink</code>. This just calls 660 * <code>Runtime.getRuntime().load(filename)</code>. 661 * 662 * <p> 663 * The library is loaded using the class loader associated with the 664 * class associated with the invoking method. 665 * 666 * @param libname the library file to load 667 * @throws SecurityException if permission is denied 668 * @throws UnsatisfiedLinkError if the file cannot be loaded 669 * @see Runtime#load(String) 670 */ loadLibrary(String libname)671 public static void loadLibrary(String libname) 672 { 673 Runtime.getRuntime().loadLibrary(libname, 674 VMStackWalker.getCallingClassLoader()); 675 } 676 677 /** 678 * Convert a library name to its platform-specific variant. 679 * 680 * @param libname the library name, as used in <code>loadLibrary</code> 681 * @return the platform-specific mangling of the name 682 * @since 1.2 683 */ mapLibraryName(String libname)684 public static String mapLibraryName(String libname) 685 { 686 return VMRuntime.mapLibraryName(libname); 687 } 688 689 /** 690 * Returns the inherited channel of the VM. 691 * 692 * This wraps the inheritedChannel() call of the system's default 693 * {@link SelectorProvider}. 694 * 695 * @return the inherited channel of the VM 696 * 697 * @throws IOException If an I/O error occurs 698 * @throws SecurityException If an installed security manager denies access 699 * to RuntimePermission("inheritedChannel") 700 * 701 * @since 1.5 702 */ inheritedChannel()703 public static Channel inheritedChannel() 704 throws IOException 705 { 706 return SelectorProvider.provider().inheritedChannel(); 707 } 708 709 /* 710 * @since 1.6 711 */ console()712 public static Console console() 713 { 714 return Console.console(); 715 } 716 717 /** 718 * Returns the system-dependent line separator. 719 * 720 * @return the system-dependent line separator. 721 */ lineSeparator()722 public static String lineSeparator() 723 { 724 return LINE_SEPARATOR; 725 } 726 727 /** 728 * This is a specialised <code>Collection</code>, providing 729 * the necessary provisions for the collections used by the 730 * environment variable map. Namely, it prevents 731 * querying anything but <code>String</code>s. 732 * 733 * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 734 */ 735 private static class EnvironmentCollection 736 extends AbstractCollection<String> 737 { 738 739 /** 740 * The wrapped collection. 741 */ 742 protected Collection<String> c; 743 744 /** 745 * Constructs a new environment collection, which 746 * wraps the elements of the supplied collection. 747 * 748 * @param coll the collection to use as a base for 749 * this collection. 750 */ EnvironmentCollection(Collection<String> coll)751 public EnvironmentCollection(Collection<String> coll) 752 { 753 c = coll; 754 } 755 756 /** 757 * Blocks queries containing a null object or an object which 758 * isn't of type <code>String</code>. All other queries 759 * are forwarded to the underlying collection. 760 * 761 * @param obj the object to look for. 762 * @return true if the object exists in the collection. 763 * @throws NullPointerException if the specified object is null. 764 * @throws ClassCastException if the specified object is not a String. 765 */ contains(Object obj)766 public boolean contains(Object obj) 767 { 768 if (obj == null) 769 throw new 770 NullPointerException("This collection does not support " + 771 "null values."); 772 if (!(obj instanceof String)) 773 throw new 774 ClassCastException("This collection only supports Strings."); 775 return c.contains(obj); 776 } 777 778 /** 779 * Blocks queries where the collection contains a null object or 780 * an object which isn't of type <code>String</code>. All other 781 * queries are forwarded to the underlying collection. 782 * 783 * @param coll the collection of objects to look for. 784 * @return true if the collection contains all elements in the collection. 785 * @throws NullPointerException if the collection is null. 786 * @throws NullPointerException if any collection entry is null. 787 * @throws ClassCastException if any collection entry is not a String. 788 */ containsAll(Collection<?> coll)789 public boolean containsAll(Collection<?> coll) 790 { 791 for (Object o: coll) 792 { 793 if (o == null) 794 throw new 795 NullPointerException("This collection does not support " + 796 "null values."); 797 if (!(o instanceof String)) 798 throw new 799 ClassCastException("This collection only supports Strings."); 800 } 801 return c.containsAll(coll); 802 } 803 804 /** 805 * This returns an iterator over the map elements, with the 806 * same provisions as for the collection and underlying map. 807 * 808 * @return an iterator over the map elements. 809 */ iterator()810 public Iterator<String> iterator() 811 { 812 return c.iterator(); 813 } 814 815 /** 816 * Blocks the removal of elements from the collection. 817 * 818 * @return true if the removal was sucessful. 819 * @throws NullPointerException if the collection is null. 820 * @throws NullPointerException if any collection entry is null. 821 * @throws ClassCastException if any collection entry is not a String. 822 */ remove(Object key)823 public boolean remove(Object key) 824 { 825 if (key == null) 826 throw new 827 NullPointerException("This collection does not support " + 828 "null values."); 829 if (!(key instanceof String)) 830 throw new 831 ClassCastException("This collection only supports Strings."); 832 return c.contains(key); 833 } 834 835 /** 836 * Blocks the removal of all elements in the specified 837 * collection from the collection. 838 * 839 * @param coll the collection of elements to remove. 840 * @return true if the elements were removed. 841 * @throws NullPointerException if the collection is null. 842 * @throws NullPointerException if any collection entry is null. 843 * @throws ClassCastException if any collection entry is not a String. 844 */ removeAll(Collection<?> coll)845 public boolean removeAll(Collection<?> coll) 846 { 847 for (Object o: coll) 848 { 849 if (o == null) 850 throw new 851 NullPointerException("This collection does not support " + 852 "null values."); 853 if (!(o instanceof String)) 854 throw new 855 ClassCastException("This collection only supports Strings."); 856 } 857 return c.removeAll(coll); 858 } 859 860 /** 861 * Blocks the retention of all elements in the specified 862 * collection from the collection. 863 * 864 * @param coll the collection of elements to retain. 865 * @return true if the other elements were removed. 866 * @throws NullPointerException if the collection is null. 867 * @throws NullPointerException if any collection entry is null. 868 * @throws ClassCastException if any collection entry is not a String. 869 */ retainAll(Collection<?> coll)870 public boolean retainAll(Collection<?> coll) 871 { 872 for (Object o: coll) 873 { 874 if (o == null) 875 throw new 876 NullPointerException("This collection does not support " + 877 "null values."); 878 if (!(o instanceof String)) 879 throw new 880 ClassCastException("This collection only supports Strings."); 881 } 882 return c.containsAll(coll); 883 } 884 885 /** 886 * This simply calls the same method on the wrapped 887 * collection. 888 * 889 * @return the size of the underlying collection. 890 */ size()891 public int size() 892 { 893 return c.size(); 894 } 895 896 } // class EnvironmentCollection<String> 897 898 /** 899 * This is a specialised <code>HashMap</code>, which 900 * prevents the addition or querying of anything other than 901 * <code>String</code> objects. 902 * 903 * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 904 */ 905 static class EnvironmentMap 906 extends HashMap<String,String> 907 { 908 909 /** 910 * Cache the entry set. 911 */ 912 private transient Set<Map.Entry<String,String>> entries; 913 914 /** 915 * Cache the key set. 916 */ 917 private transient Set<String> keys; 918 919 /** 920 * Cache the value collection. 921 */ 922 private transient Collection<String> values; 923 924 /** 925 * Constructs a new empty <code>EnvironmentMap</code>. 926 */ EnvironmentMap()927 EnvironmentMap() 928 { 929 super(); 930 } 931 932 /** 933 * Constructs a new <code>EnvironmentMap</code> containing 934 * the contents of the specified map. 935 * 936 * @param m the map to be added to this. 937 * @throws NullPointerException if a key or value is null. 938 * @throws ClassCastException if a key or value is not a String. 939 */ EnvironmentMap(Map<String,String> m)940 EnvironmentMap(Map<String,String> m) 941 { 942 super(m); 943 } 944 945 /** 946 * Blocks queries containing a null key or one which is not 947 * of type <code>String</code>. All other queries 948 * are forwarded to the superclass. 949 * 950 * @param key the key to look for in the map. 951 * @return true if the key exists in the map. 952 * @throws NullPointerException if the specified key is null. 953 */ containsKey(Object key)954 public boolean containsKey(Object key) 955 { 956 if (key == null) 957 throw new 958 NullPointerException("This map does not support null keys."); 959 if (!(key instanceof String)) 960 throw new 961 ClassCastException("This map only allows queries using Strings."); 962 return super.containsKey(key); 963 } 964 965 /** 966 * Blocks queries using a null or non-<code>String</code> value. 967 * All other queries are forwarded to the superclass. 968 * 969 * @param value the value to look for in the map. 970 * @return true if the value exists in the map. 971 * @throws NullPointerException if the specified value is null. 972 */ containsValue(Object value)973 public boolean containsValue(Object value) 974 { 975 if (value == null) 976 throw new 977 NullPointerException("This map does not support null values."); 978 if (!(value instanceof String)) 979 throw new 980 ClassCastException("This map only allows queries using Strings."); 981 return super.containsValue(value); 982 } 983 984 /** 985 * Returns a set view of the map entries, with the same 986 * provisions as for the underlying map. 987 * 988 * @return a set containing the map entries. 989 */ entrySet()990 public Set<Map.Entry<String,String>> entrySet() 991 { 992 if (entries == null) 993 entries = super.entrySet(); 994 return entries; 995 } 996 997 /** 998 * Blocks queries containing a null or non-<code>String</code> key. 999 * All other queries are passed on to the superclass. 1000 * 1001 * @param key the key to retrieve the value for. 1002 * @return the value associated with the given key. 1003 * @throws NullPointerException if the specified key is null. 1004 * @throws ClassCastException if the specified key is not a String. 1005 */ get(Object key)1006 public String get(Object key) 1007 { 1008 if (key == null) 1009 throw new 1010 NullPointerException("This map does not support null keys."); 1011 if (!(key instanceof String)) 1012 throw new 1013 ClassCastException("This map only allows queries using Strings."); 1014 return super.get(key); 1015 } 1016 1017 /** 1018 * Returns a set view of the keys, with the same 1019 * provisions as for the underlying map. 1020 * 1021 * @return a set containing the keys. 1022 */ keySet()1023 public Set<String> keySet() 1024 { 1025 if (keys == null) 1026 keys = new EnvironmentSet(super.keySet()); 1027 return keys; 1028 } 1029 1030 /** 1031 * Associates the given key to the given value. If the 1032 * map already contains the key, its value is replaced. 1033 * The map does not accept null keys or values, or keys 1034 * and values not of type {@link String}. 1035 * 1036 * @param key the key to map. 1037 * @param value the value to be mapped. 1038 * @return the previous value of the key, or null if there was no mapping 1039 * @throws NullPointerException if a key or value is null. 1040 * @throws ClassCastException if a key or value is not a String. 1041 */ put(String key, String value)1042 public String put(String key, String value) 1043 { 1044 if (key == null) 1045 throw new NullPointerException("A new key is null."); 1046 if (value == null) 1047 throw new NullPointerException("A new value is null."); 1048 if (!(key instanceof String)) 1049 throw new ClassCastException("A new key is not a String."); 1050 if (!(value instanceof String)) 1051 throw new ClassCastException("A new value is not a String."); 1052 return super.put(key, value); 1053 } 1054 1055 /** 1056 * Removes a key-value pair from the map. The queried key may not 1057 * be null or of a type other than a <code>String</code>. 1058 * 1059 * @param key the key of the entry to remove. 1060 * @return the removed value. 1061 * @throws NullPointerException if the specified key is null. 1062 * @throws ClassCastException if the specified key is not a String. 1063 */ remove(Object key)1064 public String remove(Object key) 1065 { 1066 if (key == null) 1067 throw new 1068 NullPointerException("This map does not support null keys."); 1069 if (!(key instanceof String)) 1070 throw new 1071 ClassCastException("This map only allows queries using Strings."); 1072 return super.remove(key); 1073 } 1074 1075 /** 1076 * Returns a collection view of the values, with the same 1077 * provisions as for the underlying map. 1078 * 1079 * @return a collection containing the values. 1080 */ values()1081 public Collection<String> values() 1082 { 1083 if (values == null) 1084 values = new EnvironmentCollection(super.values()); 1085 return values; 1086 } 1087 1088 } 1089 1090 /** 1091 * This is a specialised <code>Set</code>, providing 1092 * the necessary provisions for the collections used by the 1093 * environment variable map. Namely, it prevents 1094 * modifications and the use of queries with null 1095 * or non-<code>String</code> values. 1096 * 1097 * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 1098 */ 1099 private static class EnvironmentSet 1100 extends EnvironmentCollection 1101 implements Set<String> 1102 { 1103 1104 /** 1105 * Constructs a new environment set, which 1106 * wraps the elements of the supplied set. 1107 * 1108 * @param set the set to use as a base for 1109 * this set. 1110 */ EnvironmentSet(Set<String> set)1111 public EnvironmentSet(Set<String> set) 1112 { 1113 super(set); 1114 } 1115 1116 /** 1117 * This simply calls the same method on the wrapped 1118 * collection. 1119 * 1120 * @param obj the object to compare with. 1121 * @return true if the two objects are equal. 1122 */ equals(Object obj)1123 public boolean equals(Object obj) 1124 { 1125 return c.equals(obj); 1126 } 1127 1128 /** 1129 * This simply calls the same method on the wrapped 1130 * collection. 1131 * 1132 * @return the hashcode of the collection. 1133 */ hashCode()1134 public int hashCode() 1135 { 1136 return c.hashCode(); 1137 } 1138 1139 } // class EnvironmentSet<String> 1140 1141 } // class System 1142