/* System.java -- useful methods to interface with the system
   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2012
   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 gnu.classpath.VMStackWalker;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.Console;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import java.util.AbstractCollection;
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 = VMSystem.makeStandardInputStream();

  /**
   * 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 = VMSystem.makeStandardOutputStream();

  private static final String LINE_SEPARATOR = SystemProperties.getProperty("line.separator");

  /**
   * 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 = VMSystem.makeStandardErrorStream();

  /**
   * 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"));

    VMSystem.setIn(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"));
    VMSystem.setOut(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"));
    VMSystem.setErr(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.
   *
   * <STRONG>Spec Note:</STRONG> Don't ask me, I didn't write it.  It looks
   * pretty vulnerable; whoever gets to the gate first gets to set the policy.
   * There is probably some way to set the original security manager as a
   * command line argument to the VM, but I don't know it.
   *
   * @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"));

    // java.security.Security's class initialiser loads and parses the
    // policy files.  If it hasn't been run already it will be run
    // during the first permission check.  That initialisation will
    // fail if a very restrictive security manager is in force, so we
    // preload it here.
    if (SecurityManager.current == null)
      {
        try
          {
            Class.forName("java.security.Security");
          }
        catch (ClassNotFoundException e)
          {
          }
      }

    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 long currentTimeMillis()
  {
    return VMSystem.currentTimeMillis();
  }

  /**
   * <p>
   * Returns the current value of a nanosecond-precise system timer.
   * The value of the timer is an offset relative to some arbitrary fixed
   * time, which may be in the future (making the value negative).  This
   * method is useful for timing events where nanosecond precision is
   * required.  This is achieved by calling this method before and after the
   * event, and taking the difference betweent the two times:
   * </p>
   * <p>
   * <code>long startTime = System.nanoTime();</code><br />
   * <code>... <emph>event code</emph> ...</code><br />
   * <code>long endTime = System.nanoTime();</code><br />
   * <code>long duration = endTime - startTime;</code><br />
   * </p>
   * <p>
   * Note that the value is only nanosecond-precise, and not accurate; there
   * is no guarantee that the difference between two values is really a
   * nanosecond.  Also, the value is prone to overflow if the offset
   * exceeds 2^63.
   * </p>
   *
   * @return the time of a system timer in nanoseconds.
   * @since 1.5
   */
  public static long nanoTime()
  {
    return VMSystem.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 void arraycopy(Object src, int srcStart,
                               Object dest, int destStart, int len)
  {
    VMSystem.arraycopy(src, srcStart, dest, destStart, 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 int identityHashCode(Object o)
  {
    return VMSystem.identityHashCode(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.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.util.zoneinfo.dir</dt>        <dd>Root of zoneinfo tree</dd>
   * <dt>gnu.javax.print.server</dt>     <dd>Hostname of external CUPS server.</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);
    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);
    // 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.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"));
    // 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.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 VMSystem.getenv(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)
      {
        Map<String,String> variables = new EnvironmentMap();
        List<String> environ = (List<String>)VMSystem.environ();
        for (String envEntry : environ)
          {
            // avoid broken and null entries
            if (envEntry != null && !envEntry.endsWith("="))
              {
                // it's perfectly legal that some entries may be in the form
                // key=value=value=value
                int equalSignIndex = envEntry.indexOf('=');
                String key = envEntry.substring(0, equalSignIndex);
                String value = envEntry.substring(equalSignIndex + 1);
                variables.put(key, value);
              }
          }

        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.runFinalizersOnExit()</code>.
   *
   * @param finalizeOnExit whether to run finalizers on exit
   * @throws SecurityException if permission is denied
   * @see Runtime#runFinalizersOnExit(boolean)
   * @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.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, VMStackWalker.getCallingClassLoader());
  }

  /**
   * 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,
      VMStackWalker.getCallingClassLoader());
  }

  /**
   * 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)
  {
    return VMRuntime.mapLibraryName(libname);
  }

  /**
   * 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();
  }

  /*
   * @since 1.6
   */
  public static Console console()
  {
    return Console.console();
  }

  /**
   * Returns the system-dependent line separator.
   *
   * @return the system-dependent line separator.
   */
  public static String lineSeparator()
  {
    return LINE_SEPARATOR;
  }

  /**
   * 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 coll 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
