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