You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ar...@apache.org on 2006/05/02 01:11:49 UTC
svn commit: r398726 [3/6] - in /incubator/harmony/enhanced/classlibadapter:
./ trunk/ trunk/bin/ trunk/modules/ trunk/modules/kernel/
trunk/modules/kernel/src/ trunk/modules/kernel/src/main/
trunk/modules/kernel/src/main/java/ trunk/modules/kernel/src/...
Added: incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/System.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/System.java?rev=398726&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/System.java (added)
+++ incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/System.java Mon May 1 16:11:39 2006
@@ -0,0 +1,905 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Properties;
+import java.util.PropertyPermission;
+
+
+/**
+ * Class System provides a standard place for programs to find system related
+ * information. All System API is static.
+ *
+ */
+public final class System {
+
+ // The standard input, output, and error streams.
+ // Typically, these are connected to the shell which
+ // ran the Java program.
+ /**
+ * Default input stream
+ */
+ public static final InputStream in;
+
+ /**
+ * Default output stream
+ */
+ public static final PrintStream out;
+
+ /**
+ * Default error output stream
+ */
+ public static final PrintStream err;
+
+ // Get a ref to the Runtime instance for faster lookup
+ private static final Runtime RUNTIME = Runtime.getRuntime();
+
+ // The System Properties table
+ private static Properties systemProperties;
+
+ // The System default SecurityManager
+ private static SecurityManager security;
+
+ // Initialize all the slots in System on first use.
+ static {
+ //fixit -- temporarily hard code the path to a DLL library that holds a native method for simple character output
+ int tt = VMRuntime.nativeLoad("/cygdrive/c/temp2/Harmony/native-src/linux.IA32/luni_gnuclasspathadapter/libOSFileSystem.a", ClassLoader.systemClassLoader);
+ // Fill in the properties from the VM information.
+ ensureProperties();
+ // Set up standard in, out, and err.
+ err = new String.ConsolePrintStream(new BufferedOutputStream(
+ new FileOutputStream(FileDescriptor.err)));
+ VMSystem.setErr(err);
+
+ out = new String.ConsolePrintStream(new BufferedOutputStream(
+ new FileOutputStream(FileDescriptor.out)));
+ VMSystem.setOut(out);
+
+ /* toss this
+ int xx;
+ for (xx = 0; xx < 100; xx++)
+ {
+ // the below is a test that verifies System.out is initialized properly
+ out.write(0x41); out.write(0x42); out.write(0x43);
+ }
+ */
+
+ in = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
+ VMSystem.setIn(in);
+ }
+
+ /**
+ * Sets the value of the static slot "in" in the receiver to the passed in
+ * argument.
+ *
+ * @param newIn
+ * the new value for in.
+ */
+ public static void setIn(InputStream newIn) {
+ //SecurityManager secMgr = System.getSecurityManager();
+ //setFieldImpl("in", newIn);
+ //fixit -- get security out of the way while bringing up simple "hello world" demo
+ VMSystem.setIn(newIn);
+ }
+
+ /**
+ * Sets the value of the static slot "out" in the receiver to the passed in
+ * argument.
+ *
+ * @param newOut
+ * the new value for out.
+ */
+ public static void setOut(java.io.PrintStream newOut) {
+ //SecurityManager secMgr = System.getSecurityManager();
+ //setFieldImpl("out", newOut);
+ //fixit -- get security out of the way while bringing up simple "hello world" demo
+ VMSystem.setOut(newOut);
+ }
+
+ /**
+ * Sets the value of the static slot "err" in the receiver to the passed in
+ * argument.
+ *
+ * @param newErr
+ * the new value for err.
+ */
+ public static void setErr(java.io.PrintStream newErr) {
+ //SecurityManager secMgr = System.getSecurityManager();
+ //fixit -- get security out of the way while bringing up simple "hello world" demo
+ VMSystem.setErr(newErr);
+
+ }
+
+ /**
+ * Prevents this class from being instantiated.
+ */
+ private System() {
+ }
+
+ /**
+ * Copies the contents of <code>array1</code> starting at offset
+ * <code>start1</code> into <code>array2</code> starting at offset
+ * <code>start2</code> for <code>length</code> elements.
+ *
+ * @param array1
+ * the array to copy out of
+ * @param start1
+ * the starting index in array1
+ * @param array2
+ * the array to copy into
+ * @param start2
+ * the starting index in array2
+ * @param length
+ * the number of elements in the array to copy
+ */
+ public static void arraycopy(Object array1, int start1, Object array2,
+ int start2, int length) {
+ // sending getClass() to both arguments will check for null
+ Class type1 = array1.getClass();
+ Class type2 = array2.getClass();
+ if (!type1.isArray() || !type2.isArray())
+ throw new ArrayStoreException();
+ Class componentType1 = type1.getComponentType();
+ Class componentType2 = type2.getComponentType();
+ if (!componentType1.isPrimitive()) {
+ if (componentType2.isPrimitive())
+ throw new ArrayStoreException();
+ arraycopy((Object[]) array1, start1, (Object[]) array2, start2,
+ length);
+ } else {
+ if (componentType2 != componentType1)
+ throw new ArrayStoreException();
+ if (componentType1 == Integer.TYPE) {
+ arraycopy((int[]) array1, start1, (int[]) array2, start2,
+ length);
+ } else if (componentType1 == Byte.TYPE) {
+ arraycopy((byte[]) array1, start1, (byte[]) array2, start2,
+ length);
+ } else if (componentType1 == Long.TYPE) {
+ arraycopy((long[]) array1, start1, (long[]) array2, start2,
+ length);
+ } else if (componentType1 == Short.TYPE) {
+ arraycopy((short[]) array1, start1, (short[]) array2, start2,
+ length);
+ } else if (componentType1 == Character.TYPE) {
+ arraycopy((char[]) array1, start1, (char[]) array2, start2,
+ length);
+ } else if (componentType1 == Boolean.TYPE) {
+ arraycopy((boolean[]) array1, start1, (boolean[]) array2,
+ start2, length);
+ } else if (componentType1 == Double.TYPE) {
+ arraycopy((double[]) array1, start1, (double[]) array2, start2,
+ length);
+ } else if (componentType1 == Float.TYPE) {
+ arraycopy((float[]) array1, start1, (float[]) array2, start2,
+ length);
+ }
+ }
+ }
+
+ /**
+ * Private version of the arraycopy method (used by the jit for reference arraycopies)
+ */
+ private static void arraycopy(Object[] A1, int offset1, Object[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(int[] A1, int offset1, int[] A2, int offset2,
+ int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(byte[] A1, int offset1, byte[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(short[] A1, int offset1, short[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(long[] A1, int offset1, long[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(char[] A1, int offset1, char[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(boolean[] A1, int offset1, boolean[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(double[] A1, int offset1, double[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Copies the contents of <code>A1</code> starting at offset <code>offset1</code>
+ * into <code>A2</code> starting at offset <code>offset2</code> for
+ * <code>length</code> elements.
+ *
+ * @param A1 the array to copy out of
+ * @param offset1 the starting index in array1
+ * @param A2 the array to copy into
+ * @param offset2 the starting index in array2
+ * @param length the number of elements in the array to copy
+ */
+ private static void arraycopy(float[] A1, int offset1, float[] A2,
+ int offset2, int length) {
+ if (offset1 >= 0 && offset2 >= 0 && length >= 0
+ && length <= A1.length - offset1
+ && length <= A2.length - offset2) {
+ // Check if this is a forward or backwards arraycopy
+ if (A1 != A2 || offset1 > offset2 || offset1 + length <= offset2) {
+ for (int i = 0; i < length; ++i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ } else {
+ for (int i = length - 1; i >= 0; --i) {
+ A2[offset2 + i] = A1[offset1 + i];
+ }
+ }
+ } else
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /**
+ * Answers the current time expressed as milliseconds since the time
+ * 00:00:00 UTC on January 1, 1970.
+ *
+ * @return the time in milliseconds.
+ */
+ public static long currentTimeMillis()
+ {
+ return VMSystem.currentTimeMillis();
+ }
+
+ private static final int InitLocale = 0;
+
+ private static final int PlatformEncoding = 1;
+
+ private static final int FileEncoding = 2;
+
+ private static final int OSEncoding = 3;
+
+ /**
+ * If systemProperties is unset, then create a new one based on the values
+ * provided by the virtual machine.
+ */
+ private static void ensureProperties() {
+ systemProperties = new Properties();
+
+ String platformEncoding = null;
+ String fileEncoding, osEncoding = null;
+ String definedFileEncoding = getEncoding(FileEncoding);
+ String definedOSEncoding = getEncoding(OSEncoding);
+ if (definedFileEncoding != null) {
+ fileEncoding = definedFileEncoding;
+ // if file.encoding is defined, and os.encoding is not, use the
+ // detected
+ // platform encoding for os.encoding
+ if (definedOSEncoding == null) {
+ platformEncoding = getEncoding(PlatformEncoding);
+ osEncoding = platformEncoding;
+ } else {
+ getEncoding(InitLocale);
+ }
+ } else {
+ platformEncoding = getEncoding(PlatformEncoding);
+ fileEncoding = platformEncoding;
+ }
+ // if os.encoding is not defined, file.encoding will be used
+ if (osEncoding == null)
+ osEncoding = definedOSEncoding;
+ if (osEncoding != null)
+ systemProperties.put("os.encoding", osEncoding);
+
+ systemProperties.put("file.encoding", fileEncoding);
+
+ systemProperties.put("java.version", "1.4.2 subset");
+ systemProperties.put("java.specification.version", "1.4");
+
+ systemProperties.put("java.specification.vendor",
+ "Sun Microsystems Inc.");
+ systemProperties.put("java.specification.name",
+ "Java Platform API Specification");
+
+ systemProperties.put("com.ibm.oti.configuration", "clear");
+ systemProperties.put("com.ibm.oti.configuration.dir", "jclClear");
+
+ String[] list = getPropertyList();
+ for (int i = 0; i < list.length; i += 2) {
+ String key = list[i];
+ if (key == null)
+ break;
+ systemProperties.put(key, list[i + 1]);
+ }
+
+ String consoleEncoding = (String) systemProperties
+ .get("console.encoding");
+ if (consoleEncoding == null) {
+ if (platformEncoding == null)
+ platformEncoding = getEncoding(PlatformEncoding);
+ consoleEncoding = platformEncoding;
+ systemProperties.put("console.encoding", consoleEncoding);
+ }
+
+ systemProperties.put("com.ibm.oti.jcl.build", "plugin");
+ }
+
+ /**
+ * Causes the virtual machine to stop running, and the program to exit. If
+ * runFinalizersOnExit(true) has been invoked, then all finalizers will be
+ * run first.
+ *
+ * @param code
+ * the return code.
+ *
+ * @throws SecurityException
+ * if the running thread is not allowed to cause the vm to exit.
+ *
+ * @see SecurityManager#checkExit
+ */
+ public static void exit(int code) {
+ VMRuntime.exit(code);
+ }
+
+ /**
+ * Indicate to the virtual machine that it would be a good time to collect
+ * available memory. Note that, this is a hint only.
+ */
+ public static void gc() {
+ VMRuntime.gc();
+ }
+
+ /**
+ * Returns an environment variable.
+ *
+ * @param var
+ * the name of the environment variable
+ * @return the value of the specified environment variable
+ * @deprecated Use System.getProperty()
+ */
+ public static String getenv(String var) {
+ //System.out.println("System.getenv() --- security has been turned off");
+ if (var == null) {
+ throw new NullPointerException();
+ }
+ //fixit -- get security out of the way while bringing up simple "hello world" demo
+ /*
+ SecurityManager secMgr = System.getSecurityManager();
+ if (secMgr != null) {
+ secMgr.checkPermission(new RuntimePermission("getenv." + var));
+ }
+ throw new Error();
+ */
+ return null;
+ }
+
+ /**
+ * Answers the system properties. Note that this is not a copy, so that
+ * changes made to the returned Properties object will be reflected in
+ * subsequent calls to getProperty and getProperties.
+ * <p>
+ * Security managers should restrict access to this API if possible.
+ *
+ * @return the system properties
+ */
+ public static Properties getProperties() {
+ //fixit -- get security out of the way while bringing up simple "hello world" demo
+ /*
+ SecurityManager secMgr = System.getSecurityManager();
+ if (secMgr != null) {
+ secMgr.checkPropertiesAccess();
+ }
+ */
+ return systemProperties;
+ }
+
+ /**
+ * Answers the system properties without any security checks. This is used
+ * for access from within java.lang.
+ *
+ * @return the system properties
+ */
+ static Properties internalGetProperties() {
+ return systemProperties;
+ }
+
+ /**
+ * Answers the value of a particular system property. Answers null if no
+ * such property exists,
+ * <p>
+ * The properties currently provided by the virtual machine are:
+ *
+ * <pre>
+ * java.vendor.url
+ * java.class.path
+ * user.home
+ * java.class.version
+ * os.version
+ * java.vendor
+ * user.dir
+ * user.timezone
+ * path.separator
+ * os.name
+ * os.arch
+ * line.separator
+ * file.separator
+ * user.name
+ * java.version
+ * java.home
+ * </pre>
+ *
+ * @param prop
+ * the system property to look up
+ * @return the value of the specified system property, or null if the
+ * property doesn't exist
+ */
+ public static String getProperty(String prop) {
+ return getProperty(prop, null);
+ }
+
+ /**
+ * Answers the value of a particular system property. If no such property is
+ * found, answers the defaultValue.
+ *
+ * @param prop
+ * the system property to look up
+ * @param defaultValue
+ * return value if system property is not found
+ * @return the value of the specified system property, or defaultValue if
+ * the property doesn't exist
+ */
+ public static String getProperty(String prop, String defaultValue) {
+ if (prop.length() == 0)
+ throw new IllegalArgumentException();
+ //fixit -- get security out of the way while bringing up simple "hello world" demo
+ /*
+ SecurityManager secMgr = System.getSecurityManager();
+ if (secMgr != null) {
+ secMgr.checkPropertyAccess(prop);
+ }
+ */
+ return systemProperties.getProperty(prop, defaultValue);
+ }
+
+ /**
+ * Sets the value of a particular system property.
+ *
+ * @param prop
+ * the system property to change
+ * @param value
+ * the value to associate with prop
+ * @return the old value of the property, or null
+ */
+ public static String setProperty(String prop, String value) {
+ if (prop.length() == 0)
+ throw new IllegalArgumentException();
+ //fixit -- get security out of the way while bringing up simple "hello world" demo
+ /*
+ SecurityManager secMgr = System.getSecurityManager();
+ if (secMgr != null) {
+ secMgr.checkPermission(new PropertyPermission(prop, "write"));
+ }
+ */
+ return (String) systemProperties.setProperty(prop, value);
+ }
+
+ /**
+ * Answers an array of Strings containing key..value pairs (in consecutive
+ * array elements) which represent the starting values for the system
+ * properties as provided by the virtual machine.
+ *
+ * @return the default values for the system properties.
+ */
+ //fixit below is a non-native version for getting "hello world" to work ----- private static native String[] getPropertyList()
+ private static String[] getPropertyList()
+ {
+ //fixit --- apparently the below code never executes for simple "hello world" demo
+ // when getPropertyList is actually called, the hope is that it will cause an out of
+ // java heap memory exception which in turn bring us to implementing the correct native method
+ String[] str = new String[99999];
+ return str;
+ }
+
+ /**
+ * Return the requested encoding. 0 - initialize locale 1 - detected
+ * platform encoding 2 - command line defined file.encoding 3 - command line
+ * defined os.encoding
+ */
+ //fixit below is a non-native version for getting "hello world" to work ---- private static native String getEncoding(int type);
+ private static String getEncoding(int type)
+ {
+ return "java.lang.System.getEncoding()";
+ /*
+ String str = "java.lang.System.getEncoding() type = ???";
+ if (type == 0)
+ str = null; ////"java.lang.System.getEncoding() type = 0";
+ if (type == 1)
+ str = null; ///"java.lang.System.getEncoding() type = 1";
+ if (type == 2)
+ str = null; ///"java.lang.System.getEncoding() type = 2";
+ if (type == 3)
+ str = "Cp1252";
+ return str;
+ */
+ }
+
+ /**
+ * Answers the active security manager.
+ *
+ * @return the system security manager object.
+ */
+ public static SecurityManager getSecurityManager() {
+ return security;
+ }
+
+ /**
+ * Answers an integer hash code for the parameter. The hash code returned is
+ * the same one that would be returned by java.lang.Object.hashCode(),
+ * whether or not the object's class has overridden hashCode(). The hash
+ * code for null is 0.
+ *
+ * @param anObject
+ * the object
+ * @return the hash code for the object
+ *
+ * @see java.lang.Object#hashCode
+ */
+ // not the correct interface ---> public static native int identityHashCode(Object anObject);
+ public static int identityHashCode(Object anObject)
+ {
+ int hash = VMSystem.identityHashCode(anObject);
+ return hash;
+ }
+
+ /**
+ * Loads the specified file as a dynamic library.
+ *
+ * @param pathName
+ * the path of the file to be loaded
+ */
+ public static void load(String pathName) {
+ //fixit -- set aside security while bringing up simple "hello world" demo
+ /*
+ SecurityManager smngr = System.getSecurityManager();
+ if (smngr != null)
+ smngr.checkLink(pathName);
+ */
+ ClassLoader.loadLibraryWithPath(pathName, ClassLoader
+ .callerClassLoader(), null);
+ }
+
+ /**
+ * Loads and links the library specified by the argument.
+ *
+ * @param libName
+ * the name of the library to load
+ *
+ * @throws UnsatisfiedLinkError
+ * if the library could not be loaded
+ * @throws SecurityException
+ * if the library was not allowed to be loaded
+ */
+ public static void loadLibrary(String libName) {
+ ClassLoader.loadLibraryWithClassLoader(libName, ClassLoader
+ .callerClassLoader());
+ }
+
+ /**
+ * Provides a hint to the virtual machine that it would be useful to attempt
+ * to perform any outstanding object finalizations.
+ */
+ public static void runFinalization() {
+ VMRuntime.runFinalization();
+ }
+
+ /**
+ * Ensure that, when the virtual machine is about to exit, all objects are
+ * finalized. Note that all finalization which occurs when the system is
+ * exiting is performed after all running threads have been terminated.
+ *
+ * @param flag
+ * true means finalize all on exit.
+ *
+ * @deprecated This method is unsafe.
+ */
+ public static void runFinalizersOnExit(boolean flag) {
+ VMRuntime.runFinalizersOnExit(flag);
+ }
+
+ /**
+ * Answers the system properties. Note that the object which is passed in
+ * not copied, so that subsequent changes made to the object will be
+ * reflected in calls to getProperty and getProperties.
+ * <p>
+ * Security managers should restrict access to this API if possible.
+ *
+ * @param p
+ * the property to set
+ */
+ public static void setProperties(Properties p) {
+ SecurityManager secMgr = System.getSecurityManager();
+ if (secMgr != null) {
+ secMgr.checkPropertiesAccess();
+ }
+ if (p == null) {
+ ensureProperties();
+ } else {
+ systemProperties = p;
+ }
+ }
+
+ /**
+ * Sets the active security manager. Note that once the security manager has
+ * been set, it can not be changed. Attempts to do so will cause a security
+ * exception.
+ *
+ * @param s
+ * the new security manager
+ *
+ * @throws SecurityException
+ * if the security manager has already been set.
+ */
+ public static void setSecurityManager(final SecurityManager s) {
+ final SecurityManager currentSecurity = security;
+ try {
+ // Preload classes used for checkPackageAccess(),
+ // otherwise we could go recursive
+ s.checkPackageAccess("java.lang");
+ } catch (Exception e) {
+ }
+
+ security = s;
+ }
+
+ /**
+ * Answers the platform specific file name format for the shared library
+ * named by the argument.
+ *
+ * @param userLibName
+ * the name of the library to look up.
+ * @return the platform specific filename for the library
+ */
+ //fixit -- the original stub declares this routine a native method. Is this required?
+ // public static native String mapLibraryName(String userLibName);
+ public static String mapLibraryName(String userLibName)
+ {
+ return "System.mapLibraryName() is not implemented";
+ }
+
+ /**
+ * Sets the value of the named static field in the receiver to the passed in
+ * argument.
+ *
+ * @param fieldName
+ * the name of the field to set, one of in, out, or err
+ * @param stream
+ * the new value of the field
+ */
+ //fixit -- the original stub declares this routine a native method. Is this required?
+ //private static native void setFieldImpl(String fieldName, Object stream);
+ private static void setFieldImpl(String fieldName, Object stream)
+ {
+ return;
+ }
+
+}
+
Propchange: incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/System.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/Thread.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/Thread.java?rev=398726&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/Thread.java (added)
+++ incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/Thread.java Mon May 1 16:11:39 2006
@@ -0,0 +1,769 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+/**
+ * This class must be implemented by the vm vendor. The documented methods must
+ * be implemented to support other provided class implementations in this
+ * package. A Thread is a unit of concurrent execution in Java. It has its own
+ * call stack for methods being called and their parameters. Threads in the same
+ * VM interact and synchronize by the use of shared Objects and monitors
+ * associated with these objects. Synchronized methods and part of the API in
+ * Object also allow Threads to cooperate. When a Java program starts executing
+ * there is an implicit Thread (called "main") which is automatically created by
+ * the VM. This Thread belongs to a ThreadGroup (also called "main") which is
+ * automatically created by the bootstrap sequence by the VM as well.
+ *
+ * @see java.lang.Object
+ * @see java.lang.ThreadGroup
+ */
+public class Thread implements Runnable {
+
+ public final static int MAX_PRIORITY = 10; // Maximum allowed priority for
+
+ // a thread
+ public final static int MIN_PRIORITY = 1; // Minimum allowed priority for
+
+ // a thread
+ public final static int NORM_PRIORITY = 5; // Normal priority for a thread
+
+ Runnable runnableSlot;
+ //////String threadNameSlot; //maybe same as next one
+ String name;
+ /////ThreadGroup threadGroupSlot; //maybe same as next one
+ ThreadGroup group;
+ ////VMThread threadSlot; //maybe same as next one
+ VMThread vmThread;
+ ///boolean isDaemonSlot; //maybe this is the same as daemon
+ boolean daemon;
+ ThreadLocal threadLocalSlot;
+ long stackSlot;
+ int priority;
+
+
+ /**
+ * Constructs a new Thread with no runnable object and a newly generated
+ * name. The new Thread will belong to the same ThreadGroup as the Thread
+ * calling this constructor.
+ *
+ * @see java.lang.ThreadGroup
+ */
+ public Thread(VMThread vmt1, String s1, int i1, boolean b1)
+ {
+ super();
+ vmThread = vmt1;
+ name = s1;
+ priority = i1;
+ daemon = b1;
+ }
+ public Thread() {
+ super();
+ vmThread = new VMThread();
+ }
+
+ /**
+ * Constructs a new Thread with a runnable object and a newly generated
+ * name. The new Thread will belong to the same ThreadGroup as the Thread
+ * calling this constructor.
+ *
+ * @param runnable
+ * a java.lang.Runnable whose method <code>run</code> will be
+ * executed by the new Thread
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(Runnable runnable) {
+ super();
+ runnableSlot = runnable;
+ vmThread = new VMThread();
+ }
+
+ /**
+ * Constructs a new Thread with a runnable object and name provided. The new
+ * Thread will belong to the same ThreadGroup as the Thread calling this
+ * constructor.
+ *
+ * @param runnable
+ * a java.lang.Runnable whose method <code>run</code> will be
+ * executed by the new Thread
+ * @param threadName
+ * Name for the Thread being created
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(Runnable runnable, String threadName) {
+ super();
+ runnableSlot = runnable;
+ name = threadName;
+ vmThread = new VMThread();
+
+ }
+
+ /**
+ * Constructs a new Thread with no runnable object and the name provided.
+ * The new Thread will belong to the same ThreadGroup as the Thread calling
+ * this constructor.
+ *
+ * @param threadName
+ * Name for the Thread being created
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ */
+ public Thread(String threadName) {
+ super();
+ name = threadName;
+ vmThread = new VMThread();
+ }
+
+ /**
+ * Constructs a new Thread with a runnable object and a newly generated
+ * name. The new Thread will belong to the ThreadGroup passed as parameter.
+ *
+ * @param group
+ * ThreadGroup to which the new Thread will belong
+ * @param runnable
+ * a java.lang.Runnable whose method <code>run</code> will be
+ * executed by the new Thread
+ * @exception SecurityException
+ * if <code>group.checkAccess()</code> fails with a
+ * SecurityException
+ * @exception IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager
+ */
+ public Thread(ThreadGroup gr, Runnable runnable) {
+ super();
+ group = gr;
+ runnableSlot = runnable;
+ vmThread = new VMThread();
+ }
+
+ /**
+ * Constructs a new Thread with a runnable object, the given name and
+ * belonging to the ThreadGroup passed as parameter.
+ *
+ * @param group
+ * ThreadGroup to which the new Thread will belong
+ * @param runnable
+ * a java.lang.Runnable whose method <code>run</code> will be
+ * executed by the new Thread
+ * @param threadName
+ * Name for the Thread being created
+ * @param stack
+ * Platform dependent stack size
+ * @exception SecurityException
+ * if <code>group.checkAccess()</code> fails with a
+ * SecurityException
+ * @exception IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager
+ */
+ public Thread(ThreadGroup gr, Runnable runnable, String threadName,
+ long stack) {
+ super();
+ group = gr;
+ runnableSlot = runnable;
+ name = threadName;
+ vmThread = new VMThread();
+ }
+
+ /**
+ * Constructs a new Thread with a runnable object, the given name and
+ * belonging to the ThreadGroup passed as parameter.
+ *
+ * @param group
+ * ThreadGroup to which the new Thread will belong
+ * @param runnable
+ * a java.lang.Runnable whose method <code>run</code> will be
+ * executed by the new Thread
+ * @param threadName
+ * Name for the Thread being created
+ * @exception SecurityException
+ * if <code>group.checkAccess()</code> fails with a
+ * SecurityException
+ * @exception IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.Runnable
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager
+ */
+ public Thread(ThreadGroup gr, Runnable runnable, String threadName) {
+ super();
+ group = gr;
+ runnableSlot = runnable;
+ name = threadName;
+ vmThread = new VMThread();
+ }
+
+ /**
+ * Constructs a new Thread with no runnable object, the given name and
+ * belonging to the ThreadGroup passed as parameter.
+ *
+ * @param group
+ * ThreadGroup to which the new Thread will belong
+ * @param threadName
+ * Name for the Thread being created
+ * @exception SecurityException
+ * if <code>group.checkAccess()</code> fails with a
+ * SecurityException
+ * @exception IllegalThreadStateException
+ * if <code>group.destroy()</code> has already been done
+ * @see java.lang.ThreadGroup
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager
+ */
+ public Thread(ThreadGroup gr, String threadName) {
+ super();
+ group = gr;
+ name = threadName;
+ vmThread = new VMThread();
+ }
+
+ /**
+ * Returns the number of active threads in the running thread's ThreadGroup
+ *
+ * @return Number of Threads
+ */
+ public static int activeCount() {
+ return 1; //fixit -- this works for simple "hello world" bring up but is obviously wrong
+ }
+
+ /**
+ * This method is used for operations that require approval from a
+ * SecurityManager. If there's none installed, this method is a no-op. If
+ * there's a SecurityManager installed ,
+ * <code>checkAccess(Ljava.lang.Thread;)</code> is called for that
+ * SecurityManager.
+ *
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager
+ */
+ public final void checkAccess() {
+ return; //fixit -- this works for simple "hello world" bring up but is obviously wrong
+ }
+
+ /**
+ * Returns the number of stack frames in this thread.
+ *
+ * @return Number of stack frames
+ * @deprecated The results of this call were never well defined. To make
+ * things worse, it would depend if the Thread was suspended or
+ * not, and suspend was deprecated too.
+ */
+ public int countStackFrames() {
+ return vmThread.countStackFrames();
+ }
+
+ /**
+ * Answers the instance of Thread that corresponds to the running Thread
+ * which calls this method.
+ *
+ * @return a java.lang.Thread corresponding to the code that called
+ * <code>currentThread()</code>
+ */
+ public static Thread currentThread() {
+ return VMThread.currentThread();
+ };
+
+ /**
+ * Destroys the receiver without any monitor cleanup. Not implemented.
+ *
+ */
+ public void destroy() {
+ return; //fixit -- a "nop" is a reasonable implementation of a seldom used API, its never called for simple "hello world" app
+ }
+
+ /**
+ * Prints a text representation of the stack for this Thread.
+ *
+ */
+ public static void dumpStack() {
+ //VMThrowable.getStackTrace(this); // fixit -- not required for simple "hello world" demo
+ }
+
+ /**
+ * Copies an array with all Threads which are in the same ThreadGroup as the
+ * receiver - and subgroups - into the array <code>threads</code> passed
+ * as parameter. If the array passed as parameter is too small no exception
+ * is thrown - the extra elements are simply not copied.
+ *
+ * @param threads
+ * array into which the Threads will be copied
+ * @return How many Threads were copied over
+ * @exception SecurityException
+ * if the installed SecurityManager fails
+ * <code>checkAccess(Ljava.lang.Thread;)</code>
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager
+ */
+ public static int enumerate(Thread[] threads) {
+ return 0; //fixit -- returning zero is good enough for simple "hello world" demo
+ }
+
+ /**
+ * Returns the context ClassLoader for the receiver.
+ *
+ * @return ClassLoader The context ClassLoader
+ * @see java.lang.ClassLoader
+ * @see #getContextClassLoader()
+ */
+ public ClassLoader getContextClassLoader() {
+ //fixit -- returning null is good enough for simple "hello world" demo
+ return null;
+ }
+
+ /**
+ * Answers the name of the receiver.
+ *
+ * @return the receiver's name (a java.lang.String)
+ */
+ public final String getName() {
+ String ss = name + this.toString();
+ return this.toString(); // fixit -- find out the proper construction for thread names
+ }
+
+ /**
+ * Answers the priority of the receiver.
+ *
+ * @return the receiver's priority (an <code>int</code>)
+ * @see Thread#setPriority
+ */
+ public final int getPriority() {
+ return 0; //fixit -- correct thread priority is not essential to demoing simple "hello world"
+ }
+
+ /**
+ * Answers the ThreadGroup to which the receiver belongs
+ *
+ * @return the receiver's ThreadGroup
+ */
+ public final ThreadGroup getThreadGroup() {
+ return group; //fixit -- ThreadGroups are not essential to demoing simple "hello world"
+ }
+
+ /**
+ * A sample implementation of this method is provided by the reference
+ * implementation. It must be included, as it is called by ThreadLocal.get()
+ * and InheritableThreadLocal.get(). Return the value associated with the
+ * ThreadLocal in the receiver
+ *
+ * @param local
+ * ThreadLocal to perform the lookup
+ * @return the value of the ThreadLocal
+ * @see #setThreadLocal
+ */
+ Object getThreadLocal(ThreadLocal local) {
+ return threadLocalSlot.get(); //fixit -- this code looks correct. It needs to be verified/confirmed it is correct
+ }
+
+ /**
+ * Posts an interrupt request to the receiver
+ *
+ * @exception SecurityException
+ * if <code>group.checkAccess()</code> fails with a
+ * SecurityException
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager
+ * @see Thread#interrupted
+ * @see Thread#isInterrupted
+ */
+ public void interrupt() {
+ vmThread.interrupt();
+ return;
+ }
+
+ /**
+ * Answers a <code>boolean</code> indicating whether the current Thread (
+ * <code>currentThread()</code>) has a pending interrupt request (
+ * <code>true</code>) or not (<code>false</code>). It also has the
+ * side-effect of clearing the flag.
+ *
+ * @return a <code>boolean</code>
+ * @see Thread#currentThread
+ * @see Thread#interrupt
+ * @see Thread#isInterrupted
+ */
+ public static boolean interrupted() {
+ return VMThread.interrupted();
+ };
+
+ /**
+ * Answers <code>true</code> if the receiver has already been started and
+ * still runs code (hasn't died yet). Answers <code>false</code> either if
+ * the receiver hasn't been started yet or if it has already started and run
+ * to completion and died.
+ *
+ * @return a <code>boolean</code>
+ * @see Thread#start
+ */
+ public final boolean isAlive() {
+ return false; //fixit -- obviously incorrect but probably OK for simple "hello world" demo
+ }
+
+ /**
+ * Answers a <code>boolean</code> indicating whether the receiver is a
+ * daemon Thread (<code>true</code>) or not (<code>false</code>) A
+ * daemon Thread only runs as long as there are non-daemon Threads running.
+ * When the last non-daemon Thread ends, the whole program ends no matter if
+ * it had daemon Threads still running or not.
+ *
+ * @return a <code>boolean</code>
+ * @see Thread#setDaemon
+ */
+ public final boolean isDaemon() {
+ return daemon;
+ }
+
+ /**
+ * Answers a <code>boolean</code> indicating whether the receiver has a
+ * pending interrupt request (<code>true</code>) or not (
+ * <code>false</code>)
+ *
+ * @return a <code>boolean</code>
+ * @see Thread#interrupt
+ * @see Thread#interrupted
+ */
+ public boolean isInterrupted() {
+ return vmThread.isInterrupted();
+ }
+
+ /**
+ * Blocks the current Thread (<code>Thread.currentThread()</code>) until
+ * the receiver finishes its execution and dies.
+ *
+ * @exception InterruptedException
+ * if <code>interrupt()</code> was called for the receiver
+ * while it was in the <code>join()</code> call
+ * @see Object#notifyAll
+ * @see java.lang.ThreadDeath
+ */
+ public final void join() throws InterruptedException {
+ //fixit -- obviously incorrect but it seems OK for simple "hello world" demo
+ return;
+ }
+
+ /**
+ * Blocks the current Thread (<code>Thread.currentThread()</code>) until
+ * the receiver finishes its execution and dies or the specified timeout
+ * expires, whatever happens first.
+ *
+ * @param timeoutInMilliseconds
+ * The maximum time to wait (in milliseconds).
+ * @exception InterruptedException
+ * if <code>interrupt()</code> was called for the receiver
+ * while it was in the <code>join()</code> call
+ * @see Object#notifyAll
+ * @see java.lang.ThreadDeath
+ */
+ public final void join(long timeoutInMilliseconds)
+ throws InterruptedException {
+ //fixit -- obviously incorrect but it seems OK for simple "hello world" demo
+ return;
+ }
+
+ /**
+ * Blocks the current Thread (<code>Thread.currentThread()</code>) until
+ * the receiver finishes its execution and dies or the specified timeout
+ * expires, whatever happens first.
+ *
+ * @param timeoutInMilliseconds
+ * The maximum time to wait (in milliseconds).
+ * @param nanos
+ * Extra nanosecond precision
+ * @exception InterruptedException
+ * if <code>interrupt()</code> was called for the receiver
+ * while it was in the <code>join()</code> call
+ * @see Object#notifyAll
+ * @see java.lang.ThreadDeath
+ */
+ public final void join(long timeoutInMilliseconds, int nanos)
+ throws InterruptedException {
+ //fixit -- obviously incorrect but it seems OK for simple "hello world" demo
+ return;
+ }
+
+ /**
+ * This is a no-op if the receiver was never suspended, or suspended and
+ * already resumed. If the receiver is suspended, however, makes it resume
+ * to the point where it was when it was suspended.
+ *
+ * @exception SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @see Thread#suspend()
+ * @deprecated Used with deprecated method Thread.suspend().
+ */
+ public final void resume() {
+ //fixit -- obviously incorrect but it seems OK for simple "hello world" demo
+ return;
+ }
+
+ /**
+ * Calls the <code>run()</code> method of the Runnable object the receiver
+ * holds. If no Runnable is set, does nothing.
+ *
+ * @see Thread#start
+ */
+ public void run() {
+ if (runnableSlot == null)
+ return;
+ runnableSlot.run();
+ }
+
+ /**
+ * Set the context ClassLoader for the receiver.
+ *
+ * @param cl
+ * The context ClassLoader
+ * @see java.lang.ClassLoader
+ * @see #getContextClassLoader()
+ */
+ public void setContextClassLoader(ClassLoader cl) {
+ //fixit -- this incorrect code is good enough to allow simple "hello world" demo to run
+ return;
+ }
+
+ /**
+ * Set if the receiver is a daemon Thread or not. This can only be done
+ * before the Thread starts running.
+ *
+ * @param isDaemon
+ * A boolean indicating if the Thread should be daemon or not
+ * @exception SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @see Thread#isDaemon
+ */
+ public final void setDaemon(boolean isDaemon) {
+ daemon = isDaemon;
+ }
+
+ /**
+ * Sets the name of the receiver.
+ *
+ * @param threadName
+ * new name for the Thread
+ * @exception SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @see Thread#getName
+ */
+ public final void setName(String threadName) {
+ name = threadName;
+ }
+
+ /**
+ * Sets the priority of the receiver. Note that the final priority set may
+ * not be the parameter that was passed - it will depend on the receiver's
+ * ThreadGroup. The priority cannot be set to be higher than the receiver's
+ * ThreadGroup's maxPriority().
+ *
+ * @param priority
+ * new priority for the Thread
+ * @exception SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @exception IllegalArgumentException
+ * if the new priority is greater than Thread.MAX_PRIORITY or
+ * less than Thread.MIN_PRIORITY
+ * @see Thread#getPriority
+ */
+ public final void setPriority(int priority) {
+ vmThread.nativeSetPriority(priority);
+ return; //fixit -- this is incorrect code but its good enough for simple "hello world" demo
+ }
+
+ /**
+ * A sample implementation of this method is provided by the reference
+ * implementation. It must be included, as it is called by ThreadLocal.set()
+ * and InheritableThreadLocal.set(). Set the value associated with the
+ * ThreadLocal in the receiver to be <code>value</code>.
+ *
+ * @param local
+ * ThreadLocal to set
+ * @param value
+ * new value for the ThreadLocal
+ * @see #getThreadLocal
+ */
+ void setThreadLocal(ThreadLocal local, Object value) {
+ threadLocalSlot.set(value);
+ return;
+ }
+
+ /**
+ * Causes the thread which sent this message to sleep an interval of time
+ * (given in milliseconds). The precision is not guaranteed - the Thread may
+ * sleep more or less than requested.
+ *
+ * @param time
+ * The time to sleep in milliseconds.
+ * @exception InterruptedException
+ * if <code>interrupt()</code> was called for this Thread
+ * while it was sleeping
+ * @see Thread#interrupt()
+ */
+
+ public static void sleep(long time) throws InterruptedException {
+ //fixit -- this is incorrect code that is good enough to allow simple "hello world" demo to run
+ return;
+ }
+
+ /**
+ * Causes the thread which sent this message to sleep an interval of time
+ * (given in milliseconds). The precision is not guaranteed - the Thread may
+ * sleep more or less than requested.
+ *
+ * @param time
+ * The time to sleep in milliseconds.
+ * @param nanos
+ * Extra nanosecond precision
+ * @exception InterruptedException
+ * if <code>interrupt()</code> was called for this Thread
+ * while it was sleeping
+ * @see Thread#interrupt()
+ */
+ public static void sleep(long time, int nanos) throws InterruptedException {
+ //fixit -- this is incorrect code that is good enough to allow simple "hello world" demo to run
+ return;
+ };
+
+ /**
+ * Starts the new Thread of execution. The <code>run()</code> method of
+ * the receiver will be called by the receiver Thread itself (and not the
+ * Thread calling <code>start()</code>).
+ *
+ * @exception IllegalThreadStateException
+ * Unspecified in the Java language specification
+ * @see Thread#run
+ */
+ public void start() {
+ //debugging aid -- the s1 and s2 strings are easy to spot in jchevm since string creation calls into the jvm
+ String s1 = "Thread.start() -- TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT";
+ int stackSize = 1024 * 64;
+ vmThread.thread = this;
+ if (java.lang.ThreadGroup.root == null)
+ {
+ java.lang.ThreadGroup tg = new java.lang.ThreadGroup();
+ java.lang.ThreadGroup.root = tg;
+ }
+ group = java.lang.ThreadGroup.root; //wjw temporary, during bringup
+ vmThread.start(stackSize);
+ String s2 = "Thread.start() -- BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
+ int xx = 0;
+ /*
+ while (true)
+ {
+ xx++;
+ }
+ */
+ return;
+ }
+
+ /**
+ * Requests the receiver Thread to stop and throw ThreadDeath. The Thread is
+ * resumed if it was suspended and awakened if it was sleeping, so that it
+ * can proceed to throw ThreadDeath.
+ *
+ * @exception SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @deprecated
+ */
+ public final void stop() {
+ //fixit -- doing a "nop" will allow simple "hello world" app to run
+ return;
+ }
+
+ /**
+ * Requests the receiver Thread to stop and throw the
+ * <code>throwable()</code>. The Thread is resumed if it was suspended
+ * and awakened if it was sleeping, so that it can proceed to throw the
+ * <code>throwable()</code>.
+ *
+ * @param throwable
+ * Throwable object to be thrown by the Thread
+ * @exception SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @exception NullPointerException
+ * if <code>throwable()</code> is <code>null</code>
+ * @deprecated
+ */
+ public final void stop(Throwable throwable) {
+ //fixit -- doing a "nop" will allow simple "hello world" app to run
+ return;
+ }
+
+ /**
+ * This is a no-op if the receiver is suspended. If the receiver
+ * <code>isAlive()</code> however, suspended it until
+ * <code>resume()</code> is sent to it. Suspend requests are not queued,
+ * which means that N requests are equivalenet to just one - only one resume
+ * request is needed in this case.
+ *
+ * @exception SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @see Thread#resume()
+ * @deprecated May cause deadlocks.
+ */
+ public final void suspend() {
+ //fixit -- doing a "nop" will allow simple "hello world" app to run
+ return;
+ }
+
+ /**
+ * Answers a string containing a concise, human-readable description of the
+ * receiver.
+ *
+ * @return a printable representation for the receiver.
+ */
+ public String toString() {
+ return name.toString();
+ }
+
+ /**
+ * Causes the thread which sent this message to yield execution to another
+ * Thread that is ready to run. The actual scheduling is
+ * implementation-dependent.
+ *
+ */
+ public static void yield() {
+ VMThread.yield();
+ };
+
+ /**
+ * Returns whether the current thread has a monitor lock on the specified
+ * object.
+ *
+ * @param object
+ * the object to test for the monitor lock
+ * @return true when the current thread has a monitor lock on the specified
+ * object
+ */
+ public static boolean holdsLock(Object object) {
+ return false; //fixit -- simply returning "false" is good enough to get simple "hello world" demo going
+ };
+
+}
+
Propchange: incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/Thread.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/ThreadGroup.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/ThreadGroup.java?rev=398726&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/ThreadGroup.java (added)
+++ incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/ThreadGroup.java Mon May 1 16:11:39 2006
@@ -0,0 +1,861 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.lang;
+
+/**
+ * An implementation of this class is provided, but the documented constructors
+ * are used by the vm specific implementation to create the required "system"
+ * and "main" ThreadGroups. The documented methods are used by java.lang.Thread
+ * to add and remove Threads from their ThreadGroups.
+ *
+ * ThreadGroups are containers of Threads and ThreadGroups, therefore providing
+ * a tree-like structure to organize Threads. The root ThreadGroup name is
+ * "system" and it has no parent ThreadGroup. All other ThreadGroups have
+ * exactly one parent ThreadGroup. All Threads belong to exactly one
+ * ThreadGroup.
+ *
+ * @see Thread
+ * @see SecurityManager
+ */
+
+public class ThreadGroup {
+
+ static ThreadGroup root; // added for bootstrap.c support
+ // Name of this ThreadGroup
+ private String name;
+
+ // Maximum priority for Threads inside this ThreadGroup
+ private int maxPriority = Thread.MAX_PRIORITY;
+
+ // The ThreadGroup to which this ThreadGroup belongs
+ ThreadGroup parent = null;
+
+ int numThreads = 0;
+
+ // The Threads this ThreadGroup contains
+ private Thread[] childrenThreads = new Thread[5];
+
+ // The number of children groups
+ int numGroups = 0;
+
+ // The ThreadGroups this ThreadGroup contains
+ private ThreadGroup[] childrenGroups = new ThreadGroup[3];
+
+ // Locked when using the childrenGroups field
+ private Object childrenGroupsLock = new Object();
+
+ // Locked when using the childrenThreads field
+ private Object childrenThreadsLock = new Object();
+
+ // Whether this ThreadGroup is a daemon ThreadGroup or not
+ private boolean isDaemon = false;
+
+ // Whether this ThreadGroup has already been destroyed or not
+ private boolean isDestroyed = false;
+
+ // Memory space to associate all new threads with
+ private long memorySpace;
+
+ /**
+ * Used by the JVM to create the "system" ThreadGroup. Construct a
+ * ThreadGroup instance, and assign the name "system".
+ */
+ ThreadGroup() {
+ name = "system";
+ }
+
+ /**
+ * Constructs a new ThreadGroup with the name provided. The new ThreadGroup
+ * will be child of the ThreadGroup to which the
+ * <code>Thread.currentThread()</code> belongs.
+ *
+ * @param name
+ * Name for the ThreadGroup being created
+ *
+ * @throws SecurityException
+ * if <code>checkAccess()</code> for the parent group fails
+ * with a SecurityException
+ *
+ * @see java.lang.Thread#currentThread
+ */
+
+ public ThreadGroup(String name) {
+ this(Thread.currentThread().getThreadGroup(), name);
+ }
+
+ /**
+ * Constructs a new ThreadGroup with the name provided, as child of the
+ * ThreadGroup <code>parent</code>
+ *
+ * @param parent
+ * Parent ThreadGroup
+ * @param name
+ * Name for the ThreadGroup being created
+ *
+ * @throws NullPointerException
+ * if <code>parent<code> is <code>null<code>
+ * @throws SecurityException if <code>checkAccess()</code> for the parent group fails with a SecurityException
+ * @throws IllegalThreadStateException if <code>parent<code> has been destroyed already
+ */
+ public ThreadGroup(ThreadGroup parent, String name) {
+ super();
+ if (Thread.currentThread() != null) {
+ // If parent is null we must throw NullPointerException, but that
+ // will be done "for free" with the message send below
+ parent.checkAccess();
+ }
+
+ this.name = name;
+ this.setParent(parent);
+ if (parent != null) {
+ this.setMaxPriority(parent.getMaxPriority());
+ if (parent.isDaemon())
+ this.setDaemon(true);
+ }
+ }
+
+ /**
+ * Initialize the "main" ThreadGroup
+ */
+ ThreadGroup(ThreadGroup parent) {
+ this.name = "main";
+ this.setParent(parent);
+ }
+
+ /**
+ * Returns the number of Threads which are children of the receiver,
+ * directly or indirectly.
+ *
+ * @return Number of children Threads
+ */
+
+ public int activeCount() {
+ int count = numThreads;
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++)
+ count += this.childrenGroups[i].activeCount();
+ }
+ return count;
+ }
+
+ /**
+ * Returns the number of ThreadGroups which are children of the receiver,
+ * directly or indirectly.
+ *
+ * @return Number of children ThreadGroups
+ */
+ public int activeGroupCount() {
+ int count = 0;
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++)
+ // One for this group & the subgroups
+ count += 1 + this.childrenGroups[i].activeGroupCount();
+ }
+ return count;
+ }
+
+ /**
+ * Adds a Thread to the receiver. This should only be visible to class
+ * java.lang.Thread, and should only be called when a new Thread is created
+ * and initialized by the constructor.
+ *
+ * @param thread
+ * Thread to add to the receiver
+ *
+ * @throws IllegalThreadStateException
+ * if the receiver has been destroyed already
+ *
+ * @see #remove(java.lang.Thread)
+ */
+ final void addThread(Thread thread)
+ {
+ add(thread);
+ }
+ final void add(Thread thread) throws IllegalThreadStateException {
+ synchronized (this.childrenThreadsLock) {
+ if (!isDestroyed) {
+ if (childrenThreads.length == numThreads) {
+ Thread[] newThreads = new Thread[childrenThreads.length * 2];
+ System.arraycopy(childrenThreads, 0, newThreads, 0,
+ numThreads);
+ newThreads[numThreads++] = thread;
+ childrenThreads = newThreads;
+ } else
+ childrenThreads[numThreads++] = thread;
+ } else
+ throw new IllegalThreadStateException();
+ }
+ }
+
+ /**
+ * Adds a ThreadGroup to the receiver.
+ *
+ * @param g
+ * ThreadGroup to add to the receiver
+ *
+ * @throws IllegalThreadStateException
+ * if the receiver has been destroyed already
+ */
+ private void add(ThreadGroup g) throws IllegalThreadStateException {
+ synchronized (this.childrenGroupsLock) {
+ if (!isDestroyed) {
+ if (childrenGroups.length == numGroups) {
+ ThreadGroup[] newGroups = new ThreadGroup[childrenGroups.length * 2];
+ System
+ .arraycopy(childrenGroups, 0, newGroups, 0,
+ numGroups);
+ newGroups[numGroups++] = g;
+ childrenGroups = newGroups;
+ } else
+ childrenGroups[numGroups++] = g;
+ } else
+ throw new IllegalThreadStateException();
+ }
+ }
+
+ /**
+ * The definition of this method depends on the deprecated method
+ * <code>suspend()</code>. The behavior of this call was never specified.
+ *
+ * @param b
+ * Used to control low memory implicit suspension
+ *
+ * @deprecated Required deprecated method suspend().
+ */
+ public boolean allowThreadSuspension(boolean b) {
+ // fixit -- from the comments immediately above, not really sure what is supposed to be implemented
+ // in any case, returning "true" is good enough for "hello world" demo
+ return true;
+ }
+
+ /**
+ * If there is a SecurityManager installed, call <code>checkAccess</code>
+ * in it passing the receiver as parameter, otherwise do nothing.
+ */
+ public final void checkAccess() {
+ // Forwards the message to the SecurityManager (if there's one) passing
+ // the receiver as parameter
+ SecurityManager currentManager = System.getSecurityManager();
+ if (currentManager != null)
+ currentManager.checkAccess(this);
+ }
+
+ /**
+ * Destroys the receiver and recursively all its subgroups. It is only legal
+ * to destroy a ThreadGroup that has no Threads. Any daemon ThreadGroup is
+ * destroyed automatically when it becomes empty (no Threads and no
+ * ThreadGroups in it).
+ *
+ * @throws IllegalThreadStateException
+ * if the receiver or any of its subgroups has been destroyed
+ * already
+ * @throws SecurityException
+ * if <code>this.checkAccess()</code> fails with a
+ * SecurityException
+ */
+
+ public final void destroy() {
+ checkAccess();
+
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenThreadsLock) {
+ synchronized (this.childrenGroupsLock) {
+ int toDestroy = numGroups;
+ // Call recursively for subgroups
+ for (int i = 0; i < toDestroy; i++) {
+ // We always get the first element - remember, when the
+ // child dies it removes itself from our collection. See
+ // below.
+ this.childrenGroups[0].destroy();
+ }
+
+ if (parent != null)
+ parent.remove(this);
+
+ // Now that the ThreadGroup is really destroyed it can be tagged
+ // as so
+ this.isDestroyed = true;
+ }
+ }
+ }
+
+ /*
+ * Auxiliary method that destroys the receiver and recursively all its
+ * subgroups if the receiver is a daemon ThreadGroup.
+ *
+ * @see #destroy
+ * @see #setDaemon
+ * @see #isDaemon
+ */
+ private void destroyIfEmptyDaemon() {
+ // Has to be non-destroyed daemon to make sense
+ synchronized (this.childrenThreadsLock) {
+ if (isDaemon && !isDestroyed && numThreads == 0) {
+ synchronized (this.childrenGroupsLock) {
+ if (numGroups == 0)
+ destroy();
+ }
+ }
+ }
+ }
+
+ /**
+ * Copies an array with all Threads which are children of the receiver
+ * (directly or indirectly) into the array <code>threads</code> passed as
+ * parameters. If the array passed as parameter is too small no exception is
+ * thrown - the extra elements are simply not copied.
+ *
+ * @param threads
+ * Thread array into which the Threads will be copied
+ * @return How many Threads were copied over
+ *
+ */
+ public int enumerate(Thread[] threads) {
+ return enumerate(threads, true);
+ }
+
+ /**
+ * Copies an array with all Threads which are children of the receiver into
+ * the array <code>threads</code> passed as parameter. Children Threads of
+ * subgroups are recursively copied as well if parameter
+ * <code>recurse</code> is <code>true</code>.
+ *
+ * If the array passed as parameter is too small no exception is thrown -
+ * the extra elements are simply not copied.
+ *
+ * @param threads
+ * array into which the Threads will be copied
+ * @param recurse
+ * Indicates whether Threads in subgroups should be recursively
+ * copied as well or not
+ * @return How many Threads were copied over
+ *
+ */
+ public int enumerate(Thread[] threads, boolean recurse) {
+ return enumerateGeneric(threads, recurse, 0, true);
+ }
+
+ /**
+ * Copies an array with all ThreadGroups which are children of the receiver
+ * (directly or indirectly) into the array <code>groups</code> passed as
+ * parameters. If the array passed as parameter is too small no exception is
+ * thrown - the extra elements are simply not copied.
+ *
+ * @param groups
+ * array into which the ThreadGroups will be copied
+ * @return How many ThreadGroups were copied over
+ *
+ */
+ public int enumerate(ThreadGroup[] groups) {
+ return enumerate(groups, true);
+ }
+
+ /**
+ * Copies an array with all ThreadGroups which are children of the receiver
+ * into the array <code>groups</code> passed as parameter. Children
+ * ThreadGroups of subgroups are recursively copied as well if parameter
+ * <code>recurse</code> is <code>true</code>.
+ *
+ * If the array passed as parameter is too small no exception is thrown -
+ * the extra elements are simply not copied.
+ *
+ * @param groups
+ * array into which the ThreadGroups will be copied
+ * @param recurse
+ * Indicates whether ThreadGroups in subgroups should be
+ * recursively copied as well or not
+ * @return How many ThreadGroups were copied over
+ *
+ */
+ public int enumerate(ThreadGroup[] groups, boolean recurse) {
+ return enumerateGeneric(groups, recurse, 0, false);
+ }
+
+ /**
+ * Copies into <param>enumeration</param> starting at
+ * </param>enumerationIndex</param> all Threads or ThreadGroups in the
+ * receiver. If </param>recurse</param> is true, recursively enumerate the
+ * elements in subgroups.
+ *
+ * If the array passed as parameter is too small no exception is thrown -
+ * the extra elements are simply not copied.
+ *
+ * @param enumeration
+ * array into which the elements will be copied
+ * @param recurse
+ * Indicates whether </param>recurseCollection</param> should be
+ * enumerated or not
+ * @param enumerationIndex
+ * Indicates in which position of the enumeration array we are
+ * @param enumeratingThreads
+ * Indicates whether we are enumerating Threads or ThreadGroups
+ * @return How many elements were enumerated/copied over
+ */
+ private int enumerateGeneric(Object[] enumeration, boolean recurse,
+ int enumerationIndex, boolean enumeratingThreads) {
+ checkAccess();
+
+ Object[] immediateCollection = enumeratingThreads ? (Object[]) childrenThreads
+ : (Object[]) childrenGroups;
+ Object syncLock = enumeratingThreads ? childrenThreadsLock
+ : childrenGroupsLock;
+
+ synchronized (syncLock) { // Lock this subpart of the tree as we walk
+ for (int i = enumeratingThreads ? numThreads : numGroups; --i >= 0;) {
+ if (!enumeratingThreads
+ || ((Thread) immediateCollection[i]).isAlive()) {
+ if (enumerationIndex >= enumeration.length)
+ return enumerationIndex;
+ enumeration[enumerationIndex++] = immediateCollection[i];
+ }
+ }
+ }
+
+ if (recurse) { // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++) {
+ if (enumerationIndex >= enumeration.length)
+ return enumerationIndex;
+ enumerationIndex = childrenGroups[i].enumerateGeneric(
+ enumeration, recurse, enumerationIndex,
+ enumeratingThreads);
+ }
+ }
+ }
+ return enumerationIndex;
+ }
+
+ /**
+ * Answers the maximum allowed priority for a Thread in the receiver.
+ *
+ * @return the maximum priority (an <code>int</code>)
+ *
+ * @see #setMaxPriority
+ */
+ public final int getMaxPriority() {
+ return maxPriority;
+ }
+
+ /**
+ * Answers the name of the receiver.
+ *
+ * @return the receiver's name (a java.lang.String)
+ */
+ public final String getName() {
+ return name;
+ }
+
+ /**
+ * Answers the receiver's parent ThreadGroup. It can be null if the receiver
+ * is the the root ThreadGroup.
+ *
+ * @return the parent ThreadGroup
+ *
+ */
+ public final ThreadGroup getParent() {
+ if (parent != null)
+ parent.checkAccess();
+ return parent;
+ }
+
+ /**
+ * Interrupts every Thread in the receiver and recursively in all its
+ * subgroups.
+ *
+ * @throws SecurityException
+ * if <code>this.checkAccess()</code> fails with a
+ * SecurityException
+ *
+ * @see Thread#interrupt
+ */
+ public final void interrupt() {
+ checkAccess();
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenThreadsLock) {
+ for (int i = 0; i < numThreads; i++)
+ this.childrenThreads[i].interrupt();
+ }
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++)
+ this.childrenGroups[i].interrupt();
+ }
+ }
+
+ /**
+ * Answers true if the receiver is a daemon ThreadGroup, false otherwise.
+ *
+ * @return if the receiver is a daemon ThreadGroup
+ *
+ * @see #setDaemon
+ * @see #destroy
+ */
+ public final boolean isDaemon() {
+ return isDaemon;
+ }
+
+ /**
+ * Answers true if the receiver has been destroyed already, false otherwise.
+ *
+ * @return if the receiver has been destroyed already
+ *
+ * @see #destroy
+ */
+ public boolean isDestroyed() {
+ return isDestroyed;
+ }
+
+ /**
+ * Outputs to <code>System.out</code> a text representation of the
+ * hierarchy of Threads and ThreadGroups in the receiver (and recursively).
+ * Proper identation is done to suggest the nesting of groups inside groups
+ * and threads inside groups.
+ */
+ public void list() {
+ // We start in a fresh line
+ //System.out.println();
+ list(0);
+ }
+
+ /*
+ * Outputs to <code>System.out</code>a text representation of the
+ * hierarchy of Threads and ThreadGroups in the receiver (and recursively).
+ * The identation will be four spaces per level of nesting.
+ *
+ * @param levels How many levels of nesting, so that proper identetion can
+ * be output.
+ */
+ private void list(int levels) {
+ for (int i = 0; i < levels; i++)
+ {
+ //System.out.print(" "); // 4 spaces for each level
+ }
+ // Print the receiver
+ //System.out.println(this.toString());
+
+ // Print the children threads, with 1 extra identation
+ synchronized (this.childrenThreadsLock) {
+ for (int i = 0; i < numThreads; i++) {
+ // children get an extra identation, 4 spaces for each level
+ for (int j = 0; j <= levels; j++)
+ {
+ //System.out.print(" ");
+ //System.out.println(this.childrenThreads[i]);
+ }
+ }
+ }
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++)
+ this.childrenGroups[i].list(levels + 1);
+ }
+ }
+
+ /**
+ * Answers true if the receiver is a direct or indirect parent group of
+ * ThreadGroup <code>g</code>, false otherwise.
+ *
+ * @param g
+ * ThreadGroup to test
+ *
+ * @return if the receiver is parent of the ThreadGroup passed as parameter
+ *
+ */
+ public final boolean parentOf(ThreadGroup g) {
+ while (g != null) {
+ if (this == g)
+ return true;
+ g = g.parent;
+ }
+ return false;
+ }
+
+ /**
+ * Removes a Thread from the receiver. This should only be visible to class
+ * java.lang.Thread, and should only be called when a Thread dies.
+ *
+ * @param thread
+ * Thread to remove from the receiver
+ *
+ * @see #add(Thread)
+ */
+ final void remove(java.lang.Thread thread) {
+ synchronized (this.childrenThreadsLock) {
+ for (int i = 0; i < numThreads; i++) {
+ if (childrenThreads[i].equals(thread)) {
+ numThreads--;
+ System.arraycopy(childrenThreads, i + 1, childrenThreads,
+ i, numThreads - i);
+ childrenThreads[numThreads] = null;
+ break;
+ }
+ }
+ }
+ destroyIfEmptyDaemon();
+ }
+
+ /**
+ * Removes an immediate subgroup from the receiver.
+ *
+ * @param g
+ * Threadgroup to remove from the receiver
+ *
+ * @see #add(Thread)
+ * @see #add(ThreadGroup)
+ */
+ private void remove(ThreadGroup g) {
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++) {
+ if (childrenGroups[i].equals(g)) {
+ numGroups--;
+ System.arraycopy(childrenGroups, i + 1, childrenGroups, i,
+ numGroups - i);
+ childrenGroups[numGroups] = null;
+ break;
+ }
+ }
+ }
+ destroyIfEmptyDaemon();
+ }
+
+ /**
+ * Resumes every Thread in the receiver and recursively in all its
+ * subgroups.
+ *
+ * @throws SecurityException
+ * if <code>this.checkAccess()</code> fails with a
+ * SecurityException
+ *
+ * @see Thread#resume
+ * @see #suspend
+ *
+ * @deprecated Requires deprecated method Thread.resume().
+ */
+ public final void resume() {
+ checkAccess();
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenThreadsLock) {
+ for (int i = 0; i < numThreads; i++)
+ this.childrenThreads[i].resume();
+ }
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++)
+ this.childrenGroups[i].resume();
+ }
+ }
+
+ /**
+ * Configures the receiver to be a daemon ThreadGroup or not. Daemon
+ * ThreadGroups are automatically destroyed when they become empty.
+ *
+ * @param isDaemon
+ * new value defining if receiver should be daemon or not
+ *
+ * @throws SecurityException
+ * if <code>checkAccess()</code> for the parent group fails
+ * with a SecurityException
+ *
+ * @see #isDaemon
+ * @see #destroy
+ */
+ public final void setDaemon(boolean isDaemon) {
+ checkAccess();
+ this.isDaemon = isDaemon;
+ }
+
+ /**
+ * Configures the maximum allowed priority for a Thread in the receiver and
+ * recursively in all its subgroups.
+ *
+ * One can never change the maximum priority of a ThreadGroup to be higher
+ * than it was. Such an attempt will not result in an exception, it will
+ * simply leave the ThreadGroup with its current maximum priority.
+ *
+ * @param newMax
+ * the new maximum priority to be set
+ *
+ * @throws SecurityException
+ * if <code>checkAccess()</code> fails with a
+ * SecurityException
+ * @throws IllegalArgumentException
+ * if the new priority is greater than Thread.MAX_PRIORITY or
+ * less than Thread.MIN_PRIORITY
+ *
+ * @see #getMaxPriority
+ */
+ public final void setMaxPriority(int newMax) {
+ checkAccess();
+
+ if (newMax <= this.maxPriority) {
+ if (newMax < Thread.MIN_PRIORITY)
+ newMax = Thread.MIN_PRIORITY;
+
+ int parentPriority = parent == null ? newMax : parent
+ .getMaxPriority();
+ this.maxPriority = parentPriority <= newMax ? parentPriority
+ : newMax;
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ // ??? why not maxPriority
+ for (int i = 0; i < numGroups; i++)
+ this.childrenGroups[i].setMaxPriority(newMax);
+ }
+ }
+ }
+
+ /**
+ * Sets the parent ThreadGroup of the receiver, and adds the receiver to the
+ * parent's collection of immediate children (if <code>parent</code> is
+ * not <code>null</code>).
+ *
+ * @param parent
+ * The parent ThreadGroup, or null if the receiver is to be the
+ * root ThreadGroup
+ *
+ * @see #getParent
+ * @see #parentOf
+ */
+ private void setParent(ThreadGroup parent) {
+ if (parent != null)
+ parent.add(this);
+ this.parent = parent;
+ }
+
+ /**
+ * Stops every Thread in the receiver and recursively in all its subgroups.
+ *
+ * @throws SecurityException
+ * if <code>this.checkAccess()</code> fails with a
+ * SecurityException
+ *
+ * @see Thread#stop()
+ * @see Thread#stop(Throwable)
+ * @see ThreadDeath
+ *
+ * @deprecated Requires deprecated method Thread.stop().
+ */
+ public final void stop() {
+ if (stopHelper())
+ Thread.currentThread().stop();
+ }
+
+ /**
+ * @deprecated Requires deprecated method Thread.suspend().
+ */
+ private final boolean stopHelper() {
+ checkAccess();
+
+ boolean stopCurrent = false;
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenThreadsLock) {
+ Thread current = Thread.currentThread();
+ for (int i = 0; i < numThreads; i++)
+ if (this.childrenThreads[i] == current) {
+ stopCurrent = true;
+ } else {
+ this.childrenThreads[i].stop();
+ }
+ }
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++)
+ stopCurrent |= this.childrenGroups[i].stopHelper();
+ }
+ return stopCurrent;
+ }
+
+ /**
+ * Suspends every Thread in the receiver and recursively in all its
+ * subgroups.
+ *
+ * @throws SecurityException
+ * if <code>this.checkAccess()</code> fails with a
+ * SecurityException
+ *
+ * @see Thread#suspend
+ * @see #resume
+ *
+ * @deprecated Requires deprecated method Thread.suspend().
+ */
+ public final void suspend() {
+ if (suspendHelper())
+ Thread.currentThread().suspend();
+ }
+
+ /**
+ * @deprecated Requires deprecated method Thread.suspend().
+ */
+ private final boolean suspendHelper() {
+ checkAccess();
+
+ boolean suspendCurrent = false;
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenThreadsLock) {
+ Thread current = Thread.currentThread();
+ for (int i = 0; i < numThreads; i++)
+ if (this.childrenThreads[i] == current) {
+ suspendCurrent = true;
+ } else {
+ this.childrenThreads[i].suspend();
+ }
+ }
+ // Lock this subpart of the tree as we walk
+ synchronized (this.childrenGroupsLock) {
+ for (int i = 0; i < numGroups; i++)
+ suspendCurrent |= this.childrenGroups[i].suspendHelper();
+ }
+ return suspendCurrent;
+ }
+
+ /**
+ * Answers a string containing a concise, human-readable description of the
+ * receiver.
+ *
+ * @return a printable representation for the receiver.
+ */
+ public String toString() {
+ return getClass().getName() + "[name=" + this.getName() + ",maxpri="
+ + this.getMaxPriority() + "]";
+ }
+
+ /**
+ * Any uncaught exception in any Thread has to be forwarded (by the VM) to
+ * the Thread's ThreadGroup by sending this message (uncaughtException).
+ * This allows users to define custom ThreadGroup classes and custom
+ * behavior for when a Thread has an uncaughtException or when it does
+ * (ThreadDeath).
+ *
+ * @param t
+ * Thread with an uncaught exception
+ * @param e
+ * The uncaught exception itself
+ *
+ * @see Thread#stop()
+ * @see Thread#stop(Throwable)
+ * @see ThreadDeath
+ */
+ public void uncaughtException(Thread t, Throwable e) {
+ if (parent != null) {
+ parent.uncaughtException(t, e);
+ } else if (!(e instanceof ThreadDeath)) {
+ // No parent group, has to be 'system' Thread Group
+ e.printStackTrace(System.err);
+ }
+ }
+}
+
Propchange: incubator/harmony/enhanced/classlibadapter/trunk/modules/kernel/src/main/java/java/lang/ThreadGroup.java
------------------------------------------------------------------------------
svn:eol-style = native