summaryrefslogtreecommitdiff
path: root/libjava/java/lang/System.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/lang/System.java')
-rw-r--r--libjava/java/lang/System.java1089
1 files changed, 1089 insertions, 0 deletions
diff --git a/libjava/java/lang/System.java b/libjava/java/lang/System.java
new file mode 100644
index 000000000..ecfad2557
--- /dev/null
+++ b/libjava/java/lang/System.java
@@ -0,0 +1,1089 @@
+/* System.java -- useful methods to interface with the system
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.nio.channels.Channel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.AbstractCollection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Properties;
+import java.util.PropertyPermission;
+
+/**
+ * System represents system-wide resources; things that represent the
+ * general environment. As such, all methods are static.
+ *
+ * @author John Keiser
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @since 1.0
+ * @status still missing 1.4 functionality
+ */
+public final class System
+{
+ // WARNING: System is a CORE class in the bootstrap cycle. See the comments
+ // in vm/reference/java/lang/Runtime for implications of this fact.
+
+ /**
+ * The standard InputStream. This is assigned at startup and starts its
+ * life perfectly valid. Although it is marked final, you can change it
+ * using {@link #setIn(InputStream)} through some hefty VM magic.
+ *
+ * <p>This corresponds to the C stdin and C++ cin variables, which
+ * typically input from the keyboard, but may be used to pipe input from
+ * other processes or files. That should all be transparent to you,
+ * however.
+ */
+ public static final InputStream in
+ = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
+ /**
+ * The standard output PrintStream. This is assigned at startup and
+ * starts its life perfectly valid. Although it is marked final, you can
+ * change it using {@link #setOut(PrintStream)} through some hefty VM magic.
+ *
+ * <p>This corresponds to the C stdout and C++ cout variables, which
+ * typically output normal messages to the screen, but may be used to pipe
+ * output to other processes or files. That should all be transparent to
+ * you, however.
+ */
+ public static final PrintStream out
+ = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)), true);
+ /**
+ * The standard output PrintStream. This is assigned at startup and
+ * starts its life perfectly valid. Although it is marked final, you can
+ * change it using {@link #setErr(PrintStream)} through some hefty VM magic.
+ *
+ * <p>This corresponds to the C stderr and C++ cerr variables, which
+ * typically output error messages to the screen, but may be used to pipe
+ * output to other processes or files. That should all be transparent to
+ * you, however.
+ */
+ public static final PrintStream err
+ = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.err)), true);
+
+ /**
+ * A cached copy of the environment variable map.
+ */
+ private static Map<String,String> environmentMap;
+
+ /**
+ * This class is uninstantiable.
+ */
+ private System()
+ {
+ }
+
+ /**
+ * Set {@link #in} to a new InputStream. This uses some VM magic to change
+ * a "final" variable, so naturally there is a security check,
+ * <code>RuntimePermission("setIO")</code>.
+ *
+ * @param in the new InputStream
+ * @throws SecurityException if permission is denied
+ * @since 1.1
+ */
+ public static void setIn(InputStream in)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setIO"));
+ setIn0(in);
+ }
+
+ /**
+ * Set {@link #out} to a new PrintStream. This uses some VM magic to change
+ * a "final" variable, so naturally there is a security check,
+ * <code>RuntimePermission("setIO")</code>.
+ *
+ * @param out the new PrintStream
+ * @throws SecurityException if permission is denied
+ * @since 1.1
+ */
+ public static void setOut(PrintStream out)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setIO"));
+
+ setOut0(out);
+ }
+
+ /**
+ * Set {@link #err} to a new PrintStream. This uses some VM magic to change
+ * a "final" variable, so naturally there is a security check,
+ * <code>RuntimePermission("setIO")</code>.
+ *
+ * @param err the new PrintStream
+ * @throws SecurityException if permission is denied
+ * @since 1.1
+ */
+ public static void setErr(PrintStream err)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("setIO"));
+ setErr0(err);
+ }
+
+ /**
+ * Set the current SecurityManager. If a security manager already exists,
+ * then <code>RuntimePermission("setSecurityManager")</code> is checked
+ * first. Since this permission is denied by the default security manager,
+ * setting the security manager is often an irreversible action.
+ *
+ * @param sm the new SecurityManager
+ * @throws SecurityException if permission is denied
+ */
+ public static synchronized void setSecurityManager(SecurityManager sm)
+ {
+ // Implementation note: the field lives in SecurityManager because of
+ // bootstrap initialization issues. This method is synchronized so that
+ // no other thread changes it to null before this thread makes the change.
+ if (SecurityManager.current != null)
+ SecurityManager.current.checkPermission
+ (new RuntimePermission("setSecurityManager"));
+ SecurityManager.current = sm;
+ }
+
+ /**
+ * Get the current SecurityManager. If the SecurityManager has not been
+ * set yet, then this method returns null.
+ *
+ * @return the current SecurityManager, or null
+ */
+ public static SecurityManager getSecurityManager()
+ {
+ return SecurityManager.current;
+ }
+
+ /**
+ * Get the current time, measured in the number of milliseconds from the
+ * beginning of Jan. 1, 1970. This is gathered from the system clock, with
+ * any attendant incorrectness (it may be timezone dependent).
+ *
+ * @return the current time
+ * @see java.util.Date
+ */
+ public static native long currentTimeMillis();
+
+ /**
+ * Get the current time, measured in nanoseconds. The result is as
+ * precise as possible, and is measured against a fixed epoch.
+ * However, unlike currentTimeMillis(), the epoch chosen is
+ * arbitrary and may vary by platform, etc.
+ * @since 1.5
+ */
+ public static native long nanoTime();
+
+ /**
+ * Copy one array onto another from <code>src[srcStart]</code> ...
+ * <code>src[srcStart+len-1]</code> to <code>dest[destStart]</code> ...
+ * <code>dest[destStart+len-1]</code>. First, the arguments are validated:
+ * neither array may be null, they must be of compatible types, and the
+ * start and length must fit within both arrays. Then the copying starts,
+ * and proceeds through increasing slots. If src and dest are the same
+ * array, this will appear to copy the data to a temporary location first.
+ * An ArrayStoreException in the middle of copying will leave earlier
+ * elements copied, but later elements unchanged.
+ *
+ * @param src the array to copy elements from
+ * @param srcStart the starting position in src
+ * @param dest the array to copy elements to
+ * @param destStart the starting position in dest
+ * @param len the number of elements to copy
+ * @throws NullPointerException if src or dest is null
+ * @throws ArrayStoreException if src or dest is not an array, if they are
+ * not compatible array types, or if an incompatible runtime type
+ * is stored in dest
+ * @throws IndexOutOfBoundsException if len is negative, or if the start or
+ * end copy position in either array is out of bounds
+ */
+ public static native void arraycopy(Object src, int srcStart,
+ Object dest, int destStart, int len);
+
+ /**
+ * Get a hash code computed by the VM for the Object. This hash code will
+ * be the same as Object's hashCode() method. It is usually some
+ * convolution of the pointer to the Object internal to the VM. It
+ * follows standard hash code rules, in that it will remain the same for a
+ * given Object for the lifetime of that Object.
+ *
+ * @param o the Object to get the hash code for
+ * @return the VM-dependent hash code for this Object
+ * @since 1.1
+ */
+ public static native int identityHashCode(Object o);
+
+ /**
+ * Get all the system properties at once. A security check may be performed,
+ * <code>checkPropertiesAccess</code>. Note that a security manager may
+ * allow getting a single property, but not the entire group.
+ *
+ * <p>The required properties include:
+ * <dl>
+ * <dt>java.version</dt> <dd>Java version number</dd>
+ * <dt>java.vendor</dt> <dd>Java vendor specific string</dd>
+ * <dt>java.vendor.url</dt> <dd>Java vendor URL</dd>
+ * <dt>java.home</dt> <dd>Java installation directory</dd>
+ * <dt>java.vm.specification.version</dt> <dd>VM Spec version</dd>
+ * <dt>java.vm.specification.vendor</dt> <dd>VM Spec vendor</dd>
+ * <dt>java.vm.specification.name</dt> <dd>VM Spec name</dd>
+ * <dt>java.vm.version</dt> <dd>VM implementation version</dd>
+ * <dt>java.vm.vendor</dt> <dd>VM implementation vendor</dd>
+ * <dt>java.vm.name</dt> <dd>VM implementation name</dd>
+ * <dt>java.specification.version</dt> <dd>Java Runtime Environment version</dd>
+ * <dt>java.specification.vendor</dt> <dd>Java Runtime Environment vendor</dd>
+ * <dt>java.specification.name</dt> <dd>Java Runtime Environment name</dd>
+ * <dt>java.class.version</dt> <dd>Java class version number</dd>
+ * <dt>java.class.path</dt> <dd>Java classpath</dd>
+ * <dt>java.library.path</dt> <dd>Path for finding Java libraries</dd>
+ * <dt>java.io.tmpdir</dt> <dd>Default temp file path</dd>
+ * <dt>java.compiler</dt> <dd>Name of JIT to use</dd>
+ * <dt>java.ext.dirs</dt> <dd>Java extension path</dd>
+ * <dt>os.name</dt> <dd>Operating System Name</dd>
+ * <dt>os.arch</dt> <dd>Operating System Architecture</dd>
+ * <dt>os.version</dt> <dd>Operating System Version</dd>
+ * <dt>file.separator</dt> <dd>File separator ("/" on Unix)</dd>
+ * <dt>path.separator</dt> <dd>Path separator (":" on Unix)</dd>
+ * <dt>line.separator</dt> <dd>Line separator ("\n" on Unix)</dd>
+ * <dt>user.name</dt> <dd>User account name</dd>
+ * <dt>user.home</dt> <dd>User home directory</dd>
+ * <dt>user.dir</dt> <dd>User's current working directory</dd>
+ * </dl>
+ *
+ * In addition, gnu defines several other properties, where ? stands for
+ * each character in '0' through '9':
+ * <dl>
+ * <dt>gnu.classpath.home</dt> <dd>Path to the classpath libraries.</dd>
+ * <dt>gnu.classpath.version</dt> <dd>Version of the classpath libraries.</dd>
+ * <dt>gnu.classpath.vm.shortname</dt> <dd>Succinct version of the VM name;
+ * used for finding property files in file system</dd>
+ * <dt>gnu.classpath.home.url</dt> <dd> Base URL; used for finding
+ * property files in file system</dd>
+ * <dt>gnu.cpu.endian</dt> <dd>big or little</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.ISO-8859-?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.iso-8859-?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.iso8859_?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.iso-latin-_?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.latin?</dt> <dd>8859_?</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.UTF-8</dt> <dd>UTF8</dd>
+ * <dt>gnu.java.io.encoding_scheme_alias.utf-8</dt> <dd>UTF8</dd>
+ * <dt>gnu.java.util.zoneinfo.dir</dt> <dd>Root of zoneinfo tree</dd>
+ * </dl>
+ *
+ * @return the system properties, will never be null
+ * @throws SecurityException if permission is denied
+ */
+ public static Properties getProperties()
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertiesAccess();
+ return SystemProperties.getProperties();
+ }
+
+ /**
+ * Set all the system properties at once. A security check may be performed,
+ * <code>checkPropertiesAccess</code>. Note that a security manager may
+ * allow setting a single property, but not the entire group. An argument
+ * of null resets the properties to the startup default.
+ *
+ * @param properties the new set of system properties
+ * @throws SecurityException if permission is denied
+ */
+ public static void setProperties(Properties properties)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertiesAccess();
+ SystemProperties.setProperties(properties);
+ }
+
+ /**
+ * Get a single system property by name. A security check may be performed,
+ * <code>checkPropertyAccess(key)</code>.
+ *
+ * @param key the name of the system property to get
+ * @return the property, or null if not found
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ */
+ public static String getProperty(String key)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertyAccess(key);
+ else if (key.length() == 0)
+ throw new IllegalArgumentException("key can't be empty");
+ return SystemProperties.getProperty(key);
+ }
+
+ /**
+ * Get a single system property by name. A security check may be performed,
+ * <code>checkPropertyAccess(key)</code>.
+ *
+ * @param key the name of the system property to get
+ * @param def the default
+ * @return the property, or def if not found
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ */
+ public static String getProperty(String key, String def)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPropertyAccess(key);
+ return SystemProperties.getProperty(key, def);
+ }
+
+ /**
+ * Set a single system property by name. A security check may be performed,
+ * <code>checkPropertyAccess(key, "write")</code>.
+ *
+ * @param key the name of the system property to set
+ * @param value the new value
+ * @return the previous value, or null
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ * @since 1.2
+ */
+ public static String setProperty(String key, String value)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(key, "write"));
+ return SystemProperties.setProperty(key, value);
+ }
+
+ /**
+ * Remove a single system property by name. A security check may be
+ * performed, <code>checkPropertyAccess(key, "write")</code>.
+ *
+ * @param key the name of the system property to remove
+ * @return the previous value, or null
+ * @throws SecurityException if permission is denied
+ * @throws NullPointerException if key is null
+ * @throws IllegalArgumentException if key is ""
+ * @since 1.5
+ */
+ public static String clearProperty(String key)
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission(key, "write"));
+ // This handles both the null pointer exception and the illegal
+ // argument exception.
+ if (key.length() == 0)
+ throw new IllegalArgumentException("key can't be empty");
+ return SystemProperties.remove(key);
+ }
+
+ /**
+ * Gets the value of an environment variable.
+ *
+ * @param name the name of the environment variable
+ * @return the string value of the variable or null when the
+ * environment variable is not defined.
+ * @throws NullPointerException
+ * @throws SecurityException if permission is denied
+ * @since 1.5
+ * @specnote This method was deprecated in some JDK releases, but
+ * was restored in 1.5.
+ */
+ public static String getenv(String name)
+ {
+ if (name == null)
+ throw new NullPointerException();
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("getenv." + name));
+ return getenv0(name);
+ }
+
+ /**
+ * <p>
+ * Returns an unmodifiable view of the system environment variables.
+ * If the underlying system does not support environment variables,
+ * an empty map is returned.
+ * </p>
+ * <p>
+ * The returned map is read-only and does not accept queries using
+ * null keys or values, or those of a type other than <code>String</code>.
+ * Attempts to modify the map will throw an
+ * <code>UnsupportedOperationException</code>, while attempts
+ * to pass in a null value will throw a
+ * <code>NullPointerException</code>. Types other than <code>String</code>
+ * throw a <code>ClassCastException</code>.
+ * </p>
+ * <p>
+ * As the returned map is generated using data from the underlying
+ * platform, it may not comply with the <code>equals()</code>
+ * and <code>hashCode()</code> contracts. It is also likely that
+ * the keys of this map will be case-sensitive.
+ * </p>
+ * <p>
+ * Use of this method may require a security check for the
+ * RuntimePermission "getenv.*".
+ * </p>
+ *
+ * @return a map of the system environment variables.
+ * @throws SecurityException if the checkPermission method of
+ * an installed security manager prevents access to
+ * the system environment variables.
+ * @since 1.5
+ */
+ public static Map<String, String> getenv()
+ {
+ SecurityManager sm = SecurityManager.current; // Be thread-safe.
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("getenv.*"));
+ if (environmentMap == null)
+ {
+ // List<String> environ = (List<String>)VMSystem.environ();
+ // FIXME
+ List<String> environ = new ArrayList<String>();
+ Map<String,String> variables = new EnvironmentMap();
+ for (String pair : environ)
+ {
+ String[] parts = pair.split("=");
+ variables.put(parts[0], parts[1]);
+ }
+ environmentMap = Collections.unmodifiableMap(variables);
+ }
+ return environmentMap;
+ }
+
+ /**
+ * Terminate the Virtual Machine. This just calls
+ * <code>Runtime.getRuntime().exit(status)</code>, and never returns.
+ * Obviously, a security check is in order, <code>checkExit</code>.
+ *
+ * @param status the exit status; by convention non-zero is abnormal
+ * @throws SecurityException if permission is denied
+ * @see Runtime#exit(int)
+ */
+ public static void exit(int status)
+ {
+ Runtime.getRuntime().exit(status);
+ }
+
+ /**
+ * Calls the garbage collector. This is only a hint, and it is up to the
+ * implementation what this hint suggests, but it usually causes a
+ * best-effort attempt to reclaim unused memory from discarded objects.
+ * This calls <code>Runtime.getRuntime().gc()</code>.
+ *
+ * @see Runtime#gc()
+ */
+ public static void gc()
+ {
+ Runtime.getRuntime().gc();
+ }
+
+ /**
+ * Runs object finalization on pending objects. This is only a hint, and
+ * it is up to the implementation what this hint suggests, but it usually
+ * causes a best-effort attempt to run finalizers on all objects ready
+ * to be reclaimed. This calls
+ * <code>Runtime.getRuntime().runFinalization()</code>.
+ *
+ * @see Runtime#runFinalization()
+ */
+ public static void runFinalization()
+ {
+ Runtime.getRuntime().runFinalization();
+ }
+
+ /**
+ * Tell the Runtime whether to run finalization before exiting the
+ * JVM. This is inherently unsafe in multi-threaded applications,
+ * since it can force initialization on objects which are still in use
+ * by live threads, leading to deadlock; therefore this is disabled by
+ * default. There may be a security check, <code>checkExit(0)</code>. This
+ * calls <code>Runtime.getRuntime().runFinalizersOnExit()</code>.
+ *
+ * @param finalizeOnExit whether to run finalizers on exit
+ * @throws SecurityException if permission is denied
+ * @see Runtime#runFinalizersOnExit()
+ * @since 1.1
+ * @deprecated never rely on finalizers to do a clean, thread-safe,
+ * mop-up from your code
+ */
+ public static void runFinalizersOnExit(boolean finalizeOnExit)
+ {
+ Runtime.getRuntime().runFinalizersOnExit(finalizeOnExit);
+ }
+
+ /**
+ * Load a code file using its explicit system-dependent filename. A security
+ * check may be performed, <code>checkLink</code>. This just calls
+ * <code>Runtime.getRuntime().load(filename)</code>.
+ *
+ * <p>
+ * The library is loaded using the class loader associated with the
+ * class associated with the invoking method.
+ *
+ * @param filename the code file to load
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the file cannot be loaded
+ * @see Runtime#load(String)
+ */
+ public static void load(String filename)
+ {
+ Runtime.getRuntime().load(filename);
+ }
+
+ /**
+ * Load a library using its explicit system-dependent filename. A security
+ * check may be performed, <code>checkLink</code>. This just calls
+ * <code>Runtime.getRuntime().load(filename)</code>.
+ *
+ * <p>
+ * The library is loaded using the class loader associated with the
+ * class associated with the invoking method.
+ *
+ * @param libname the library file to load
+ * @throws SecurityException if permission is denied
+ * @throws UnsatisfiedLinkError if the file cannot be loaded
+ * @see Runtime#load(String)
+ */
+ public static void loadLibrary(String libname)
+ {
+ Runtime.getRuntime().loadLibrary(libname);
+ }
+
+ /**
+ * Convert a library name to its platform-specific variant.
+ *
+ * @param libname the library name, as used in <code>loadLibrary</code>
+ * @return the platform-specific mangling of the name
+ * @since 1.2
+ */
+ public static String mapLibraryName(String libname)
+ {
+ // XXX Fix this!!!!
+ return Runtime.nativeGetLibname("", libname);
+ }
+
+ /**
+ * Set {@link #in} to a new InputStream.
+ *
+ * @param in the new InputStream
+ * @see #setIn(InputStream)
+ */
+ private static native void setIn0(InputStream in);
+
+ /**
+ * Set {@link #out} to a new PrintStream.
+ *
+ * @param out the new PrintStream
+ * @see #setOut(PrintStream)
+ */
+ private static native void setOut0(PrintStream out);
+
+ /**
+ * Set {@link #err} to a new PrintStream.
+ *
+ * @param err the new PrintStream
+ * @see #setErr(PrintStream)
+ */
+ private static native void setErr0(PrintStream err);
+
+ /**
+ * Gets the value of an environment variable.
+ *
+ * @see #getenv(String)
+ */
+ static native String getenv0(String name);
+
+ /**
+ * Returns the inherited channel of the VM.
+ *
+ * This wraps the inheritedChannel() call of the system's default
+ * {@link SelectorProvider}.
+ *
+ * @return the inherited channel of the VM
+ *
+ * @throws IOException If an I/O error occurs
+ * @throws SecurityException If an installed security manager denies access
+ * to RuntimePermission("inheritedChannel")
+ *
+ * @since 1.5
+ */
+ public static Channel inheritedChannel()
+ throws IOException
+ {
+ return SelectorProvider.provider().inheritedChannel();
+ }
+
+ /**
+ * This is a specialised <code>Collection</code>, providing
+ * the necessary provisions for the collections used by the
+ * environment variable map. Namely, it prevents
+ * querying anything but <code>String</code>s.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class EnvironmentCollection
+ extends AbstractCollection<String>
+ {
+
+ /**
+ * The wrapped collection.
+ */
+ protected Collection<String> c;
+
+ /**
+ * Constructs a new environment collection, which
+ * wraps the elements of the supplied collection.
+ *
+ * @param coll the collection to use as a base for
+ * this collection.
+ */
+ public EnvironmentCollection(Collection<String> coll)
+ {
+ c = coll;
+ }
+
+ /**
+ * Blocks queries containing a null object or an object which
+ * isn't of type <code>String</code>. All other queries
+ * are forwarded to the underlying collection.
+ *
+ * @param obj the object to look for.
+ * @return true if the object exists in the collection.
+ * @throws NullPointerException if the specified object is null.
+ * @throws ClassCastException if the specified object is not a String.
+ */
+ public boolean contains(Object obj)
+ {
+ if (obj == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(obj instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ return c.contains(obj);
+ }
+
+ /**
+ * Blocks queries where the collection contains a null object or
+ * an object which isn't of type <code>String</code>. All other
+ * queries are forwarded to the underlying collection.
+ *
+ * @param coll the collection of objects to look for.
+ * @return true if the collection contains all elements in the collection.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean containsAll(Collection<?> coll)
+ {
+ for (Object o: coll)
+ {
+ if (o == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(o instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ }
+ return c.containsAll(coll);
+ }
+
+ /**
+ * This returns an iterator over the map elements, with the
+ * same provisions as for the collection and underlying map.
+ *
+ * @return an iterator over the map elements.
+ */
+ public Iterator<String> iterator()
+ {
+ return c.iterator();
+ }
+
+ /**
+ * Blocks the removal of elements from the collection.
+ *
+ * @return true if the removal was sucessful.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean remove(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ return c.contains(key);
+ }
+
+ /**
+ * Blocks the removal of all elements in the specified
+ * collection from the collection.
+ *
+ * @param coll the collection of elements to remove.
+ * @return true if the elements were removed.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean removeAll(Collection<?> coll)
+ {
+ for (Object o: coll)
+ {
+ if (o == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(o instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ }
+ return c.removeAll(coll);
+ }
+
+ /**
+ * Blocks the retention of all elements in the specified
+ * collection from the collection.
+ *
+ * @param c the collection of elements to retain.
+ * @return true if the other elements were removed.
+ * @throws NullPointerException if the collection is null.
+ * @throws NullPointerException if any collection entry is null.
+ * @throws ClassCastException if any collection entry is not a String.
+ */
+ public boolean retainAll(Collection<?> coll)
+ {
+ for (Object o: coll)
+ {
+ if (o == null)
+ throw new
+ NullPointerException("This collection does not support " +
+ "null values.");
+ if (!(o instanceof String))
+ throw new
+ ClassCastException("This collection only supports Strings.");
+ }
+ return c.containsAll(coll);
+ }
+
+ /**
+ * This simply calls the same method on the wrapped
+ * collection.
+ *
+ * @return the size of the underlying collection.
+ */
+ public int size()
+ {
+ return c.size();
+ }
+
+ } // class EnvironmentCollection<String>
+
+ /**
+ * This is a specialised <code>HashMap</code>, which
+ * prevents the addition or querying of anything other than
+ * <code>String</code> objects.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ static class EnvironmentMap
+ extends HashMap<String,String>
+ {
+
+ /**
+ * Cache the entry set.
+ */
+ private transient Set<Map.Entry<String,String>> entries;
+
+ /**
+ * Cache the key set.
+ */
+ private transient Set<String> keys;
+
+ /**
+ * Cache the value collection.
+ */
+ private transient Collection<String> values;
+
+ /**
+ * Constructs a new empty <code>EnvironmentMap</code>.
+ */
+ EnvironmentMap()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>EnvironmentMap</code> containing
+ * the contents of the specified map.
+ *
+ * @param m the map to be added to this.
+ * @throws NullPointerException if a key or value is null.
+ * @throws ClassCastException if a key or value is not a String.
+ */
+ EnvironmentMap(Map<String,String> m)
+ {
+ super(m);
+ }
+
+ /**
+ * Blocks queries containing a null key or one which is not
+ * of type <code>String</code>. All other queries
+ * are forwarded to the superclass.
+ *
+ * @param key the key to look for in the map.
+ * @return true if the key exists in the map.
+ * @throws NullPointerException if the specified key is null.
+ */
+ public boolean containsKey(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This map does not support null keys.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.containsKey(key);
+ }
+
+ /**
+ * Blocks queries using a null or non-<code>String</code> value.
+ * All other queries are forwarded to the superclass.
+ *
+ * @param value the value to look for in the map.
+ * @return true if the value exists in the map.
+ * @throws NullPointerException if the specified value is null.
+ */
+ public boolean containsValue(Object value)
+ {
+ if (value == null)
+ throw new
+ NullPointerException("This map does not support null values.");
+ if (!(value instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.containsValue(value);
+ }
+
+ /**
+ * Returns a set view of the map entries, with the same
+ * provisions as for the underlying map.
+ *
+ * @return a set containing the map entries.
+ */
+ public Set<Map.Entry<String,String>> entrySet()
+ {
+ if (entries == null)
+ entries = super.entrySet();
+ return entries;
+ }
+
+ /**
+ * Blocks queries containing a null or non-<code>String</code> key.
+ * All other queries are passed on to the superclass.
+ *
+ * @param key the key to retrieve the value for.
+ * @return the value associated with the given key.
+ * @throws NullPointerException if the specified key is null.
+ * @throws ClassCastException if the specified key is not a String.
+ */
+ public String get(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This map does not support null keys.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.get(key);
+ }
+
+ /**
+ * Returns a set view of the keys, with the same
+ * provisions as for the underlying map.
+ *
+ * @return a set containing the keys.
+ */
+ public Set<String> keySet()
+ {
+ if (keys == null)
+ keys = new EnvironmentSet(super.keySet());
+ return keys;
+ }
+
+ /**
+ * Associates the given key to the given value. If the
+ * map already contains the key, its value is replaced.
+ * The map does not accept null keys or values, or keys
+ * and values not of type {@link String}.
+ *
+ * @param key the key to map.
+ * @param value the value to be mapped.
+ * @return the previous value of the key, or null if there was no mapping
+ * @throws NullPointerException if a key or value is null.
+ * @throws ClassCastException if a key or value is not a String.
+ */
+ public String put(String key, String value)
+ {
+ if (key == null)
+ throw new NullPointerException("A new key is null.");
+ if (value == null)
+ throw new NullPointerException("A new value is null.");
+ if (!(key instanceof String))
+ throw new ClassCastException("A new key is not a String.");
+ if (!(value instanceof String))
+ throw new ClassCastException("A new value is not a String.");
+ return super.put(key, value);
+ }
+
+ /**
+ * Removes a key-value pair from the map. The queried key may not
+ * be null or of a type other than a <code>String</code>.
+ *
+ * @param key the key of the entry to remove.
+ * @return the removed value.
+ * @throws NullPointerException if the specified key is null.
+ * @throws ClassCastException if the specified key is not a String.
+ */
+ public String remove(Object key)
+ {
+ if (key == null)
+ throw new
+ NullPointerException("This map does not support null keys.");
+ if (!(key instanceof String))
+ throw new
+ ClassCastException("This map only allows queries using Strings.");
+ return super.remove(key);
+ }
+
+ /**
+ * Returns a collection view of the values, with the same
+ * provisions as for the underlying map.
+ *
+ * @return a collection containing the values.
+ */
+ public Collection<String> values()
+ {
+ if (values == null)
+ values = new EnvironmentCollection(super.values());
+ return values;
+ }
+
+ }
+
+ /**
+ * This is a specialised <code>Set</code>, providing
+ * the necessary provisions for the collections used by the
+ * environment variable map. Namely, it prevents
+ * modifications and the use of queries with null
+ * or non-<code>String</code> values.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ */
+ private static class EnvironmentSet
+ extends EnvironmentCollection
+ implements Set<String>
+ {
+
+ /**
+ * Constructs a new environment set, which
+ * wraps the elements of the supplied set.
+ *
+ * @param set the set to use as a base for
+ * this set.
+ */
+ public EnvironmentSet(Set<String> set)
+ {
+ super(set);
+ }
+
+ /**
+ * This simply calls the same method on the wrapped
+ * collection.
+ *
+ * @param obj the object to compare with.
+ * @return true if the two objects are equal.
+ */
+ public boolean equals(Object obj)
+ {
+ return c.equals(obj);
+ }
+
+ /**
+ * This simply calls the same method on the wrapped
+ * collection.
+ *
+ * @return the hashcode of the collection.
+ */
+ public int hashCode()
+ {
+ return c.hashCode();
+ }
+
+ } // class EnvironmentSet<String>
+
+} // class System