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