System.java revision ccbe3404e0691dab506d017550658e8e5974c83e
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/*
18 * Copyright (C) 2008 The Android Open Source Project
19 *
20 * Licensed under the Apache License, Version 2.0 (the "License");
21 * you may not use this file except in compliance with the License.
22 * You may obtain a copy of the License at
23 *
24 *      http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33package java.lang;
34
35import java.io.Console;
36import java.io.FileDescriptor;
37import java.io.FileInputStream;
38import java.io.FileOutputStream;
39import java.io.IOException;
40import java.io.InputStream;
41import java.io.PrintStream;
42import java.nio.channels.Channel;
43import java.nio.channels.spi.SelectorProvider;
44import java.security.SecurityPermission;
45import java.util.Collection;
46import java.util.HashMap;
47import java.util.Map;
48import java.util.Properties;
49import java.util.PropertyPermission;
50import java.util.Set;
51
52import dalvik.system.VMStack;
53
54/**
55 * Provides access to system-related information and resources including
56 * standard input and output. Enables clients to dynamically load native
57 * libraries. All methods of this class are accessed in a static way and the
58 * class itself can not be instantiated.
59 *
60 * @see Runtime
61 */
62public final class System {
63
64    /**
65     * Default input stream.
66     */
67    public static final InputStream in;
68
69    /**
70     * Default output stream.
71     */
72    public static final PrintStream out;
73
74    /**
75     * Default error output stream.
76     */
77    public static final PrintStream err;
78
79    /**
80     * The System Properties table.
81     */
82    private static Properties systemProperties;
83
84    /**
85     * Initialize all the slots in System on first use.
86     */
87    static {
88        /*
89         * Set up standard in, out, and err. TODO err and out are
90         * String.ConsolePrintStream. All three are buffered in Harmony. Check
91         * and possibly change this later.
92         */
93        err = new PrintStream(new FileOutputStream(FileDescriptor.err));
94        out = new PrintStream(new FileOutputStream(FileDescriptor.out));
95        in = new FileInputStream(FileDescriptor.in);
96    }
97
98    /**
99     * Sets the standard input stream to the given user defined input stream.
100     *
101     * @param newIn
102     *            the user defined input stream to set as the standard input
103     *            stream.
104     * @throws SecurityException
105     *             if a {@link SecurityManager} is installed and its {@code
106     *             checkPermission()} method does not allow the change of the
107     *             stream.
108     */
109    public static void setIn(InputStream newIn) {
110        SecurityManager secMgr = System.getSecurityManager();
111        if(secMgr != null) {
112            secMgr.checkPermission(RuntimePermission.permissionToSetIO);
113        }
114        setFieldImpl("in", "Ljava/io/InputStream;", newIn);
115    }
116
117    /**
118     * Sets the standard output stream to the given user defined output stream.
119     *
120     * @param newOut
121     *            the user defined output stream to set as the standard output
122     *            stream.
123     * @throws SecurityException
124     *             if a {@link SecurityManager} is installed and its {@code
125     *             checkPermission()} method does not allow the change of the
126     *             stream.
127     */
128    public static void setOut(java.io.PrintStream newOut) {
129        SecurityManager secMgr = System.getSecurityManager();
130        if(secMgr != null) {
131            secMgr.checkPermission(RuntimePermission.permissionToSetIO);
132        }
133        setFieldImpl("out", "Ljava/io/PrintStream;", newOut);
134    }
135
136    /**
137     * Sets the standard error output stream to the given user defined output
138     * stream.
139     *
140     * @param newErr
141     *            the user defined output stream to set as the standard error
142     *            output stream.
143     * @throws SecurityException
144     *             if a {@link SecurityManager} is installed and its {@code
145     *             checkPermission()} method does not allow the change of the
146     *             stream.
147     */
148    public static void setErr(java.io.PrintStream newErr) {
149        SecurityManager secMgr = System.getSecurityManager();
150        if(secMgr != null) {
151            secMgr.checkPermission(RuntimePermission.permissionToSetIO);
152        }
153        setFieldImpl("err", "Ljava/io/PrintStream;", newErr);
154    }
155
156    /**
157     * Prevents this class from being instantiated.
158     */
159    private System() {
160    }
161
162    /**
163     * Copies {@code length} elements from the array {@code src},
164     * starting at offset {@code srcPos}, into the array {@code dst},
165     * starting at offset {@code dstPos}.
166     *
167     * @param src
168     *            the source array to copy the content.
169     * @param srcPos
170     *            the starting index of the content in {@code src}.
171     * @param dst
172     *            the destination array to copy the data into.
173     * @param dstPos
174     *            the starting index for the copied content in {@code dst}.
175     * @param length
176     *            the number of elements to be copied.
177     */
178    public static native void arraycopy(Object src, int srcPos, Object dst, int dstPos, int length);
179
180    /**
181     * Returns the current system time in milliseconds since January 1, 1970
182     * 00:00:00 UTC. This method shouldn't be used for measuring timeouts or
183     * other elapsed time measurements, as changing the system time can affect
184     * the results.
185     *
186     * @return the local system time in milliseconds.
187     */
188    public static native long currentTimeMillis();
189
190    /**
191     * Returns the current timestamp of the most precise timer available on the
192     * local system. This timestamp can only be used to measure an elapsed
193     * period by comparing it against another timestamp. It cannot be used as a
194     * very exact system time expression.
195     *
196     * @return the current timestamp in nanoseconds.
197     */
198    public static native long nanoTime();
199
200    /**
201     * Causes the virtual machine to stop running and the program to exit. If
202     * {@link #runFinalizersOnExit(boolean)} has been previously invoked with a
203     * {@code true} argument, then all objects will be properly
204     * garbage-collected and finalized first.
205     *
206     * @param code
207     *            the return code.
208     * @throws SecurityException
209     *             if the running thread has not enough permission to exit the
210     *             virtual machine.
211     * @see SecurityManager#checkExit
212     */
213    public static void exit(int code) {
214        Runtime.getRuntime().exit(code);
215    }
216
217    /**
218     * Indicates to the virtual machine that it would be a good time to run the
219     * garbage collector. Note that this is a hint only. There is no guarantee
220     * that the garbage collector will actually be run.
221     */
222    public static void gc() {
223        Runtime.getRuntime().gc();
224    }
225
226    /**
227     * Returns the value of the environment variable with the given name {@code
228     * var}.
229     *
230     * @param name
231     *            the name of the environment variable.
232     * @return the value of the specified environment variable or {@code null}
233     *         if no variable exists with the given name.
234     * @throws SecurityException
235     *             if a {@link SecurityManager} is installed and its {@code
236     *             checkPermission()} method does not allow the querying of
237     *             single environment variables.
238     */
239    public static String getenv(String name) {
240        if (name == null) {
241            throw new NullPointerException();
242        }
243        SecurityManager secMgr = System.getSecurityManager();
244        if (secMgr != null) {
245            secMgr.checkPermission(new RuntimePermission("getenv." + name));
246        }
247
248        return getEnvByName(name);
249    }
250
251    /*
252     * Returns an environment variable. No security checks are performed.
253     * @param var the name of the environment variable
254     * @return the value of the specified environment variable
255     */
256    private static native String getEnvByName(String name);
257
258    /**
259     * Returns an unmodifiable map of all available environment variables.
260     *
261     * @return the map representing all environment variables.
262     * @throws SecurityException
263     *             if a {@link SecurityManager} is installed and its {@code
264     *             checkPermission()} method does not allow the querying of
265     *             all environment variables.
266     */
267    public static Map<String, String> getenv() {
268        SecurityManager secMgr = System.getSecurityManager();
269        if (secMgr != null) {
270            secMgr.checkPermission(new RuntimePermission("getenv.*"));
271        }
272
273        Map<String, String> map = new HashMap<String, String>();
274
275        int index = 0;
276        String entry = getEnvByIndex(index++);
277        while (entry != null) {
278            int pos = entry.indexOf('=');
279            if (pos != -1) {
280                map.put(entry.substring(0, pos), entry.substring(pos + 1));
281            }
282
283            entry = getEnvByIndex(index++);
284        }
285
286        return new SystemEnvironment(map);
287    }
288
289    /*
290     * Returns an environment variable. No security checks are performed. The
291     * safe way of traversing the environment is to start at index zero and
292     * count upwards until a null pointer is encountered. This marks the end of
293     * the Unix environment.
294     * @param index the index of the environment variable
295     * @return the value of the specified environment variable
296     */
297    private static native String getEnvByIndex(int index);
298
299    /**
300     * Returns the inherited channel from the creator of the current virtual
301     * machine.
302     *
303     * @return the inherited {@link Channel} or {@code null} if none exists.
304     * @throws IOException
305     *             if an I/O error occurred.
306     * @see SelectorProvider
307     * @see SelectorProvider#inheritedChannel()
308     */
309    public static Channel inheritedChannel() throws IOException {
310        return SelectorProvider.provider().inheritedChannel();
311    }
312
313    /**
314     * Returns the system properties. Note that this is not a copy, so that
315     * changes made to the returned Properties object will be reflected in
316     * subsequent calls to getProperty and getProperties.
317     *
318     * @return the system properties.
319     * @throws SecurityException
320     *             if a {@link SecurityManager} is installed and its {@code
321     *             checkPropertiesAccess()} method does not allow the operation.
322     */
323    public static Properties getProperties() {
324        SecurityManager secMgr = System.getSecurityManager();
325        if (secMgr != null) {
326            secMgr.checkPropertiesAccess();
327        }
328
329        return internalGetProperties();
330    }
331
332    /**
333     * Returns the system properties without any security checks. This is used
334     * for access from within java.lang.
335     *
336     * @return the system properties
337     */
338    static Properties internalGetProperties() {
339        if (System.systemProperties == null) {
340            SystemProperties props = new SystemProperties();
341            props.preInit();
342            props.postInit();
343            System.systemProperties = props;
344        }
345
346        return systemProperties;
347    }
348
349    /**
350     * Returns the value of a particular system property or {@code null} if no
351     * such property exists.
352     * <p>
353     * The properties currently provided by the virtual machine are:
354     *
355     * <pre>
356     *        java.vendor.url
357     *        java.class.path
358     *        user.home
359     *        java.class.version
360     *        os.version
361     *        java.vendor
362     *        user.dir
363     *        user.timezone
364     *        path.separator
365     *        os.name
366     *        os.arch
367     *        line.separator
368     *        file.separator
369     *        user.name
370     *        java.version
371     *        java.home
372     * </pre>
373     *
374     * @param prop
375     *            the name of the system property to look up.
376     * @return the value of the specified system property or {@code null} if the
377     *         property doesn't exist.
378     * @throws SecurityException
379     *             if a {@link SecurityManager} is installed and its {@code
380     *             checkPropertyAccess()} method does not allow the operation.
381     */
382    public static String getProperty(String prop) {
383        return getProperty(prop, null);
384    }
385
386    /**
387     * Returns the value of a particular system property. The {@code
388     * defaultValue} will be returned if no such property has been found.
389     *
390     * @param prop
391     *            the name of the system property to look up.
392     * @param defaultValue
393     *            the return value if the system property with the given name
394     *            does not exist.
395     * @return the value of the specified system property or the {@code
396     *         defaultValue} if the property does not exist.
397     * @throws SecurityException
398     *             if a {@link SecurityManager} is installed and its {@code
399     *             checkPropertyAccess()} method does not allow the operation.
400     */
401    public static String getProperty(String prop, String defaultValue) {
402        if (prop.length() == 0) {
403            throw new IllegalArgumentException();
404        }
405        SecurityManager secMgr = System.getSecurityManager();
406        if (secMgr != null) {
407            secMgr.checkPropertyAccess(prop);
408        }
409
410        return internalGetProperties().getProperty(prop, defaultValue);
411    }
412
413    /**
414     * Sets the value of a particular system property.
415     *
416     * @param prop
417     *            the name of the system property to be changed.
418     * @param value
419     *            the value to associate with the given property {@code prop}.
420     * @return the old value of the property or {@code null} if the property
421     *         didn't exist.
422     * @throws SecurityException
423     *             if a security manager exists and write access to the
424     *             specified property is not allowed.
425     */
426    public static String setProperty(String prop, String value) {
427        if (prop.length() == 0) {
428            throw new IllegalArgumentException();
429        }
430        SecurityManager secMgr = System.getSecurityManager();
431        if (secMgr != null) {
432            secMgr.checkPermission(new PropertyPermission(prop, "write"));
433        }
434        return (String)internalGetProperties().setProperty(prop, value);
435    }
436
437    /**
438     * Removes a specific system property.
439     *
440     * @param key
441     *            the name of the system property to be removed.
442     * @return the property value or {@code null} if the property didn't exist.
443     * @throws NullPointerException
444     *             if the argument {@code key} is {@code null}.
445     * @throws IllegalArgumentException
446     *             if the argument {@code key} is empty.
447     * @throws SecurityException
448     *             if a security manager exists and write access to the
449     *             specified property is not allowed.
450     */
451    public static String clearProperty(String key) {
452        if (key == null) {
453            throw new NullPointerException();
454        }
455        if (key.length() == 0) {
456            throw new IllegalArgumentException();
457        }
458
459        SecurityManager secMgr = System.getSecurityManager();
460        if (secMgr != null) {
461            secMgr.checkPermission(new PropertyPermission(key, "write"));
462        }
463        return (String)internalGetProperties().remove(key);
464    }
465
466    /**
467     * Returns the {@link java.io.Console} associated with this VM, or null.
468     * Not all VMs will have an associated console. A console is typically only
469     * available for programs run from the command line.
470     * @since 1.6
471     */
472    public static Console console() {
473        return Console.getConsole();
474    }
475
476    /**
477     * Returns null. Android does not use {@code SecurityManager}. This method
478     * is only provided for source compatibility.
479     *
480     * @return null
481     */
482    public static SecurityManager getSecurityManager() {
483        return null;
484    }
485
486    /**
487     * Returns an integer hash code for the parameter. The hash code returned is
488     * the same one that would be returned by the method {@code
489     * java.lang.Object.hashCode()}, whether or not the object's class has
490     * overridden hashCode(). The hash code for {@code null} is {@code 0}.
491     *
492     * @param anObject
493     *            the object to calculate the hash code.
494     * @return the hash code for the given object.
495     * @see java.lang.Object#hashCode
496     */
497    public static native int identityHashCode(Object anObject);
498
499    /**
500     * Loads the specified file as a dynamic library.
501     *
502     * @param pathName
503     *            the path of the file to be loaded.
504     * @throws SecurityException
505     *             if the library was not allowed to be loaded.
506     */
507    public static void load(String pathName) {
508        SecurityManager smngr = System.getSecurityManager();
509        if (smngr != null) {
510            smngr.checkLink(pathName);
511        }
512        Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader());
513    }
514
515    /**
516     * Loads and links the shared library with the given name {@code libName}.
517     * The file will be searched in the default directory for shared libraries
518     * of the local system.
519     *
520     * @param libName
521     *            the name of the library to load.
522     * @throws UnsatisfiedLinkError
523     *             if the library could not be loaded.
524     * @throws SecurityException
525     *             if the library was not allowed to be loaded.
526     */
527    public static void loadLibrary(String libName) {
528        SecurityManager smngr = System.getSecurityManager();
529        if (smngr != null) {
530            smngr.checkLink(libName);
531        }
532        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
533    }
534
535    /**
536     * Provides a hint to the virtual machine that it would be useful to attempt
537     * to perform any outstanding object finalization.
538     */
539    public static void runFinalization() {
540        Runtime.getRuntime().runFinalization();
541    }
542
543    /**
544     * Ensures that, when the virtual machine is about to exit, all objects are
545     * finalized. Note that all finalization which occurs when the system is
546     * exiting is performed after all running threads have been terminated.
547     *
548     * @param flag
549     *            the flag determines if finalization on exit is enabled.
550     * @deprecated this method is unsafe.
551     */
552    @SuppressWarnings("deprecation")
553    @Deprecated
554    public static void runFinalizersOnExit(boolean flag) {
555        Runtime.runFinalizersOnExit(flag);
556    }
557
558    /**
559     * Sets all system properties.
560     *
561     * @param p
562     *            the new system property.
563     * @throws SecurityException
564     *             if a {@link SecurityManager} is installed and its {@code
565     *             checkPropertiesAccess()} method does not allow the operation.
566     */
567    public static void setProperties(Properties p) {
568        SecurityManager secMgr = System.getSecurityManager();
569        if (secMgr != null) {
570            secMgr.checkPropertiesAccess();
571        }
572
573        systemProperties = p;
574    }
575
576    /**
577     * Throws {@code SecurityException}.
578     *
579     * <p>Security managers do <i>not</i> provide a secure environment for
580     * executing untrusted code and are unsupported on Android. Untrusted code
581     * cannot be safely isolated within a single VM on Android.
582     *
583     * @param sm a security manager
584     * @throws SecurityException always
585     */
586    public static void setSecurityManager(SecurityManager sm) {
587        if (sm != null) {
588            throw new SecurityException();
589        }
590    }
591
592    /**
593     * Returns the platform specific file name format for the shared library
594     * named by the argument.
595     *
596     * @param userLibName
597     *            the name of the library to look up.
598     * @return the platform specific filename for the library.
599     */
600    public static native String mapLibraryName(String userLibName);
601
602    /**
603     * Sets the value of the named static field in the receiver to the passed in
604     * argument.
605     *
606     * @param fieldName
607     *            the name of the field to set, one of in, out, or err
608     * @param stream
609     *            the new value of the field
610     */
611    private static native void setFieldImpl(String fieldName, String signature, Object stream);
612
613}
614
615/**
616 * Internal class holding the System properties. Needed by the Dalvik VM for the
617 * two native methods. Must not be a local class, since we don't have a System
618 * instance.
619 */
620class SystemProperties extends Properties {
621    // Dummy, just to make the compiler happy.
622
623    native void preInit();
624
625    native void postInit();
626}
627
628/**
629 * Internal class holding the System environment variables. The Java spec
630 * mandates that this map be read-only, so we wrap our real map into this one
631 * and make sure no one touches the contents. We also check for null parameters
632 * and do some (seemingly unnecessary) type casts to fulfill the contract layed
633 * out in the spec.
634 */
635class SystemEnvironment implements Map {
636
637    private Map<String, String> map;
638
639    public SystemEnvironment(Map<String, String> map) {
640        this.map = map;
641    }
642
643    public void clear() {
644        throw new UnsupportedOperationException("Can't modify environment");
645    }
646
647    @SuppressWarnings("cast")
648    public boolean containsKey(Object key) {
649        if (key == null) {
650            throw new NullPointerException();
651        }
652
653        return map.containsKey((String)key);
654    }
655
656    @SuppressWarnings("cast")
657    public boolean containsValue(Object value) {
658        if (value == null) {
659            throw new NullPointerException();
660        }
661
662        return map.containsValue((String)value);
663    }
664
665    public Set entrySet() {
666        return map.entrySet();
667    }
668
669    @SuppressWarnings("cast")
670    public String get(Object key) {
671        if (key == null) {
672            throw new NullPointerException();
673        }
674
675        return map.get((String)key);
676    }
677
678    public boolean isEmpty() {
679        return map.isEmpty();
680    }
681
682    public Set<String> keySet() {
683        return map.keySet();
684    }
685
686    public String put(Object key, Object value) {
687        throw new UnsupportedOperationException("Can't modify environment");
688    }
689
690    public void putAll(Map map) {
691        throw new UnsupportedOperationException("Can't modify environment");
692    }
693
694    public String remove(Object key) {
695        throw new UnsupportedOperationException("Can't modify environment");
696    }
697
698    public int size() {
699        return map.size();
700    }
701
702    public Collection values() {
703        return map.values();
704    }
705
706}
707