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

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.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();

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

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