System.java revision 16773d4f29a6cc3d0ab11f66ff15d606cffe4059
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     *
353     * <p>The following properties are always provided by the virtual machine:
354     * <p><table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
355     * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
356     *     <td><b>Name</b></td>        <td><b>Meaning</b></td>                    <td><b>Example</b></td></tr>
357     * <tr><td>file.separator</td>     <td>{@link java.io.File#separator}</td>    <td>{@code /}</td></tr>
358     *
359     * <tr><td>java.class.path</td>    <td>System class path</td>                 <td>{@code .}</td></tr>
360     * <tr><td>java.class.version</td> <td>Maximum supported .class file version</td> <td>{@code 46.0}</td></tr>
361     * <tr><td>java.compiler</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
362     * <tr><td>java.ext.dirs</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
363     * <tr><td>java.home</td>          <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr>
364     * <tr><td>java.io.tmpdir</td>     <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr>
365     * <tr><td>java.library.path</td>  <td>Search path for JNI libraries</td>     <td>{@code /system/lib}</td></tr>
366     * <tr><td>java.vendor</td>        <td>Human-readable VM vendor</td>          <td>{@code The Android Project}</td></tr>
367     * <tr><td>java.vendor.url</td>    <td>URL for VM vendor's web site</td>      <td>{@code http://www.android.com/}</td></tr>
368     * <tr><td>java.version</td>       <td>(Not useful on Android)</td>           <td>{@code 0}</td></tr>
369     *
370     * <tr><td>java.specification.version</td>    <td>VM libraries version</td>        <td>{@code 0.9}</td></tr>
371     * <tr><td>java.specification.vendor</td>     <td>VM libraries vendor</td>         <td>{@code The Android Project}</td></tr>
372     * <tr><td>java.specification.name</td>       <td>VM libraries name</td>           <td>{@code Dalvik Core Library}</td></tr>
373     * <tr><td>java.vm.version</td>               <td>VM implementation version</td>   <td>{@code 1.2.0}</td></tr>
374     * <tr><td>java.vm.vendor</td>                <td>VM implementation vendor</td>    <td>{@code The Android Project}</td></tr>
375     * <tr><td>java.vm.name</td>                  <td>VM implementation name</td>      <td>{@code Dalvik}</td></tr>
376     * <tr><td>java.vm.specification.version</td> <td>VM specification version</td>    <td>{@code 0.9}</td></tr>
377     * <tr><td>java.vm.specification.vendor</td>  <td>VM specification vendor</td>     <td>{@code The Android Project}</td></tr>
378     * <tr><td>java.vm.specification.name</td>    <td>VM specification name</td>       <td>{@code Dalvik Virtual Machine Specification}</td></tr>
379     *
380     * <tr><td>line.separator</td>     <td>Default line separator</td>            <td>{@code \n}</td></tr>
381     *
382     * <tr><td>os.arch</td>            <td>OS architecture</td>                   <td>{@code armv7l}</td></tr>
383     * <tr><td>os.name</td>            <td>OS (kernel) name</td>                  <td>{@code Linux}</td></tr>
384     * <tr><td>os.version</td>         <td>OS (kernel) version</td>               <td>{@code 2.6.32.9-g103d848}</td></tr>
385     *
386     * <tr><td>path.separator</td>     <td>{@link java.io.File#pathSeparator}</td> <td>{@code :}</td></tr>
387     *
388     * <tr><td>user.dir</td>           <td>Base of non-absolute paths</td>        <td>{@code /}</td></tr>
389     * <tr><td>user.home</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
390     * <tr><td>user.name</td>          <td>(Not useful on Android)</td>           <td>Empty</td></tr>
391     *
392     * </table>
393     *
394     * @param propertyName
395     *            the name of the system property to look up.
396     * @return the value of the specified system property or {@code null} if the
397     *         property doesn't exist.
398     * @throws SecurityException
399     *             if a {@link SecurityManager} is installed and its {@code
400     *             checkPropertyAccess()} method does not allow the operation.
401     */
402    public static String getProperty(String propertyName) {
403        return getProperty(propertyName, null);
404    }
405
406    /**
407     * Returns the value of a particular system property. The {@code
408     * defaultValue} will be returned if no such property has been found.
409     *
410     * @param prop
411     *            the name of the system property to look up.
412     * @param defaultValue
413     *            the return value if the system property with the given name
414     *            does not exist.
415     * @return the value of the specified system property or the {@code
416     *         defaultValue} if the property does not exist.
417     * @throws SecurityException
418     *             if a {@link SecurityManager} is installed and its {@code
419     *             checkPropertyAccess()} method does not allow the operation.
420     */
421    public static String getProperty(String prop, String defaultValue) {
422        if (prop.length() == 0) {
423            throw new IllegalArgumentException();
424        }
425        SecurityManager secMgr = System.getSecurityManager();
426        if (secMgr != null) {
427            secMgr.checkPropertyAccess(prop);
428        }
429
430        return internalGetProperties().getProperty(prop, defaultValue);
431    }
432
433    /**
434     * Sets the value of a particular system property.
435     *
436     * @param prop
437     *            the name of the system property to be changed.
438     * @param value
439     *            the value to associate with the given property {@code prop}.
440     * @return the old value of the property or {@code null} if the property
441     *         didn't exist.
442     * @throws SecurityException
443     *             if a security manager exists and write access to the
444     *             specified property is not allowed.
445     */
446    public static String setProperty(String prop, String value) {
447        if (prop.length() == 0) {
448            throw new IllegalArgumentException();
449        }
450        SecurityManager secMgr = System.getSecurityManager();
451        if (secMgr != null) {
452            secMgr.checkPermission(new PropertyPermission(prop, "write"));
453        }
454        return (String)internalGetProperties().setProperty(prop, value);
455    }
456
457    /**
458     * Removes a specific system property.
459     *
460     * @param key
461     *            the name of the system property to be removed.
462     * @return the property value or {@code null} if the property didn't exist.
463     * @throws NullPointerException
464     *             if the argument {@code key} is {@code null}.
465     * @throws IllegalArgumentException
466     *             if the argument {@code key} is empty.
467     * @throws SecurityException
468     *             if a security manager exists and write access to the
469     *             specified property is not allowed.
470     */
471    public static String clearProperty(String key) {
472        if (key == null) {
473            throw new NullPointerException();
474        }
475        if (key.length() == 0) {
476            throw new IllegalArgumentException();
477        }
478
479        SecurityManager secMgr = System.getSecurityManager();
480        if (secMgr != null) {
481            secMgr.checkPermission(new PropertyPermission(key, "write"));
482        }
483        return (String)internalGetProperties().remove(key);
484    }
485
486    /**
487     * Returns the {@link java.io.Console} associated with this VM, or null.
488     * Not all VMs will have an associated console. A console is typically only
489     * available for programs run from the command line.
490     * @since 1.6
491     */
492    public static Console console() {
493        return Console.getConsole();
494    }
495
496    /**
497     * Returns null. Android does not use {@code SecurityManager}. This method
498     * is only provided for source compatibility.
499     *
500     * @return null
501     */
502    public static SecurityManager getSecurityManager() {
503        return null;
504    }
505
506    /**
507     * Returns an integer hash code for the parameter. The hash code returned is
508     * the same one that would be returned by the method {@code
509     * java.lang.Object.hashCode()}, whether or not the object's class has
510     * overridden hashCode(). The hash code for {@code null} is {@code 0}.
511     *
512     * @param anObject
513     *            the object to calculate the hash code.
514     * @return the hash code for the given object.
515     * @see java.lang.Object#hashCode
516     */
517    public static native int identityHashCode(Object anObject);
518
519    /**
520     * Loads the specified file as a dynamic library.
521     *
522     * @param pathName
523     *            the path of the file to be loaded.
524     * @throws SecurityException
525     *             if the library was not allowed to be loaded.
526     */
527    public static void load(String pathName) {
528        SecurityManager smngr = System.getSecurityManager();
529        if (smngr != null) {
530            smngr.checkLink(pathName);
531        }
532        Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader());
533    }
534
535    /**
536     * Loads and links the shared library with the given name {@code libName}.
537     * The file will be searched in the default directory for shared libraries
538     * of the local system.
539     *
540     * @param libName
541     *            the name of the library to load.
542     * @throws UnsatisfiedLinkError
543     *             if the library could not be loaded.
544     * @throws SecurityException
545     *             if the library was not allowed to be loaded.
546     */
547    public static void loadLibrary(String libName) {
548        SecurityManager smngr = System.getSecurityManager();
549        if (smngr != null) {
550            smngr.checkLink(libName);
551        }
552        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
553    }
554
555    /**
556     * Provides a hint to the virtual machine that it would be useful to attempt
557     * to perform any outstanding object finalization.
558     */
559    public static void runFinalization() {
560        Runtime.getRuntime().runFinalization();
561    }
562
563    /**
564     * Ensures that, when the virtual machine is about to exit, all objects are
565     * finalized. Note that all finalization which occurs when the system is
566     * exiting is performed after all running threads have been terminated.
567     *
568     * @param flag
569     *            the flag determines if finalization on exit is enabled.
570     * @deprecated this method is unsafe.
571     */
572    @SuppressWarnings("deprecation")
573    @Deprecated
574    public static void runFinalizersOnExit(boolean flag) {
575        Runtime.runFinalizersOnExit(flag);
576    }
577
578    /**
579     * Sets all system properties.
580     *
581     * @param p
582     *            the new system property.
583     * @throws SecurityException
584     *             if a {@link SecurityManager} is installed and its {@code
585     *             checkPropertiesAccess()} method does not allow the operation.
586     */
587    public static void setProperties(Properties p) {
588        SecurityManager secMgr = System.getSecurityManager();
589        if (secMgr != null) {
590            secMgr.checkPropertiesAccess();
591        }
592
593        systemProperties = p;
594    }
595
596    /**
597     * Throws {@code SecurityException}.
598     *
599     * <p>Security managers do <i>not</i> provide a secure environment for
600     * executing untrusted code and are unsupported on Android. Untrusted code
601     * cannot be safely isolated within a single VM on Android.
602     *
603     * @param sm a security manager
604     * @throws SecurityException always
605     */
606    public static void setSecurityManager(SecurityManager sm) {
607        if (sm != null) {
608            throw new SecurityException();
609        }
610    }
611
612    /**
613     * Returns the platform specific file name format for the shared library
614     * named by the argument.
615     *
616     * @param userLibName
617     *            the name of the library to look up.
618     * @return the platform specific filename for the library.
619     */
620    public static native String mapLibraryName(String userLibName);
621
622    /**
623     * Sets the value of the named static field in the receiver to the passed in
624     * argument.
625     *
626     * @param fieldName
627     *            the name of the field to set, one of in, out, or err
628     * @param stream
629     *            the new value of the field
630     */
631    private static native void setFieldImpl(String fieldName, String signature, Object stream);
632
633}
634
635/**
636 * Internal class holding the System properties. Needed by the Dalvik VM for the
637 * two native methods. Must not be a local class, since we don't have a System
638 * instance.
639 */
640class SystemProperties extends Properties {
641    // Dummy, just to make the compiler happy.
642
643    native void preInit();
644
645    native void postInit();
646}
647
648/**
649 * Internal class holding the System environment variables. The Java spec
650 * mandates that this map be read-only, so we wrap our real map into this one
651 * and make sure no one touches the contents. We also check for null parameters
652 * and do some (seemingly unnecessary) type casts to fulfill the contract layed
653 * out in the spec.
654 */
655class SystemEnvironment implements Map {
656
657    private Map<String, String> map;
658
659    public SystemEnvironment(Map<String, String> map) {
660        this.map = map;
661    }
662
663    public void clear() {
664        throw new UnsupportedOperationException("Can't modify environment");
665    }
666
667    @SuppressWarnings("cast")
668    public boolean containsKey(Object key) {
669        if (key == null) {
670            throw new NullPointerException();
671        }
672
673        return map.containsKey((String)key);
674    }
675
676    @SuppressWarnings("cast")
677    public boolean containsValue(Object value) {
678        if (value == null) {
679            throw new NullPointerException();
680        }
681
682        return map.containsValue((String)value);
683    }
684
685    public Set entrySet() {
686        return map.entrySet();
687    }
688
689    @SuppressWarnings("cast")
690    public String get(Object key) {
691        if (key == null) {
692            throw new NullPointerException();
693        }
694
695        return map.get((String)key);
696    }
697
698    public boolean isEmpty() {
699        return map.isEmpty();
700    }
701
702    public Set<String> keySet() {
703        return map.keySet();
704    }
705
706    public String put(Object key, Object value) {
707        throw new UnsupportedOperationException("Can't modify environment");
708    }
709
710    public void putAll(Map map) {
711        throw new UnsupportedOperationException("Can't modify environment");
712    }
713
714    public String remove(Object key) {
715        throw new UnsupportedOperationException("Can't modify environment");
716    }
717
718    public int size() {
719        return map.size();
720    }
721
722    public Collection values() {
723        return map.values();
724    }
725
726}
727