You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/03/31 17:34:51 UTC

svn commit: r390443 [3/5] - in /incubator/harmony/enhanced/classlib/trunk: make/ make/patternsets/ modules/kernel/ modules/luni-kernel/ modules/luni-kernel/META-INF/ modules/luni-kernel/src/ modules/luni-kernel/src/main/ modules/luni-kernel/src/main/ja...

Added: incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/System.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/System.java?rev=390443&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/System.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/System.java Fri Mar 31 07:34:47 2006
@@ -0,0 +1,824 @@
+/* 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 {
+		// 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)));
+		out = new String.ConsolePrintStream(new BufferedOutputStream(
+				new FileOutputStream(FileDescriptor.out)));
+		in = new BufferedInputStream(new FileInputStream(FileDescriptor.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);
+	}
+
+	/**
+	 * 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);
+	}
+
+	/**
+	 * 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();
+
+	}
+
+	/**
+	 * 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 native long 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) {
+		RUNTIME.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() {
+		RUNTIME.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) {
+		if (var == null) {
+			throw new NullPointerException();
+		}
+		SecurityManager secMgr = System.getSecurityManager();
+		if (secMgr != null) {
+			secMgr.checkPermission(new RuntimePermission("getenv." + var));
+		}
+		throw new Error();
+	}
+
+	/**
+	 * 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() {
+		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();
+		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();
+		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.
+	 */
+	private static native String[] getPropertyList();
+
+	/**
+	 * Return the requested encoding. 0 - initialize locale 1 - detected
+	 * platform encoding 2 - command line defined file.encoding 3 - command line
+	 * defined os.encoding
+	 */
+	private static native String getEncoding(int type);
+
+	/**
+	 * 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
+	 */
+	public static native int identityHashCode(Object anObject);
+
+	/**
+	 * Loads the specified file as a dynamic library.
+	 * 
+	 * @param pathName
+	 *            the path of the file to be loaded
+	 */
+	public static void load(String pathName) {
+		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() {
+		RUNTIME.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) {
+		Runtime.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
+	 */
+	public static native String mapLibraryName(String userLibName);
+
+	/**
+	 * 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
+	 */
+	private static native void setFieldImpl(String fieldName, Object stream);
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Thread.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Thread.java?rev=390443&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Thread.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Thread.java Fri Mar 31 07:34:47 2006
@@ -0,0 +1,694 @@
+/* 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
+
+	Object slot1;
+
+	Object slot2;
+
+	Object slot3;
+
+	/**
+	 * 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() {
+		super();
+	}
+
+	/**
+	 * 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();
+	}
+
+	/**
+	 * 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();
+	}
+
+	/**
+	 * 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();
+	}
+
+	/**
+	 * 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 group, Runnable runnable) {
+		super();
+	}
+
+	/**
+	 * 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 group, Runnable runnable, String threadName,
+			long stack) {
+		super();
+	}
+
+	/**
+	 * 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 group, Runnable runnable, String threadName) {
+		super();
+	}
+
+	/**
+	 * 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 group, String threadName) {
+		super();
+	}
+
+	/**
+	 * Returns the number of active threads in the running thread's ThreadGroup
+	 * 
+	 * @return Number of Threads
+	 */
+	public static int activeCount() {
+		return 0;
+	}
+
+	/**
+	 * 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;
+	}
+
+	/**
+	 * 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 0;
+	}
+
+	/**
+	 * 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 null;
+	};
+
+	/**
+	 * Destroys the receiver without any monitor cleanup. Not implemented.
+	 * 
+	 * @deprecated Not implemented.
+	 */
+	public void destroy() {
+		return;
+	}
+
+	/**
+	 * Prints a text representation of the stack for this Thread.
+	 * 
+	 */
+	public static void dumpStack() {
+		return;
+	}
+
+	/**
+	 * 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;
+	}
+
+	/**
+	 * Returns the context ClassLoader for the receiver.
+	 * 
+	 * @return ClassLoader The context ClassLoader
+	 * @see java.lang.ClassLoader
+	 * @see #getContextClassLoader()
+	 */
+	public ClassLoader getContextClassLoader() {
+		return null;
+	}
+
+	/**
+	 * Answers the name of the receiver.
+	 * 
+	 * @return the receiver's name (a java.lang.String)
+	 */
+	public final String getName() {
+		return null;
+	}
+
+	/**
+	 * Answers the priority of the receiver.
+	 * 
+	 * @return the receiver's priority (an <code>int</code>)
+	 * @see Thread#setPriority
+	 */
+	public final int getPriority() {
+		return 0;
+	}
+
+	/**
+	 * Answers the ThreadGroup to which the receiver belongs
+	 * 
+	 * @return the receiver's ThreadGroup
+	 */
+	public final ThreadGroup getThreadGroup() {
+		return null;
+	}
+
+	/**
+	 * 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 null;
+	}
+
+	/**
+	 * 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() {
+		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 false;
+	};
+
+	/**
+	 * 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;
+	}
+
+	/**
+	 * 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 false;
+	}
+
+	/**
+	 * 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 false;
+	}
+
+	/**
+	 * 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 {
+		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 {
+		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 {
+		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() {
+		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() {
+		return;
+	}
+
+	/**
+	 * Set the context ClassLoader for the receiver.
+	 * 
+	 * @param cl
+	 *            The context ClassLoader
+	 * @see java.lang.ClassLoader
+	 * @see #getContextClassLoader()
+	 */
+	public void setContextClassLoader(ClassLoader cl) {
+		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) {
+		return;
+	}
+
+	/**
+	 * 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) {
+		return;
+	}
+
+	/**
+	 * 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) {
+		return;
+	}
+
+	/**
+	 * 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) {
+		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 {
+		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 {
+		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() {
+		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() {
+		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) {
+		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 equivalent 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() {
+		return;
+	}
+
+	/**
+	 * Answers a string containing a concise, human-readable description of the
+	 * receiver.
+	 * 
+	 * @return a printable representation for the receiver.
+	 */
+	public String toString() {
+		return null;
+	}
+
+	/**
+	 * 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() {
+		return;
+	};
+
+	/**
+	 * 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;
+	};
+
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/ThreadGroup.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/ThreadGroup.java?rev=390443&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/ThreadGroup.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/ThreadGroup.java Fri Mar 31 07:34:47 2006
@@ -0,0 +1,850 @@
+/* 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 {
+	// 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".
+	 */
+	private 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 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) {
+		// Does not apply to this VM, no-op
+		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);
+		}
+	}
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Throwable.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Throwable.java?rev=390443&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Throwable.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni-kernel/src/main/java/java/lang/Throwable.java Fri Mar 31 07:34:47 2006
@@ -0,0 +1,350 @@
+/* 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.IOException;
+import java.io.ObjectOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+
+/**
+ * This class must be implemented by the vm vendor, or the reference
+ * implementation can be used if the documented natives are implemented.
+ * 
+ * This class is the superclass of all classes which can be thrown by the
+ * virtual machine. The two direct subclasses represent recoverable exceptions
+ * (Exception) and unrecoverable errors (Error). This class provides common
+ * methods for accessing a string message which provides extra information about
+ * the circumstances in which the throwable was created, and for filling in a
+ * walkback (i.e. a record of the call stack at a particular point in time)
+ * which can be printed later.
+ * 
+ * @see Error
+ * @see Exception
+ * @see RuntimeException
+ */
+public class Throwable implements java.io.Serializable {
+	private static final long serialVersionUID = -3042686055658047285L;
+
+	/**
+	 * The message provided when the exception was created.
+	 */
+	private String detailMessage;
+
+	/**
+	 * An object which describes the walkback. This field is stored by the
+	 * fillInStackTrace() native, and used by the getStackTraceImpl() native.
+	 */
+	private transient Object walkback;
+
+	/**
+	 * The cause of this Throwable. Null when there is no cause.
+	 */
+	private Throwable cause = this;
+
+	private StackTraceElement[] stackTrace = null;
+
+	/**
+	 * Constructs a new instance of this class with its walkback filled in.
+	 */
+	public Throwable() {
+		super();
+		fillInStackTrace();
+	}
+
+	/**
+	 * Constructs a new instance of this class with its walkback and message
+	 * filled in.
+	 * 
+	 * @param detailMessage
+	 *            String The detail message for the exception.
+	 */
+	public Throwable(String detailMessage) {
+		this();
+		this.detailMessage = detailMessage;
+	}
+
+	/**
+	 * Constructs a new instance of this class with its walkback, message and
+	 * cause filled in.
+	 * 
+	 * @param detailMessage
+	 *            String The detail message for the exception.
+	 * @param throwable
+	 *            The cause of this Throwable
+	 */
+	public Throwable(String detailMessage, Throwable throwable) {
+		this();
+		this.detailMessage = detailMessage;
+		cause = throwable;
+	}
+
+	/**
+	 * Constructs a new instance of this class with its walkback and cause
+	 * filled in.
+	 * 
+	 * @param throwable
+	 *            The cause of this Throwable
+	 */
+	public Throwable(Throwable throwable) {
+		this();
+		this.detailMessage = throwable == null ? null : throwable.toString();
+		cause = throwable;
+	}
+
+	/**
+	 * This native must be implemented to use the reference implementation of
+	 * this class.
+	 * 
+	 * Record in the receiver a walkback from the point where this message was
+	 * sent. The message is public so that code which catches a throwable and
+	 * then <em>re-throws</em> it can adjust the walkback to represent the
+	 * location where the exception was re-thrown.
+	 * 
+	 * @return the receiver
+	 */
+	public native Throwable fillInStackTrace();
+
+	/**
+	 * Answers the extra information message which was provided when the
+	 * throwable was created. If no message was provided at creation time, then
+	 * answer null.
+	 * 
+	 * @return String The receiver's message.
+	 */
+	public String getMessage() {
+		return detailMessage;
+	}
+
+	/**
+	 * Answers the extra information message which was provided when the
+	 * throwable was created. If no message was provided at creation time, then
+	 * answer null. Subclasses may override this method to answer localized text
+	 * for the message.
+	 * 
+	 * @return String The receiver's message.
+	 */
+	public String getLocalizedMessage() {
+		return getMessage();
+	}
+
+	/**
+	 * This native must be implemented to use the reference implementation of
+	 * this class. The result of this native is cloned, and returned from the
+	 * public API getStackTrace().
+	 * 
+	 * Answers an array of StackTraceElement. Each StackTraceElement represents
+	 * a entry on the stack.
+	 * 
+	 * @return an array of StackTraceElement representing the stack
+	 */
+	private native StackTraceElement[] getStackTraceImpl();
+
+	/**
+	 * Answers an array of StackTraceElement. Each StackTraceElement represents
+	 * a entry on the stack.
+	 * 
+	 * @return an array of StackTraceElement representing the stack
+	 */
+	public StackTraceElement[] getStackTrace() {
+		return (StackTraceElement[]) getInternalStackTrace().clone();
+	}
+
+	/**
+	 * Sets the array of StackTraceElements. Each StackTraceElement represents a
+	 * entry on the stack. A copy of this array will be returned by
+	 * getStackTrace() and printed by printStackTrace().
+	 * 
+	 * @param trace
+	 *            The array of StackTraceElement
+	 */
+	public void setStackTrace(StackTraceElement[] trace) {
+		StackTraceElement[] newTrace = (StackTraceElement[]) trace.clone();
+		for (int i = 0; i < newTrace.length; i++)
+			if (newTrace[i] == null)
+				throw new NullPointerException();
+		stackTrace = newTrace;
+	}
+
+	/**
+	 * Outputs a printable representation of the receiver's walkback on the
+	 * System.err stream.
+	 */
+	public void printStackTrace() {
+		printStackTrace(System.err);
+	}
+
+	/**
+	 * Count the number of duplicate stack frames, starting from
+	 * the end of the stack.
+	 * 
+	 * @param currentStack a stack to compare
+	 * @param parentStack a stack to compare
+	 *  
+	 * @return the number of duplicate stack frames.
+	 */
+	private static int countDuplicates(StackTraceElement[] currentStack,
+			StackTraceElement[] parentStack) {
+		int duplicates = 0;
+		int parentIndex = parentStack.length;
+		for (int i = currentStack.length; --i >= 0 && --parentIndex >= 0;) {
+			StackTraceElement parentFrame = parentStack[parentIndex];
+			if (parentFrame.equals(currentStack[i])) {
+				duplicates++;
+			} else {
+				break;
+			}
+		}
+		return duplicates;
+	}
+
+	/**
+	 * Answers an array of StackTraceElement. Each StackTraceElement represents
+	 * a entry on the stack. Cache the stack trace in the stackTrace field, returning
+	 * the cached field when it has already been initialized.
+	 *
+	 * @return an array of StackTraceElement representing the stack
+	 */
+	private StackTraceElement[] getInternalStackTrace() {
+		if (stackTrace == null)
+			stackTrace = getStackTraceImpl();
+		return stackTrace;
+	}
+
+	/**
+	 * Outputs a printable representation of the receiver's walkback on the
+	 * stream specified by the argument.
+	 * 
+	 * @param err
+	 *            PrintStream The stream to write the walkback on.
+	 */
+	public void printStackTrace(PrintStream err) {
+		err.println(toString());
+		// Don't use getStackTrace() as it calls clone()
+		// Get stackTrace, in case stackTrace is reassigned
+		StackTraceElement[] stack = getInternalStackTrace();
+		for (int i = 0; i < stack.length; i++)
+			err.println("\tat " + stack[i]);
+
+		StackTraceElement[] parentStack = stack;
+		Throwable throwable = getCause();
+		while (throwable != null) {
+			err.print("Caused by: ");
+			err.println(throwable);
+			StackTraceElement[] currentStack = throwable
+					.getInternalStackTrace();
+			int duplicates = countDuplicates(currentStack, parentStack);
+			for (int i = 0; i < currentStack.length - duplicates; i++)
+				err.println("\tat " + currentStack[i]);
+			if (duplicates > 0) {
+				err.println("\t... " + duplicates + " more");
+			}
+			parentStack = currentStack;
+			throwable = throwable.getCause();
+		}
+	}
+
+	/**
+	 * Outputs a printable representation of the receiver's walkback on the
+	 * writer specified by the argument.
+	 * 
+	 * @param err
+	 *            PrintWriter The writer to write the walkback on.
+	 */
+	public void printStackTrace(PrintWriter err) {
+		err.println(toString());
+		// Don't use getStackTrace() as it calls clone()
+		// Get stackTrace, in case stackTrace is reassigned
+		StackTraceElement[] stack = getInternalStackTrace();
+		for (int i = 0; i < stack.length; i++)
+			err.println("\tat " + stack[i]);
+
+		StackTraceElement[] parentStack = stack;
+		Throwable throwable = getCause();
+		while (throwable != null) {
+			err.print("Caused by: ");
+			err.println(throwable);
+			StackTraceElement[] currentStack = throwable
+					.getInternalStackTrace();
+			int duplicates = countDuplicates(currentStack, parentStack);
+			for (int i = 0; i < currentStack.length - duplicates; i++)
+				err.println("\tat " + currentStack[i]);
+			if (duplicates > 0) {
+				err.println("\t... " + duplicates + " more");
+			}
+			parentStack = currentStack;
+			throwable = throwable.getCause();
+		}
+	}
+
+	/**
+	 * Answers a string containing a concise, human-readable description of the
+	 * receiver.
+	 * 
+	 * @return String a printable representation for the receiver.
+	 */
+	public String toString() {
+		String msg = getLocalizedMessage();
+		String name = getClass().getName();
+		if (msg == null) {
+			return name;
+		}
+		return new StringBuffer(name.length() + 2 + msg.length()).append(name)
+				.append(": ").append(msg).toString();
+	}
+
+	/**
+	 * Initialize the cause of the receiver. The cause cannot be reassigned.
+	 * 
+	 * @param throwable
+	 *            The cause of this Throwable
+	 * 
+	 * @exception IllegalArgumentException
+	 *                when the cause is the receiver
+	 * @exception IllegalStateException
+	 *                when the cause has already been initialized
+	 * 
+	 * @return the receiver.
+	 */
+	public synchronized Throwable initCause(Throwable throwable) {
+		if (cause == this) {
+			if (throwable != this) {
+				cause = throwable;
+				return this;
+			}
+			throw new IllegalArgumentException("Cause cannot be the receiver");
+		}
+		throw new IllegalStateException("Cause already initialized");
+	}
+
+	/**
+	 * Answers the cause of this Throwable, or null if there is no cause.
+	 * 
+	 * @return Throwable The receiver's cause.
+	 */
+	public Throwable getCause() {
+		if (cause == this)
+			return null;
+		return cause;
+	}
+
+	private void writeObject(ObjectOutputStream s) throws IOException {
+		// ensure the stackTrace field is initialized
+		getInternalStackTrace();
+		s.defaultWriteObject();
+	}
+}