diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
commit | f911ba985aa7fe0096c386c5be385ac5825ea527 (patch) | |
tree | a0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/java/lang | |
parent | 6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff) | |
download | gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.zip gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.bz2 |
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/java/lang')
112 files changed, 30133 insertions, 0 deletions
diff --git a/libjava/classpath/java/lang/AbstractMethodError.java b/libjava/classpath/java/lang/AbstractMethodError.java new file mode 100644 index 0000000..b9eb622 --- /dev/null +++ b/libjava/classpath/java/lang/AbstractMethodError.java @@ -0,0 +1,75 @@ +/* AbstractMethodError.java -- thrown if an abstract method is invoked + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>AbstractMethodError</code> is thrown when an application attempts + * to access an abstract method. Compilers typically detect this error, but + * it can be thrown at run time if the definition of a class has changed + * since the application was last compiled. This can also occur when + * reflecting on methods. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class AbstractMethodError extends IncompatibleClassChangeError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -1654391082989018462L; + + /** + * Create an error without a message. + */ + public AbstractMethodError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public AbstractMethodError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Appendable.java b/libjava/classpath/java/lang/Appendable.java new file mode 100644 index 0000000..c096677 --- /dev/null +++ b/libjava/classpath/java/lang/Appendable.java @@ -0,0 +1,122 @@ +/* Appendable.java -- Something to which characters can be appended + Copyright (C) 2004 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.io.IOException; + +/** + * <p> + * An <code>Appendable</code> object is one to which a sequence of Unicode + * characters can be added. The appended characters must be valid Unicode + * characters, and may include supplementary characters, composed of multiple + * 16-bit <code>char</code> values. + * </p> + * <p> + * The behaviour of the <code>Appendable</code> object is heavily dependent + * on the particular implementation being used. Some implementations may be + * thread-safe, while others may not. Likewise, some implementing classes + * may produce errors which aren't propogated to the invoking class, due + * to differences in the error handling used. + * </p> + * <p> + * <strong>Note</strong>: implementation of this interface is required for + * any class that wishes to receive data from a <code>Formatter</code> + * instance. + * </p> + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public interface Appendable +{ + + /** + * Appends the Unicode character, c, to this <code>Appendable</code> + * object. + * + * @param c the character to append. + * @return a reference to this object. + * @throws IOException if an I/O error occurs. + */ + Appendable append(char c) + throws IOException; + + /** + * Appends the specified sequence of Unicode characters to this + * <code>Appendable</code> object. The entire sequence may not + * be appended, if constrained by the underlying implementation. + * For example, a buffer may reach its size limit before the entire + * sequence is appended. + * + * @param seq the character sequence to append. If seq is null, + * then the string "null" (the string representation of null) + * is appended. + * @return a reference to this object. + * @throws IOException if an I/O error occurs. + */ + Appendable append(CharSequence seq) + throws IOException; + + /** + * Appends the specified subsequence of Unicode characters to this + * <code>Appendable</code> object, starting and ending at the specified + * positions within the sequence. The entire sequence may not + * be appended, if constrained by the underlying implementation. + * For example, a buffer may reach its size limit before the entire + * sequence is appended. The behaviour of this method matches the + * behaviour of <code>append(seq.subSequence(start,end))</code> when + * the sequence is not null. + * + * @param seq the character sequence to append. If seq is null, + * then the string "null" (the string representation of null) + * is appended. + * @param start the index of the first Unicode character to use from + * the sequence. + * @param end the index of the last Unicode character to use from the + * sequence. + * @return a reference to this object. + * @throws IOException if an I/O error occurs. + * @throws IndexOutOfBoundsException if either of the indices are negative, + * the start index occurs after the end index, or the end index is + * beyond the end of the sequence. + */ + Appendable append(CharSequence seq, int start, int end) + throws IOException; + +} diff --git a/libjava/classpath/java/lang/ArithmeticException.java b/libjava/classpath/java/lang/ArithmeticException.java new file mode 100644 index 0000000..5acea43 --- /dev/null +++ b/libjava/classpath/java/lang/ArithmeticException.java @@ -0,0 +1,77 @@ +/* ArithmeticException.java -- exception thrown to indicate conditions + like divide by zero. + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when a math error has occured, such as trying to divide an + * integer by zero. For example:<br> + * <pre> + * int i = 0; + * int j = 2 / i; + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class ArithmeticException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 2256477558314496007L; + + /** + * Create an exception without a message. + */ + public ArithmeticException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public ArithmeticException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/ArrayIndexOutOfBoundsException.java b/libjava/classpath/java/lang/ArrayIndexOutOfBoundsException.java new file mode 100644 index 0000000..371623b --- /dev/null +++ b/libjava/classpath/java/lang/ArrayIndexOutOfBoundsException.java @@ -0,0 +1,87 @@ +/* ArrayIndexOutOfBoundsException.java -- exception thrown when accessing + an illegal index. + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when attempting to access a position outside the valid range of + * an array. For example:<br> + * <pre> + * int[] i = { 1 }; + * i[1] = 2; + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -5116101128118950844L; + + /** + * Create an exception without a message. + */ + public ArrayIndexOutOfBoundsException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public ArrayIndexOutOfBoundsException(String s) + { + super(s); + } + + /** + * Create an exception indicating the illegal index. + * + * @param index the invalid index + */ + public ArrayIndexOutOfBoundsException(int index) + { + super("Array index out of range: " + index); + } +} diff --git a/libjava/classpath/java/lang/ArrayStoreException.java b/libjava/classpath/java/lang/ArrayStoreException.java new file mode 100644 index 0000000..042e78c --- /dev/null +++ b/libjava/classpath/java/lang/ArrayStoreException.java @@ -0,0 +1,77 @@ +/* ArrayStoreException.java -- exception thrown to when trying to store an + object into an array of a different type. + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when trying to store an object of the wrong runtime type in an + * array. For example:<br> + * <pre> + * Object[] o = new Integer[1]; + * o[0] = "oops"; + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class ArrayStoreException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -4522193890499838241L; + + /** + * Create an exception without a message. + */ + public ArrayStoreException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public ArrayStoreException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/AssertionError.java b/libjava/classpath/java/lang/AssertionError.java new file mode 100644 index 0000000..778eb58 --- /dev/null +++ b/libjava/classpath/java/lang/AssertionError.java @@ -0,0 +1,148 @@ +/* AssertionError.java -- indication of a failed assertion + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An assertion error normally occurs as a result of the <code>assert</code> + * statement added in JDK 1.4, to indicate that an assertion failed. There + * are enough constructors to ensure that + * <code>new AssertionError(<em>expression</em>)</code> will work for all + * expressions, regardless of type, as if the error message were given by + * the string <code>"" + <em>expression</em></code>. This extends Error, + * because you usually do not want to inadvertently trap an assertion failure. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.4 + * @status updated to 1.4 + */ +public class AssertionError extends Error +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = -5013299493970297370L; + + /** + * Construct an AssertionError with no detail message. + */ + public AssertionError() + { + } + + /** + * Construct an AssertionError with the string conversion of the given + * object as its error message. If the object is a Throwable, it is also + * set as the cause of this error. + * + * @param msg the source of the error message + * @see Throwable#getCause() + */ + public AssertionError(Object msg) + { + super("" + msg); + if (msg instanceof Throwable) + initCause((Throwable) msg); + } + + /** + * Construct an AssertionError with the string conversion of the given + * boolean as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(boolean msg) + { + super(msg ? "true" : "false"); + } + + /** + * Construct an AssertionError with the string conversion of the given + * char as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(char msg) + { + super(String.valueOf(msg)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * int as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(int msg) + { + super(Integer.toString(msg, 10)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * long as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(long msg) + { + super(Long.toString(msg)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * float as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(float msg) + { + super(Float.toString(msg)); + } + + /** + * Construct an AssertionError with the string conversion of the given + * double as its error message. + * + * @param msg the source of the error message + */ + public AssertionError(double msg) + { + super(Double.toString(msg)); + } +} diff --git a/libjava/classpath/java/lang/Boolean.java b/libjava/classpath/java/lang/Boolean.java new file mode 100644 index 0000000..b691028 --- /dev/null +++ b/libjava/classpath/java/lang/Boolean.java @@ -0,0 +1,224 @@ +/* Boolean.java -- object wrapper for boolean + Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.io.Serializable; + +/** + * Instances of class <code>Boolean</code> represent primitive + * <code>boolean</code> values. + * + * @author Paul Fisher + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public final class Boolean implements Serializable +{ + /** + * Compatible with JDK 1.0.2+. + */ + private static final long serialVersionUID = -3665804199014368530L; + + /** + * This field is a <code>Boolean</code> object representing the + * primitive value <code>true</code>. This instance is returned + * by the static <code>valueOf()</code> methods if they return + * a <code>Boolean</code> representing <code>true</code>. + */ + public static final Boolean TRUE = new Boolean(true); + + /** + * This field is a <code>Boolean</code> object representing the + * primitive value <code>false</code>. This instance is returned + * by the static <code>valueOf()</code> methods if they return + * a <code>Boolean</code> representing <code>false</code>. + */ + public static final Boolean FALSE = new Boolean(false); + + /** + * The primitive type <code>boolean</code> is represented by this + * <code>Class</code> object. + * + * @since 1.1 + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('Z'); + + /** + * The immutable value of this Boolean. + * @serial the wrapped value + */ + private final boolean value; + + /** + * Create a <code>Boolean</code> object representing the value of the + * argument <code>value</code>. In general the use of the static + * method <code>valueof(boolean)</code> is more efficient since it will + * not create a new object. + * + * @param value the primitive value of this <code>Boolean</code> + * @see #valueOf(boolean) + */ + public Boolean(boolean value) + { + this.value = value; + } + + /** + * Creates a <code>Boolean</code> object representing the primitive + * <code>true</code> if and only if <code>s</code> matches + * the string "true" ignoring case, otherwise the object will represent + * the primitive <code>false</code>. In general the use of the static + * method <code>valueof(String)</code> is more efficient since it will + * not create a new object. + * + * @param s the <code>String</code> representation of <code>true</code> + * or false + */ + public Boolean(String s) + { + value = "true".equalsIgnoreCase(s); + } + + /** + * Return the primitive <code>boolean</code> value of this + * <code>Boolean</code> object. + * + * @return true or false, depending on the value of this Boolean + */ + public boolean booleanValue() + { + return value; + } + + /** + * Returns the Boolean <code>TRUE</code> if the given boolean is + * <code>true</code>, otherwise it will return the Boolean + * <code>FALSE</code>. + * + * @param b the boolean to wrap + * @return the wrapper object + * @see #TRUE + * @see #FALSE + * @since 1.4 + */ + public static Boolean valueOf(boolean b) + { + return b ? TRUE : FALSE; + } + + /** + * Returns the Boolean <code>TRUE</code> if and only if the given + * String is equal, ignoring case, to the the String "true", otherwise + * it will return the Boolean <code>FALSE</code>. + * + * @param s the string to convert + * @return a wrapped boolean from the string + */ + public static Boolean valueOf(String s) + { + return "true".equalsIgnoreCase(s) ? TRUE : FALSE; + } + + /** + * Returns "true" if the value of the give boolean is <code>true</code> and + * returns "false" if the value of the given boolean is <code>false</code>. + * + * @param b the boolean to convert + * @return the string representation of the boolean + * @since 1.4 + */ + public static String toString(boolean b) + { + return b ? "true" : "false"; + } + + /** + * Returns "true" if the value of this object is <code>true</code> and + * returns "false" if the value of this object is <code>false</code>. + * + * @return the string representation of this + */ + public String toString() + { + return value ? "true" : "false"; + } + + /** + * Returns the integer <code>1231</code> if this object represents + * the primitive <code>true</code> and the integer <code>1237</code> + * otherwise. + * + * @return the hash code + */ + public int hashCode() + { + return value ? 1231 : 1237; + } + + /** + * If the <code>obj</code> is an instance of <code>Boolean</code> and + * has the same primitive value as this object then <code>true</code> + * is returned. In all other cases, including if the <code>obj</code> + * is <code>null</code>, <code>false</code> is returned. + * + * @param obj possibly an instance of any <code>Class</code> + * @return true if <code>obj</code> equals this + */ + public boolean equals(Object obj) + { + return obj instanceof Boolean && value == ((Boolean) obj).value; + } + + /** + * If the value of the system property <code>name</code> matches + * "true" ignoring case then the function returns <code>true</code>. + * + * @param name the property name to look up + * @return true if the property resulted in "true" + * @throws SecurityException if accessing the system property is forbidden + * @see System#getProperty(String) + */ + public static boolean getBoolean(String name) + { + if (name == null || "".equals(name)) + return false; + return "true".equalsIgnoreCase(System.getProperty(name)); + } +} diff --git a/libjava/classpath/java/lang/Byte.java b/libjava/classpath/java/lang/Byte.java new file mode 100644 index 0000000..338e216 --- /dev/null +++ b/libjava/classpath/java/lang/Byte.java @@ -0,0 +1,357 @@ +/* Byte.java -- object wrapper for byte + Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Instances of class <code>Byte</code> represent primitive <code>byte</code> + * values. + * + * Additionally, this class provides various helper functions and variables + * useful to bytes. + * + * @author Paul Fisher + * @author John Keiser + * @author Per Bothner + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.1 + * @status updated to 1.4 + */ +public final class Byte extends Number implements Comparable +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -7183698231559129828L; + + /** + * The minimum value a <code>byte</code> can represent is -128 (or + * -2<sup>7</sup>). + */ + public static final byte MIN_VALUE = -128; + + /** + * The maximum value a <code>byte</code> can represent is 127 (or + * 2<sup>7</sup> - 1). + */ + public static final byte MAX_VALUE = 127; + + /** + * The primitive type <code>byte</code> is represented by this + * <code>Class</code> object. + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('B'); + + /** + * The immutable value of this Byte. + * + * @serial the wrapped byte + */ + private final byte value; + + /** + * Create a <code>Byte</code> object representing the value of the + * <code>byte</code> argument. + * + * @param value the value to use + */ + public Byte(byte value) + { + this.value = value; + } + + /** + * Create a <code>Byte</code> object representing the value specified + * by the <code>String</code> argument + * + * @param s the string to convert + * @throws NumberFormatException if the String does not contain a byte + * @see #valueOf(String) + */ + public Byte(String s) + { + value = parseByte(s, 10); + } + + /** + * Converts the <code>byte</code> to a <code>String</code> and assumes + * a radix of 10. + * + * @param b the <code>byte</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toString(byte b) + { + return String.valueOf(b); + } + + /** + * Converts the specified <code>String</code> into a <code>byte</code>. + * This function assumes a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the <code>byte</code> value of <code>s</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>byte</code> + * @see #parseByte(String) + */ + public static byte parseByte(String s) + { + return parseByte(s, 10); + } + + /** + * Converts the specified <code>String</code> into an <code>int</code> + * using the specified radix (base). The string must not be <code>null</code> + * or empty. It may begin with an optional '-', which will negate the answer, + * provided that there are also valid digits. Each digit is parsed as if by + * <code>Character.digit(d, radix)</code>, and must be in the range + * <code>0</code> to <code>radix - 1</code>. Finally, the result must be + * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive. + * Unlike Double.parseDouble, you may not have a leading '+'. + * + * @param s the <code>String</code> to convert + * @param radix the radix (base) to use in the conversion + * @return the <code>String</code> argument converted to <code>byte</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>byte</code> + */ + public static byte parseByte(String s, int radix) + { + int i = Integer.parseInt(s, radix, false); + if ((byte) i != i) + throw new NumberFormatException(); + return (byte) i; + } + + /** + * Creates a new <code>Byte</code> object using the <code>String</code> + * and specified radix (base). + * + * @param s the <code>String</code> to convert + * @param radix the radix (base) to convert with + * @return the new <code>Byte</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>byte</code> + * @see #parseByte(String, int) + */ + public static Byte valueOf(String s, int radix) + { + return new Byte(parseByte(s, radix)); + } + + /** + * Creates a new <code>Byte</code> object using the <code>String</code>, + * assuming a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the new <code>Byte</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>byte</code> + * @see #Byte(String) + * @see #parseByte(String) + */ + public static Byte valueOf(String s) + { + return new Byte(parseByte(s, 10)); + } + + /** + * Convert the specified <code>String</code> into a <code>Byte</code>. + * The <code>String</code> may represent decimal, hexadecimal, or + * octal numbers. + * + * <p>The extended BNF grammar is as follows:<br> + * <pre> + * <em>DecodableString</em>: + * ( [ <code>-</code> ] <em>DecimalNumber</em> ) + * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code> + * | <code>#</code> ) { <em>HexDigit</em> }+ ) + * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } ) + * <em>DecimalNumber</em>: + * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> } + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 10) has value 0 to 9</em> + * <em>OctalDigit</em>: + * <em>Character.digit(d, 8) has value 0 to 7</em> + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 16) has value 0 to 15</em> + * </pre> + * Finally, the value must be in the range <code>MIN_VALUE</code> to + * <code>MAX_VALUE</code>, or an exception is thrown. + * + * @param s the <code>String</code> to interpret + * @return the value of the String as a <code>Byte</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>byte</code> + * @throws NullPointerException if <code>s</code> is null + * @see Integer#decode(String) + */ + public static Byte decode(String s) + { + int i = Integer.parseInt(s, 10, true); + if ((byte) i != i) + throw new NumberFormatException(); + return new Byte((byte) i); + } + + /** + * Return the value of this <code>Byte</code>. + * + * @return the byte value + */ + public byte byteValue() + { + return value; + } + + /** + * Return the value of this <code>Byte</code> as a <code>short</code>. + * + * @return the short value + */ + public short shortValue() + { + return value; + } + + /** + * Return the value of this <code>Byte</code> as an <code>int</code>. + * + * @return the int value + */ + public int intValue() + { + return value; + } + + /** + * Return the value of this <code>Byte</code> as a <code>long</code>. + * + * @return the long value + */ + public long longValue() + { + return value; + } + + /** + * Return the value of this <code>Byte</code> as a <code>float</code>. + * + * @return the float value + */ + public float floatValue() + { + return value; + } + + /** + * Return the value of this <code>Byte</code> as a <code>double</code>. + * + * @return the double value + */ + public double doubleValue() + { + return value; + } + + /** + * Converts the <code>Byte</code> value to a <code>String</code> and + * assumes a radix of 10. + * + * @return the <code>String</code> representation of this <code>Byte</code> + * @see Integer#toString() + */ + public String toString() + { + return String.valueOf(value); + } + + /** + * Return a hashcode representing this Object. <code>Byte</code>'s hash + * code is simply its value. + * + * @return this Object's hash code + */ + public int hashCode() + { + return value; + } + + /** + * Returns <code>true</code> if <code>obj</code> is an instance of + * <code>Byte</code> and represents the same byte value. + * + * @param obj the object to compare + * @return whether these Objects are semantically equal + */ + public boolean equals(Object obj) + { + return obj instanceof Byte && value == ((Byte) obj).value; + } + + /** + * Compare two Bytes numerically by comparing their <code>byte</code> values. + * The result is positive if the first is greater, negative if the second + * is greater, and 0 if the two are equal. + * + * @param b the Byte to compare + * @return the comparison + * @since 1.2 + */ + public int compareTo(Byte b) + { + return value - b.value; + } + + /** + * Behaves like <code>compareTo(Byte)</code> unless the Object + * is not a <code>Byte</code>. + * + * @param o the object to compare + * @return the comparison + * @throws ClassCastException if the argument is not a <code>Byte</code> + * @see #compareTo(Byte) + * @see Comparable + * @since 1.2 + */ + public int compareTo(Object o) + { + return compareTo((Byte) o); + } +} diff --git a/libjava/classpath/java/lang/CharSequence.java b/libjava/classpath/java/lang/CharSequence.java new file mode 100644 index 0000000..5c014e1 --- /dev/null +++ b/libjava/classpath/java/lang/CharSequence.java @@ -0,0 +1,99 @@ +/* CharSequence.java -- Anything that has an indexed sequence of chars + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * General functions on a sequence of chars. This interface is implemented + * by <code>String</code>, <code>StringBuffer</code> and + * <code>CharBuffer</code> to give a uniform way to get chars at a certain + * index, the number of characters in the sequence and a subrange of the + * chars. Indexes start at 0 and the last index is <code>length()-1</code>. + * + * <p>Even when classes implement this interface they are not always + * exchangeble because they might implement their compare, equals or hash + * function differently. This means that in general one should not use a + * <code>CharSequence</code> as keys in collections since two sequences + * with the same chars at the same indexes with the same length might not + * have the same hash code, be equal or be comparable since the are + * represented by different classes. + * + * @author Mark Wielaard (mark@klomp.org) + * @since 1.4 + * @status updated to 1.4 + */ +public interface CharSequence +{ + /** + * Returns the character at the given index. + * + * @param i the index to retrieve from + * @return the character at that location + * @throws IndexOutOfBoundsException if i < 0 || i >= length() - 1 + */ + char charAt(int i); + + /** + * Returns the length of the sequence. This is the number of 16-bit + * characters in the sequence, which may differ from the length of the + * underlying encoding. + * + * @return the sequence length + */ + int length(); + + /** + * Returns a new <code>CharSequence</code> of the indicated range. + * + * @param begin the start index (inclusive) + * @param end the end index (exclusive) + * @return a subsequence of this + * @throws IndexOutOfBoundsException if begin > end || begin < 0 || + * end > length() + */ + CharSequence subSequence(int begin, int end); + + /** + * Returns the complete <code>CharSequence</code> as a <code>String</code>. + * Classes that implement this interface should return a <code>String</code> + * which contains only the characters in the sequence in the correct order. + * + * @return the character sequence as a String + */ + String toString(); +} diff --git a/libjava/classpath/java/lang/Character.java b/libjava/classpath/java/lang/Character.java new file mode 100644 index 0000000..4eac147 --- /dev/null +++ b/libjava/classpath/java/lang/Character.java @@ -0,0 +1,2253 @@ +/* java.lang.Character -- Wrapper class for char, and Unicode subsets + Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import gnu.java.lang.CharData; + +import java.io.Serializable; + +/** + * Wrapper class for the primitive char data type. In addition, this class + * allows one to retrieve property information and perform transformations + * on the 57,707 defined characters in the Unicode Standard, Version 3.0.0. + * java.lang.Character is designed to be very dynamic, and as such, it + * retrieves information on the Unicode character set from a separate + * database, gnu.java.lang.CharData, which can be easily upgraded. + * + * <p>For predicates, boundaries are used to describe + * the set of characters for which the method will return true. + * This syntax uses fairly normal regular expression notation. + * See 5.13 of the Unicode Standard, Version 3.0, for the + * boundary specification. + * + * <p>See <a href="http://www.unicode.org">http://www.unicode.org</a> + * for more information on the Unicode Standard. + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Paul N. Fisher + * @author Jochen Hoenicke + * @author Eric Blake (ebb9@email.byu.edu) + * @see CharData + * @since 1.0 + * @status updated to 1.4 + */ +public final class Character implements Serializable, Comparable +{ + /** + * A subset of Unicode blocks. + * + * @author Paul N. Fisher + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + */ + public static class Subset + { + /** The name of the subset. */ + private final String name; + + /** + * Construct a new subset of characters. + * + * @param name the name of the subset + * @throws NullPointerException if name is null + */ + protected Subset(String name) + { + // Note that name.toString() is name, unless name was null. + this.name = name.toString(); + } + + /** + * Compares two Subsets for equality. This is <code>final</code>, and + * restricts the comparison on the <code>==</code> operator, so it returns + * true only for the same object. + * + * @param o the object to compare + * @return true if o is this + */ + public final boolean equals(Object o) + { + return o == this; + } + + /** + * Makes the original hashCode of Object final, to be consistent with + * equals. + * + * @return the hash code for this object + */ + public final int hashCode() + { + return super.hashCode(); + } + + /** + * Returns the name of the subset. + * + * @return the name + */ + public final String toString() + { + return name; + } + } // class Subset + + /** + * A family of character subsets in the Unicode specification. A character + * is in at most one of these blocks. + * + * This inner class was generated automatically from + * <code>doc/unicode/Block-3.txt</code>, by some perl scripts. + * This Unicode definition file can be found on the + * <a href="http://www.unicode.org">http://www.unicode.org</a> website. + * JDK 1.4 uses Unicode version 3.0.0. + * + * @author scripts/unicode-blocks.pl (written by Eric Blake) + * @since 1.2 + */ + public static final class UnicodeBlock extends Subset + { + /** The start of the subset. */ + private final char start; + + /** The end of the subset. */ + private final char end; + + /** + * Constructor for strictly defined blocks. + * + * @param start the start character of the range + * @param end the end character of the range + * @param name the block name + */ + private UnicodeBlock(char start, char end, String name) + { + super(name); + this.start = start; + this.end = end; + } + + /** + * Returns the Unicode character block which a character belongs to. + * + * @param ch the character to look up + * @return the set it belongs to, or null if it is not in one + */ + public static UnicodeBlock of(char ch) + { + // Special case, since SPECIALS contains two ranges. + if (ch == '\uFEFF') + return SPECIALS; + // Simple binary search for the correct block. + int low = 0; + int hi = sets.length - 1; + while (low <= hi) + { + int mid = (low + hi) >> 1; + UnicodeBlock b = sets[mid]; + if (ch < b.start) + hi = mid - 1; + else if (ch > b.end) + low = mid + 1; + else + return b; + } + return null; + } + + /** + * Basic Latin. + * '\u0000' - '\u007F'. + */ + public static final UnicodeBlock BASIC_LATIN + = new UnicodeBlock('\u0000', '\u007F', + "BASIC_LATIN"); + + /** + * Latin-1 Supplement. + * '\u0080' - '\u00FF'. + */ + public static final UnicodeBlock LATIN_1_SUPPLEMENT + = new UnicodeBlock('\u0080', '\u00FF', + "LATIN_1_SUPPLEMENT"); + + /** + * Latin Extended-A. + * '\u0100' - '\u017F'. + */ + public static final UnicodeBlock LATIN_EXTENDED_A + = new UnicodeBlock('\u0100', '\u017F', + "LATIN_EXTENDED_A"); + + /** + * Latin Extended-B. + * '\u0180' - '\u024F'. + */ + public static final UnicodeBlock LATIN_EXTENDED_B + = new UnicodeBlock('\u0180', '\u024F', + "LATIN_EXTENDED_B"); + + /** + * IPA Extensions. + * '\u0250' - '\u02AF'. + */ + public static final UnicodeBlock IPA_EXTENSIONS + = new UnicodeBlock('\u0250', '\u02AF', + "IPA_EXTENSIONS"); + + /** + * Spacing Modifier Letters. + * '\u02B0' - '\u02FF'. + */ + public static final UnicodeBlock SPACING_MODIFIER_LETTERS + = new UnicodeBlock('\u02B0', '\u02FF', + "SPACING_MODIFIER_LETTERS"); + + /** + * Combining Diacritical Marks. + * '\u0300' - '\u036F'. + */ + public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS + = new UnicodeBlock('\u0300', '\u036F', + "COMBINING_DIACRITICAL_MARKS"); + + /** + * Greek. + * '\u0370' - '\u03FF'. + */ + public static final UnicodeBlock GREEK + = new UnicodeBlock('\u0370', '\u03FF', + "GREEK"); + + /** + * Cyrillic. + * '\u0400' - '\u04FF'. + */ + public static final UnicodeBlock CYRILLIC + = new UnicodeBlock('\u0400', '\u04FF', + "CYRILLIC"); + + /** + * Armenian. + * '\u0530' - '\u058F'. + */ + public static final UnicodeBlock ARMENIAN + = new UnicodeBlock('\u0530', '\u058F', + "ARMENIAN"); + + /** + * Hebrew. + * '\u0590' - '\u05FF'. + */ + public static final UnicodeBlock HEBREW + = new UnicodeBlock('\u0590', '\u05FF', + "HEBREW"); + + /** + * Arabic. + * '\u0600' - '\u06FF'. + */ + public static final UnicodeBlock ARABIC + = new UnicodeBlock('\u0600', '\u06FF', + "ARABIC"); + + /** + * Syriac. + * '\u0700' - '\u074F'. + * @since 1.4 + */ + public static final UnicodeBlock SYRIAC + = new UnicodeBlock('\u0700', '\u074F', + "SYRIAC"); + + /** + * Thaana. + * '\u0780' - '\u07BF'. + * @since 1.4 + */ + public static final UnicodeBlock THAANA + = new UnicodeBlock('\u0780', '\u07BF', + "THAANA"); + + /** + * Devanagari. + * '\u0900' - '\u097F'. + */ + public static final UnicodeBlock DEVANAGARI + = new UnicodeBlock('\u0900', '\u097F', + "DEVANAGARI"); + + /** + * Bengali. + * '\u0980' - '\u09FF'. + */ + public static final UnicodeBlock BENGALI + = new UnicodeBlock('\u0980', '\u09FF', + "BENGALI"); + + /** + * Gurmukhi. + * '\u0A00' - '\u0A7F'. + */ + public static final UnicodeBlock GURMUKHI + = new UnicodeBlock('\u0A00', '\u0A7F', + "GURMUKHI"); + + /** + * Gujarati. + * '\u0A80' - '\u0AFF'. + */ + public static final UnicodeBlock GUJARATI + = new UnicodeBlock('\u0A80', '\u0AFF', + "GUJARATI"); + + /** + * Oriya. + * '\u0B00' - '\u0B7F'. + */ + public static final UnicodeBlock ORIYA + = new UnicodeBlock('\u0B00', '\u0B7F', + "ORIYA"); + + /** + * Tamil. + * '\u0B80' - '\u0BFF'. + */ + public static final UnicodeBlock TAMIL + = new UnicodeBlock('\u0B80', '\u0BFF', + "TAMIL"); + + /** + * Telugu. + * '\u0C00' - '\u0C7F'. + */ + public static final UnicodeBlock TELUGU + = new UnicodeBlock('\u0C00', '\u0C7F', + "TELUGU"); + + /** + * Kannada. + * '\u0C80' - '\u0CFF'. + */ + public static final UnicodeBlock KANNADA + = new UnicodeBlock('\u0C80', '\u0CFF', + "KANNADA"); + + /** + * Malayalam. + * '\u0D00' - '\u0D7F'. + */ + public static final UnicodeBlock MALAYALAM + = new UnicodeBlock('\u0D00', '\u0D7F', + "MALAYALAM"); + + /** + * Sinhala. + * '\u0D80' - '\u0DFF'. + * @since 1.4 + */ + public static final UnicodeBlock SINHALA + = new UnicodeBlock('\u0D80', '\u0DFF', + "SINHALA"); + + /** + * Thai. + * '\u0E00' - '\u0E7F'. + */ + public static final UnicodeBlock THAI + = new UnicodeBlock('\u0E00', '\u0E7F', + "THAI"); + + /** + * Lao. + * '\u0E80' - '\u0EFF'. + */ + public static final UnicodeBlock LAO + = new UnicodeBlock('\u0E80', '\u0EFF', + "LAO"); + + /** + * Tibetan. + * '\u0F00' - '\u0FFF'. + */ + public static final UnicodeBlock TIBETAN + = new UnicodeBlock('\u0F00', '\u0FFF', + "TIBETAN"); + + /** + * Myanmar. + * '\u1000' - '\u109F'. + * @since 1.4 + */ + public static final UnicodeBlock MYANMAR + = new UnicodeBlock('\u1000', '\u109F', + "MYANMAR"); + + /** + * Georgian. + * '\u10A0' - '\u10FF'. + */ + public static final UnicodeBlock GEORGIAN + = new UnicodeBlock('\u10A0', '\u10FF', + "GEORGIAN"); + + /** + * Hangul Jamo. + * '\u1100' - '\u11FF'. + */ + public static final UnicodeBlock HANGUL_JAMO + = new UnicodeBlock('\u1100', '\u11FF', + "HANGUL_JAMO"); + + /** + * Ethiopic. + * '\u1200' - '\u137F'. + * @since 1.4 + */ + public static final UnicodeBlock ETHIOPIC + = new UnicodeBlock('\u1200', '\u137F', + "ETHIOPIC"); + + /** + * Cherokee. + * '\u13A0' - '\u13FF'. + * @since 1.4 + */ + public static final UnicodeBlock CHEROKEE + = new UnicodeBlock('\u13A0', '\u13FF', + "CHEROKEE"); + + /** + * Unified Canadian Aboriginal Syllabics. + * '\u1400' - '\u167F'. + * @since 1.4 + */ + public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS + = new UnicodeBlock('\u1400', '\u167F', + "UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS"); + + /** + * Ogham. + * '\u1680' - '\u169F'. + * @since 1.4 + */ + public static final UnicodeBlock OGHAM + = new UnicodeBlock('\u1680', '\u169F', + "OGHAM"); + + /** + * Runic. + * '\u16A0' - '\u16FF'. + * @since 1.4 + */ + public static final UnicodeBlock RUNIC + = new UnicodeBlock('\u16A0', '\u16FF', + "RUNIC"); + + /** + * Khmer. + * '\u1780' - '\u17FF'. + * @since 1.4 + */ + public static final UnicodeBlock KHMER + = new UnicodeBlock('\u1780', '\u17FF', + "KHMER"); + + /** + * Mongolian. + * '\u1800' - '\u18AF'. + * @since 1.4 + */ + public static final UnicodeBlock MONGOLIAN + = new UnicodeBlock('\u1800', '\u18AF', + "MONGOLIAN"); + + /** + * Latin Extended Additional. + * '\u1E00' - '\u1EFF'. + */ + public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL + = new UnicodeBlock('\u1E00', '\u1EFF', + "LATIN_EXTENDED_ADDITIONAL"); + + /** + * Greek Extended. + * '\u1F00' - '\u1FFF'. + */ + public static final UnicodeBlock GREEK_EXTENDED + = new UnicodeBlock('\u1F00', '\u1FFF', + "GREEK_EXTENDED"); + + /** + * General Punctuation. + * '\u2000' - '\u206F'. + */ + public static final UnicodeBlock GENERAL_PUNCTUATION + = new UnicodeBlock('\u2000', '\u206F', + "GENERAL_PUNCTUATION"); + + /** + * Superscripts and Subscripts. + * '\u2070' - '\u209F'. + */ + public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS + = new UnicodeBlock('\u2070', '\u209F', + "SUPERSCRIPTS_AND_SUBSCRIPTS"); + + /** + * Currency Symbols. + * '\u20A0' - '\u20CF'. + */ + public static final UnicodeBlock CURRENCY_SYMBOLS + = new UnicodeBlock('\u20A0', '\u20CF', + "CURRENCY_SYMBOLS"); + + /** + * Combining Marks for Symbols. + * '\u20D0' - '\u20FF'. + */ + public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS + = new UnicodeBlock('\u20D0', '\u20FF', + "COMBINING_MARKS_FOR_SYMBOLS"); + + /** + * Letterlike Symbols. + * '\u2100' - '\u214F'. + */ + public static final UnicodeBlock LETTERLIKE_SYMBOLS + = new UnicodeBlock('\u2100', '\u214F', + "LETTERLIKE_SYMBOLS"); + + /** + * Number Forms. + * '\u2150' - '\u218F'. + */ + public static final UnicodeBlock NUMBER_FORMS + = new UnicodeBlock('\u2150', '\u218F', + "NUMBER_FORMS"); + + /** + * Arrows. + * '\u2190' - '\u21FF'. + */ + public static final UnicodeBlock ARROWS + = new UnicodeBlock('\u2190', '\u21FF', + "ARROWS"); + + /** + * Mathematical Operators. + * '\u2200' - '\u22FF'. + */ + public static final UnicodeBlock MATHEMATICAL_OPERATORS + = new UnicodeBlock('\u2200', '\u22FF', + "MATHEMATICAL_OPERATORS"); + + /** + * Miscellaneous Technical. + * '\u2300' - '\u23FF'. + */ + public static final UnicodeBlock MISCELLANEOUS_TECHNICAL + = new UnicodeBlock('\u2300', '\u23FF', + "MISCELLANEOUS_TECHNICAL"); + + /** + * Control Pictures. + * '\u2400' - '\u243F'. + */ + public static final UnicodeBlock CONTROL_PICTURES + = new UnicodeBlock('\u2400', '\u243F', + "CONTROL_PICTURES"); + + /** + * Optical Character Recognition. + * '\u2440' - '\u245F'. + */ + public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION + = new UnicodeBlock('\u2440', '\u245F', + "OPTICAL_CHARACTER_RECOGNITION"); + + /** + * Enclosed Alphanumerics. + * '\u2460' - '\u24FF'. + */ + public static final UnicodeBlock ENCLOSED_ALPHANUMERICS + = new UnicodeBlock('\u2460', '\u24FF', + "ENCLOSED_ALPHANUMERICS"); + + /** + * Box Drawing. + * '\u2500' - '\u257F'. + */ + public static final UnicodeBlock BOX_DRAWING + = new UnicodeBlock('\u2500', '\u257F', + "BOX_DRAWING"); + + /** + * Block Elements. + * '\u2580' - '\u259F'. + */ + public static final UnicodeBlock BLOCK_ELEMENTS + = new UnicodeBlock('\u2580', '\u259F', + "BLOCK_ELEMENTS"); + + /** + * Geometric Shapes. + * '\u25A0' - '\u25FF'. + */ + public static final UnicodeBlock GEOMETRIC_SHAPES + = new UnicodeBlock('\u25A0', '\u25FF', + "GEOMETRIC_SHAPES"); + + /** + * Miscellaneous Symbols. + * '\u2600' - '\u26FF'. + */ + public static final UnicodeBlock MISCELLANEOUS_SYMBOLS + = new UnicodeBlock('\u2600', '\u26FF', + "MISCELLANEOUS_SYMBOLS"); + + /** + * Dingbats. + * '\u2700' - '\u27BF'. + */ + public static final UnicodeBlock DINGBATS + = new UnicodeBlock('\u2700', '\u27BF', + "DINGBATS"); + + /** + * Braille Patterns. + * '\u2800' - '\u28FF'. + * @since 1.4 + */ + public static final UnicodeBlock BRAILLE_PATTERNS + = new UnicodeBlock('\u2800', '\u28FF', + "BRAILLE_PATTERNS"); + + /** + * CJK Radicals Supplement. + * '\u2E80' - '\u2EFF'. + * @since 1.4 + */ + public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT + = new UnicodeBlock('\u2E80', '\u2EFF', + "CJK_RADICALS_SUPPLEMENT"); + + /** + * Kangxi Radicals. + * '\u2F00' - '\u2FDF'. + * @since 1.4 + */ + public static final UnicodeBlock KANGXI_RADICALS + = new UnicodeBlock('\u2F00', '\u2FDF', + "KANGXI_RADICALS"); + + /** + * Ideographic Description Characters. + * '\u2FF0' - '\u2FFF'. + * @since 1.4 + */ + public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS + = new UnicodeBlock('\u2FF0', '\u2FFF', + "IDEOGRAPHIC_DESCRIPTION_CHARACTERS"); + + /** + * CJK Symbols and Punctuation. + * '\u3000' - '\u303F'. + */ + public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION + = new UnicodeBlock('\u3000', '\u303F', + "CJK_SYMBOLS_AND_PUNCTUATION"); + + /** + * Hiragana. + * '\u3040' - '\u309F'. + */ + public static final UnicodeBlock HIRAGANA + = new UnicodeBlock('\u3040', '\u309F', + "HIRAGANA"); + + /** + * Katakana. + * '\u30A0' - '\u30FF'. + */ + public static final UnicodeBlock KATAKANA + = new UnicodeBlock('\u30A0', '\u30FF', + "KATAKANA"); + + /** + * Bopomofo. + * '\u3100' - '\u312F'. + */ + public static final UnicodeBlock BOPOMOFO + = new UnicodeBlock('\u3100', '\u312F', + "BOPOMOFO"); + + /** + * Hangul Compatibility Jamo. + * '\u3130' - '\u318F'. + */ + public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO + = new UnicodeBlock('\u3130', '\u318F', + "HANGUL_COMPATIBILITY_JAMO"); + + /** + * Kanbun. + * '\u3190' - '\u319F'. + */ + public static final UnicodeBlock KANBUN + = new UnicodeBlock('\u3190', '\u319F', + "KANBUN"); + + /** + * Bopomofo Extended. + * '\u31A0' - '\u31BF'. + * @since 1.4 + */ + public static final UnicodeBlock BOPOMOFO_EXTENDED + = new UnicodeBlock('\u31A0', '\u31BF', + "BOPOMOFO_EXTENDED"); + + /** + * Enclosed CJK Letters and Months. + * '\u3200' - '\u32FF'. + */ + public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS + = new UnicodeBlock('\u3200', '\u32FF', + "ENCLOSED_CJK_LETTERS_AND_MONTHS"); + + /** + * CJK Compatibility. + * '\u3300' - '\u33FF'. + */ + public static final UnicodeBlock CJK_COMPATIBILITY + = new UnicodeBlock('\u3300', '\u33FF', + "CJK_COMPATIBILITY"); + + /** + * CJK Unified Ideographs Extension A. + * '\u3400' - '\u4DB5'. + * @since 1.4 + */ + public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A + = new UnicodeBlock('\u3400', '\u4DB5', + "CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A"); + + /** + * CJK Unified Ideographs. + * '\u4E00' - '\u9FFF'. + */ + public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS + = new UnicodeBlock('\u4E00', '\u9FFF', + "CJK_UNIFIED_IDEOGRAPHS"); + + /** + * Yi Syllables. + * '\uA000' - '\uA48F'. + * @since 1.4 + */ + public static final UnicodeBlock YI_SYLLABLES + = new UnicodeBlock('\uA000', '\uA48F', + "YI_SYLLABLES"); + + /** + * Yi Radicals. + * '\uA490' - '\uA4CF'. + * @since 1.4 + */ + public static final UnicodeBlock YI_RADICALS + = new UnicodeBlock('\uA490', '\uA4CF', + "YI_RADICALS"); + + /** + * Hangul Syllables. + * '\uAC00' - '\uD7A3'. + */ + public static final UnicodeBlock HANGUL_SYLLABLES + = new UnicodeBlock('\uAC00', '\uD7A3', + "HANGUL_SYLLABLES"); + + /** + * Surrogates Area. + * '\uD800' - '\uDFFF'. + */ + public static final UnicodeBlock SURROGATES_AREA + = new UnicodeBlock('\uD800', '\uDFFF', + "SURROGATES_AREA"); + + /** + * Private Use Area. + * '\uE000' - '\uF8FF'. + */ + public static final UnicodeBlock PRIVATE_USE_AREA + = new UnicodeBlock('\uE000', '\uF8FF', + "PRIVATE_USE_AREA"); + + /** + * CJK Compatibility Ideographs. + * '\uF900' - '\uFAFF'. + */ + public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS + = new UnicodeBlock('\uF900', '\uFAFF', + "CJK_COMPATIBILITY_IDEOGRAPHS"); + + /** + * Alphabetic Presentation Forms. + * '\uFB00' - '\uFB4F'. + */ + public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS + = new UnicodeBlock('\uFB00', '\uFB4F', + "ALPHABETIC_PRESENTATION_FORMS"); + + /** + * Arabic Presentation Forms-A. + * '\uFB50' - '\uFDFF'. + */ + public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A + = new UnicodeBlock('\uFB50', '\uFDFF', + "ARABIC_PRESENTATION_FORMS_A"); + + /** + * Combining Half Marks. + * '\uFE20' - '\uFE2F'. + */ + public static final UnicodeBlock COMBINING_HALF_MARKS + = new UnicodeBlock('\uFE20', '\uFE2F', + "COMBINING_HALF_MARKS"); + + /** + * CJK Compatibility Forms. + * '\uFE30' - '\uFE4F'. + */ + public static final UnicodeBlock CJK_COMPATIBILITY_FORMS + = new UnicodeBlock('\uFE30', '\uFE4F', + "CJK_COMPATIBILITY_FORMS"); + + /** + * Small Form Variants. + * '\uFE50' - '\uFE6F'. + */ + public static final UnicodeBlock SMALL_FORM_VARIANTS + = new UnicodeBlock('\uFE50', '\uFE6F', + "SMALL_FORM_VARIANTS"); + + /** + * Arabic Presentation Forms-B. + * '\uFE70' - '\uFEFE'. + */ + public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B + = new UnicodeBlock('\uFE70', '\uFEFE', + "ARABIC_PRESENTATION_FORMS_B"); + + /** + * Halfwidth and Fullwidth Forms. + * '\uFF00' - '\uFFEF'. + */ + public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS + = new UnicodeBlock('\uFF00', '\uFFEF', + "HALFWIDTH_AND_FULLWIDTH_FORMS"); + + /** + * Specials. + * '\uFEFF', '\uFFF0' - '\uFFFD'. + */ + public static final UnicodeBlock SPECIALS + = new UnicodeBlock('\uFFF0', '\uFFFD', + "SPECIALS"); + + /** + * The defined subsets. + */ + private static final UnicodeBlock sets[] = { + BASIC_LATIN, + LATIN_1_SUPPLEMENT, + LATIN_EXTENDED_A, + LATIN_EXTENDED_B, + IPA_EXTENSIONS, + SPACING_MODIFIER_LETTERS, + COMBINING_DIACRITICAL_MARKS, + GREEK, + CYRILLIC, + ARMENIAN, + HEBREW, + ARABIC, + SYRIAC, + THAANA, + DEVANAGARI, + BENGALI, + GURMUKHI, + GUJARATI, + ORIYA, + TAMIL, + TELUGU, + KANNADA, + MALAYALAM, + SINHALA, + THAI, + LAO, + TIBETAN, + MYANMAR, + GEORGIAN, + HANGUL_JAMO, + ETHIOPIC, + CHEROKEE, + UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS, + OGHAM, + RUNIC, + KHMER, + MONGOLIAN, + LATIN_EXTENDED_ADDITIONAL, + GREEK_EXTENDED, + GENERAL_PUNCTUATION, + SUPERSCRIPTS_AND_SUBSCRIPTS, + CURRENCY_SYMBOLS, + COMBINING_MARKS_FOR_SYMBOLS, + LETTERLIKE_SYMBOLS, + NUMBER_FORMS, + ARROWS, + MATHEMATICAL_OPERATORS, + MISCELLANEOUS_TECHNICAL, + CONTROL_PICTURES, + OPTICAL_CHARACTER_RECOGNITION, + ENCLOSED_ALPHANUMERICS, + BOX_DRAWING, + BLOCK_ELEMENTS, + GEOMETRIC_SHAPES, + MISCELLANEOUS_SYMBOLS, + DINGBATS, + BRAILLE_PATTERNS, + CJK_RADICALS_SUPPLEMENT, + KANGXI_RADICALS, + IDEOGRAPHIC_DESCRIPTION_CHARACTERS, + CJK_SYMBOLS_AND_PUNCTUATION, + HIRAGANA, + KATAKANA, + BOPOMOFO, + HANGUL_COMPATIBILITY_JAMO, + KANBUN, + BOPOMOFO_EXTENDED, + ENCLOSED_CJK_LETTERS_AND_MONTHS, + CJK_COMPATIBILITY, + CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A, + CJK_UNIFIED_IDEOGRAPHS, + YI_SYLLABLES, + YI_RADICALS, + HANGUL_SYLLABLES, + SURROGATES_AREA, + PRIVATE_USE_AREA, + CJK_COMPATIBILITY_IDEOGRAPHS, + ALPHABETIC_PRESENTATION_FORMS, + ARABIC_PRESENTATION_FORMS_A, + COMBINING_HALF_MARKS, + CJK_COMPATIBILITY_FORMS, + SMALL_FORM_VARIANTS, + ARABIC_PRESENTATION_FORMS_B, + HALFWIDTH_AND_FULLWIDTH_FORMS, + SPECIALS, + }; + } // class UnicodeBlock + + /** + * The immutable value of this Character. + * + * @serial the value of this Character + */ + private final char value; + + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 3786198910865385080L; + + /** + * Smallest value allowed for radix arguments in Java. This value is 2. + * + * @see #digit(char, int) + * @see #forDigit(int, int) + * @see Integer#toString(int, int) + * @see Integer#valueOf(String) + */ + public static final int MIN_RADIX = 2; + + /** + * Largest value allowed for radix arguments in Java. This value is 36. + * + * @see #digit(char, int) + * @see #forDigit(int, int) + * @see Integer#toString(int, int) + * @see Integer#valueOf(String) + */ + public static final int MAX_RADIX = 36; + + /** + * The minimum value the char data type can hold. + * This value is <code>'\\u0000'</code>. + */ + public static final char MIN_VALUE = '\u0000'; + + /** + * The maximum value the char data type can hold. + * This value is <code>'\\uFFFF'</code>. + */ + public static final char MAX_VALUE = '\uFFFF'; + + /** + * Class object representing the primitive char data type. + * + * @since 1.1 + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('C'); + + /** + * Lu = Letter, Uppercase (Informative). + * + * @since 1.1 + */ + public static final byte UPPERCASE_LETTER = 1; + + /** + * Ll = Letter, Lowercase (Informative). + * + * @since 1.1 + */ + public static final byte LOWERCASE_LETTER = 2; + + /** + * Lt = Letter, Titlecase (Informative). + * + * @since 1.1 + */ + public static final byte TITLECASE_LETTER = 3; + + /** + * Mn = Mark, Non-Spacing (Normative). + * + * @since 1.1 + */ + public static final byte NON_SPACING_MARK = 6; + + /** + * Mc = Mark, Spacing Combining (Normative). + * + * @since 1.1 + */ + public static final byte COMBINING_SPACING_MARK = 8; + + /** + * Me = Mark, Enclosing (Normative). + * + * @since 1.1 + */ + public static final byte ENCLOSING_MARK = 7; + + /** + * Nd = Number, Decimal Digit (Normative). + * + * @since 1.1 + */ + public static final byte DECIMAL_DIGIT_NUMBER = 9; + + /** + * Nl = Number, Letter (Normative). + * + * @since 1.1 + */ + public static final byte LETTER_NUMBER = 10; + + /** + * No = Number, Other (Normative). + * + * @since 1.1 + */ + public static final byte OTHER_NUMBER = 11; + + /** + * Zs = Separator, Space (Normative). + * + * @since 1.1 + */ + public static final byte SPACE_SEPARATOR = 12; + + /** + * Zl = Separator, Line (Normative). + * + * @since 1.1 + */ + public static final byte LINE_SEPARATOR = 13; + + /** + * Zp = Separator, Paragraph (Normative). + * + * @since 1.1 + */ + public static final byte PARAGRAPH_SEPARATOR = 14; + + /** + * Cc = Other, Control (Normative). + * + * @since 1.1 + */ + public static final byte CONTROL = 15; + + /** + * Cf = Other, Format (Normative). + * + * @since 1.1 + */ + public static final byte FORMAT = 16; + + /** + * Cs = Other, Surrogate (Normative). + * + * @since 1.1 + */ + public static final byte SURROGATE = 19; + + /** + * Co = Other, Private Use (Normative). + * + * @since 1.1 + */ + public static final byte PRIVATE_USE = 18; + + /** + * Cn = Other, Not Assigned (Normative). + * + * @since 1.1 + */ + public static final byte UNASSIGNED = 0; + + /** + * Lm = Letter, Modifier (Informative). + * + * @since 1.1 + */ + public static final byte MODIFIER_LETTER = 4; + + /** + * Lo = Letter, Other (Informative). + * + * @since 1.1 + */ + public static final byte OTHER_LETTER = 5; + + /** + * Pc = Punctuation, Connector (Informative). + * + * @since 1.1 + */ + public static final byte CONNECTOR_PUNCTUATION = 23; + + /** + * Pd = Punctuation, Dash (Informative). + * + * @since 1.1 + */ + public static final byte DASH_PUNCTUATION = 20; + + /** + * Ps = Punctuation, Open (Informative). + * + * @since 1.1 + */ + public static final byte START_PUNCTUATION = 21; + + /** + * Pe = Punctuation, Close (Informative). + * + * @since 1.1 + */ + public static final byte END_PUNCTUATION = 22; + + /** + * Pi = Punctuation, Initial Quote (Informative). + * + * @since 1.4 + */ + public static final byte INITIAL_QUOTE_PUNCTUATION = 29; + + /** + * Pf = Punctuation, Final Quote (Informative). + * + * @since 1.4 + */ + public static final byte FINAL_QUOTE_PUNCTUATION = 30; + + /** + * Po = Punctuation, Other (Informative). + * + * @since 1.1 + */ + public static final byte OTHER_PUNCTUATION = 24; + + /** + * Sm = Symbol, Math (Informative). + * + * @since 1.1 + */ + public static final byte MATH_SYMBOL = 25; + + /** + * Sc = Symbol, Currency (Informative). + * + * @since 1.1 + */ + public static final byte CURRENCY_SYMBOL = 26; + + /** + * Sk = Symbol, Modifier (Informative). + * + * @since 1.1 + */ + public static final byte MODIFIER_SYMBOL = 27; + + /** + * So = Symbol, Other (Informative). + * + * @since 1.1 + */ + public static final byte OTHER_SYMBOL = 28; + + /** + * Undefined bidirectional character type. Undefined char values have + * undefined directionality in the Unicode specification. + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_UNDEFINED = -1; + + /** + * Strong bidirectional character type "L". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0; + + /** + * Strong bidirectional character type "R". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1; + + /** + * Strong bidirectional character type "AL". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2; + + /** + * Weak bidirectional character type "EN". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 3; + + /** + * Weak bidirectional character type "ES". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4; + + /** + * Weak bidirectional character type "ET". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5; + + /** + * Weak bidirectional character type "AN". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_ARABIC_NUMBER = 6; + + /** + * Weak bidirectional character type "CS". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7; + + /** + * Weak bidirectional character type "NSM". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_NONSPACING_MARK = 8; + + /** + * Weak bidirectional character type "BN". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 9; + + /** + * Neutral bidirectional character type "B". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10; + + /** + * Neutral bidirectional character type "S". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 11; + + /** + * Strong bidirectional character type "WS". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_WHITESPACE = 12; + + /** + * Neutral bidirectional character type "ON". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 13; + + /** + * Strong bidirectional character type "LRE". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14; + + /** + * Strong bidirectional character type "LRO". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15; + + /** + * Strong bidirectional character type "RLE". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16; + + /** + * Strong bidirectional character type "RLO". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17; + + /** + * Weak bidirectional character type "PDF". + * + * @since 1.4 + */ + public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18; + + /** + * Stores unicode block offset lookup table. Exploit package visibility of + * String.value to avoid copying the array. + * @see #readChar(char) + * @see CharData#BLOCKS + */ + private static final char[] blocks = String.zeroBasedStringValue(CharData.BLOCKS); + + /** + * Stores unicode attribute offset lookup table. Exploit package visibility + * of String.value to avoid copying the array. + * @see CharData#DATA + */ + private static final char[] data = String.zeroBasedStringValue(CharData.DATA); + + /** + * Stores unicode numeric value attribute table. Exploit package visibility + * of String.value to avoid copying the array. + * @see CharData#NUM_VALUE + */ + private static final char[] numValue + = String.zeroBasedStringValue(CharData.NUM_VALUE); + + /** + * Stores unicode uppercase attribute table. Exploit package visibility + * of String.value to avoid copying the array. + * @see CharData#UPPER + */ + private static final char[] upper = String.zeroBasedStringValue(CharData.UPPER); + + /** + * Stores unicode lowercase attribute table. Exploit package visibility + * of String.value to avoid copying the array. + * @see CharData#LOWER + */ + private static final char[] lower = String.zeroBasedStringValue(CharData.LOWER); + + /** + * Stores unicode direction attribute table. Exploit package visibility + * of String.value to avoid copying the array. + * @see CharData#DIRECTION + */ + // Package visible for use by String. + static final char[] direction = String.zeroBasedStringValue(CharData.DIRECTION); + + /** + * Stores unicode titlecase table. Exploit package visibility of + * String.value to avoid copying the array. + * @see CharData#TITLE + */ + private static final char[] title = String.zeroBasedStringValue(CharData.TITLE); + + /** + * Mask for grabbing the type out of the contents of data. + * @see CharData#DATA + */ + private static final int TYPE_MASK = 0x1F; + + /** + * Mask for grabbing the non-breaking space flag out of the contents of + * data. + * @see CharData#DATA + */ + private static final int NO_BREAK_MASK = 0x20; + + /** + * Mask for grabbing the mirrored directionality flag out of the contents + * of data. + * @see CharData#DATA + */ + private static final int MIRROR_MASK = 0x40; + + /** + * Grabs an attribute offset from the Unicode attribute database. The lower + * 5 bits are the character type, the next 2 bits are flags, and the top + * 9 bits are the offset into the attribute tables. + * + * @param ch the character to look up + * @return the character's attribute offset and type + * @see #TYPE_MASK + * @see #NO_BREAK_MASK + * @see #MIRROR_MASK + * @see CharData#DATA + * @see CharData#SHIFT + */ + // Package visible for use in String. + static char readChar(char ch) + { + // Perform 16-bit addition to find the correct entry in data. + return data[(char) (blocks[ch >> CharData.SHIFT] + ch)]; + } + + /** + * Wraps up a character. + * + * @param value the character to wrap + */ + public Character(char value) + { + this.value = value; + } + + /** + * Returns the character which has been wrapped by this class. + * + * @return the character wrapped + */ + public char charValue() + { + return value; + } + + /** + * Returns the numerical value (unsigned) of the wrapped character. + * Range of returned values: 0x0000-0xFFFF. + * + * @return the value of the wrapped character + */ + public int hashCode() + { + return value; + } + + /** + * Determines if an object is equal to this object. This is only true for + * another Character object wrapping the same value. + * + * @param o object to compare + * @return true if o is a Character with the same value + */ + public boolean equals(Object o) + { + return o instanceof Character && value == ((Character) o).value; + } + + /** + * Converts the wrapped character into a String. + * + * @return a String containing one character -- the wrapped character + * of this instance + */ + public String toString() + { + // Package constructor avoids an array copy. + return new String(new char[] { value }, 0, 1, true); + } + + /** + * Returns a String of length 1 representing the specified character. + * + * @param ch the character to convert + * @return a String containing the character + * @since 1.4 + */ + public static String toString(char ch) + { + // Package constructor avoids an array copy. + return new String(new char[] { ch }, 0, 1, true); + } + + /** + * Determines if a character is a Unicode lowercase letter. For example, + * <code>'a'</code> is lowercase. + * <br> + * lowercase = [Ll] + * + * @param ch character to test + * @return true if ch is a Unicode lowercase letter, else false + * @see #isUpperCase(char) + * @see #isTitleCase(char) + * @see #toLowerCase(char) + * @see #getType(char) + */ + public static boolean isLowerCase(char ch) + { + return getType(ch) == LOWERCASE_LETTER; + } + + /** + * Determines if a character is a Unicode uppercase letter. For example, + * <code>'A'</code> is uppercase. + * <br> + * uppercase = [Lu] + * + * @param ch character to test + * @return true if ch is a Unicode uppercase letter, else false + * @see #isLowerCase(char) + * @see #isTitleCase(char) + * @see #toUpperCase(char) + * @see #getType(char) + */ + public static boolean isUpperCase(char ch) + { + return getType(ch) == UPPERCASE_LETTER; + } + + /** + * Determines if a character is a Unicode titlecase letter. For example, + * the character "Lj" (Latin capital L with small letter j) is titlecase. + * <br> + * titlecase = [Lt] + * + * @param ch character to test + * @return true if ch is a Unicode titlecase letter, else false + * @see #isLowerCase(char) + * @see #isUpperCase(char) + * @see #toTitleCase(char) + * @see #getType(char) + */ + public static boolean isTitleCase(char ch) + { + return getType(ch) == TITLECASE_LETTER; + } + + /** + * Determines if a character is a Unicode decimal digit. For example, + * <code>'0'</code> is a digit. + * <br> + * Unicode decimal digit = [Nd] + * + * @param ch character to test + * @return true if ch is a Unicode decimal digit, else false + * @see #digit(char, int) + * @see #forDigit(int, int) + * @see #getType(char) + */ + public static boolean isDigit(char ch) + { + return getType(ch) == DECIMAL_DIGIT_NUMBER; + } + + /** + * Determines if a character is part of the Unicode Standard. This is an + * evolving standard, but covers every character in the data file. + * <br> + * defined = not [Cn] + * + * @param ch character to test + * @return true if ch is a Unicode character, else false + * @see #isDigit(char) + * @see #isLetter(char) + * @see #isLetterOrDigit(char) + * @see #isLowerCase(char) + * @see #isTitleCase(char) + * @see #isUpperCase(char) + */ + public static boolean isDefined(char ch) + { + return getType(ch) != UNASSIGNED; + } + + /** + * Determines if a character is a Unicode letter. Not all letters have case, + * so this may return true when isLowerCase and isUpperCase return false. + * <br> + * letter = [Lu]|[Ll]|[Lt]|[Lm]|[Lo] + * + * @param ch character to test + * @return true if ch is a Unicode letter, else false + * @see #isDigit(char) + * @see #isJavaIdentifierStart(char) + * @see #isJavaLetter(char) + * @see #isJavaLetterOrDigit(char) + * @see #isLetterOrDigit(char) + * @see #isLowerCase(char) + * @see #isTitleCase(char) + * @see #isUnicodeIdentifierStart(char) + * @see #isUpperCase(char) + */ + public static boolean isLetter(char ch) + { + return ((1 << getType(ch)) + & ((1 << UPPERCASE_LETTER) + | (1 << LOWERCASE_LETTER) + | (1 << TITLECASE_LETTER) + | (1 << MODIFIER_LETTER) + | (1 << OTHER_LETTER))) != 0; + } + + /** + * Determines if a character is a Unicode letter or a Unicode digit. This + * is the combination of isLetter and isDigit. + * <br> + * letter or digit = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nd] + * + * @param ch character to test + * @return true if ch is a Unicode letter or a Unicode digit, else false + * @see #isDigit(char) + * @see #isJavaIdentifierPart(char) + * @see #isJavaLetter(char) + * @see #isJavaLetterOrDigit(char) + * @see #isLetter(char) + * @see #isUnicodeIdentifierPart(char) + */ + public static boolean isLetterOrDigit(char ch) + { + return ((1 << getType(ch)) + & ((1 << UPPERCASE_LETTER) + | (1 << LOWERCASE_LETTER) + | (1 << TITLECASE_LETTER) + | (1 << MODIFIER_LETTER) + | (1 << OTHER_LETTER) + | (1 << DECIMAL_DIGIT_NUMBER))) != 0; + } + + /** + * Determines if a character can start a Java identifier. This is the + * combination of isLetter, any character where getType returns + * LETTER_NUMBER, currency symbols (like '$'), and connecting punctuation + * (like '_'). + * + * @param ch character to test + * @return true if ch can start a Java identifier, else false + * @deprecated Replaced by {@link #isJavaIdentifierStart(char)} + * @see #isJavaLetterOrDigit(char) + * @see #isJavaIdentifierStart(char) + * @see #isJavaIdentifierPart(char) + * @see #isLetter(char) + * @see #isLetterOrDigit(char) + * @see #isUnicodeIdentifierStart(char) + */ + public static boolean isJavaLetter(char ch) + { + return isJavaIdentifierStart(ch); + } + + /** + * Determines if a character can follow the first letter in + * a Java identifier. This is the combination of isJavaLetter (isLetter, + * type of LETTER_NUMBER, currency, connecting punctuation) and digit, + * numeric letter (like Roman numerals), combining marks, non-spacing marks, + * or isIdentifierIgnorable. + * + * @param ch character to test + * @return true if ch can follow the first letter in a Java identifier + * @deprecated Replaced by {@link #isJavaIdentifierPart(char)} + * @see #isJavaLetter(char) + * @see #isJavaIdentifierStart(char) + * @see #isJavaIdentifierPart(char) + * @see #isLetter(char) + * @see #isLetterOrDigit(char) + * @see #isUnicodeIdentifierPart(char) + * @see #isIdentifierIgnorable(char) + */ + public static boolean isJavaLetterOrDigit(char ch) + { + return isJavaIdentifierPart(ch); + } + + /** + * Determines if a character can start a Java identifier. This is the + * combination of isLetter, any character where getType returns + * LETTER_NUMBER, currency symbols (like '$'), and connecting punctuation + * (like '_'). + * <br> + * Java identifier start = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]|[Sc]|[Pc] + * + * @param ch character to test + * @return true if ch can start a Java identifier, else false + * @see #isJavaIdentifierPart(char) + * @see #isLetter(char) + * @see #isUnicodeIdentifierStart(char) + * @since 1.1 + */ + public static boolean isJavaIdentifierStart(char ch) + { + return ((1 << getType(ch)) + & ((1 << UPPERCASE_LETTER) + | (1 << LOWERCASE_LETTER) + | (1 << TITLECASE_LETTER) + | (1 << MODIFIER_LETTER) + | (1 << OTHER_LETTER) + | (1 << LETTER_NUMBER) + | (1 << CURRENCY_SYMBOL) + | (1 << CONNECTOR_PUNCTUATION))) != 0; + } + + /** + * Determines if a character can follow the first letter in + * a Java identifier. This is the combination of isJavaLetter (isLetter, + * type of LETTER_NUMBER, currency, connecting punctuation) and digit, + * numeric letter (like Roman numerals), combining marks, non-spacing marks, + * or isIdentifierIgnorable. + * <br> + * Java identifier extender = + * [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]|[Sc]|[Pc]|[Mn]|[Mc]|[Nd]|[Cf] + * |U+0000-U+0008|U+000E-U+001B|U+007F-U+009F + * + * @param ch character to test + * @return true if ch can follow the first letter in a Java identifier + * @see #isIdentifierIgnorable(char) + * @see #isJavaIdentifierStart(char) + * @see #isLetterOrDigit(char) + * @see #isUnicodeIdentifierPart(char) + * @since 1.1 + */ + public static boolean isJavaIdentifierPart(char ch) + { + int category = getType(ch); + return ((1 << category) + & ((1 << UPPERCASE_LETTER) + | (1 << LOWERCASE_LETTER) + | (1 << TITLECASE_LETTER) + | (1 << MODIFIER_LETTER) + | (1 << OTHER_LETTER) + | (1 << NON_SPACING_MARK) + | (1 << COMBINING_SPACING_MARK) + | (1 << DECIMAL_DIGIT_NUMBER) + | (1 << LETTER_NUMBER) + | (1 << CURRENCY_SYMBOL) + | (1 << CONNECTOR_PUNCTUATION) + | (1 << FORMAT))) != 0 + || (category == CONTROL && isIdentifierIgnorable(ch)); + } + + /** + * Determines if a character can start a Unicode identifier. Only + * letters can start a Unicode identifier, but this includes characters + * in LETTER_NUMBER. + * <br> + * Unicode identifier start = [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl] + * + * @param ch character to test + * @return true if ch can start a Unicode identifier, else false + * @see #isJavaIdentifierStart(char) + * @see #isLetter(char) + * @see #isUnicodeIdentifierPart(char) + * @since 1.1 + */ + public static boolean isUnicodeIdentifierStart(char ch) + { + return ((1 << getType(ch)) + & ((1 << UPPERCASE_LETTER) + | (1 << LOWERCASE_LETTER) + | (1 << TITLECASE_LETTER) + | (1 << MODIFIER_LETTER) + | (1 << OTHER_LETTER) + | (1 << LETTER_NUMBER))) != 0; + } + + /** + * Determines if a character can follow the first letter in + * a Unicode identifier. This includes letters, connecting punctuation, + * digits, numeric letters, combining marks, non-spacing marks, and + * isIdentifierIgnorable. + * <br> + * Unicode identifier extender = + * [Lu]|[Ll]|[Lt]|[Lm]|[Lo]|[Nl]|[Mn]|[Mc]|[Nd]|[Pc]|[Cf]| + * |U+0000-U+0008|U+000E-U+001B|U+007F-U+009F + * + * @param ch character to test + * @return true if ch can follow the first letter in a Unicode identifier + * @see #isIdentifierIgnorable(char) + * @see #isJavaIdentifierPart(char) + * @see #isLetterOrDigit(char) + * @see #isUnicodeIdentifierStart(char) + * @since 1.1 + */ + public static boolean isUnicodeIdentifierPart(char ch) + { + int category = getType(ch); + return ((1 << category) + & ((1 << UPPERCASE_LETTER) + | (1 << LOWERCASE_LETTER) + | (1 << TITLECASE_LETTER) + | (1 << MODIFIER_LETTER) + | (1 << OTHER_LETTER) + | (1 << NON_SPACING_MARK) + | (1 << COMBINING_SPACING_MARK) + | (1 << DECIMAL_DIGIT_NUMBER) + | (1 << LETTER_NUMBER) + | (1 << CONNECTOR_PUNCTUATION) + | (1 << FORMAT))) != 0 + || (category == CONTROL && isIdentifierIgnorable(ch)); + } + + /** + * Determines if a character is ignorable in a Unicode identifier. This + * includes the non-whitespace ISO control characters (<code>'\u0000'</code> + * through <code>'\u0008'</code>, <code>'\u000E'</code> through + * <code>'\u001B'</code>, and <code>'\u007F'</code> through + * <code>'\u009F'</code>), and FORMAT characters. + * <br> + * Unicode identifier ignorable = [Cf]|U+0000-U+0008|U+000E-U+001B + * |U+007F-U+009F + * + * @param ch character to test + * @return true if ch is ignorable in a Unicode or Java identifier + * @see #isJavaIdentifierPart(char) + * @see #isUnicodeIdentifierPart(char) + * @since 1.1 + */ + public static boolean isIdentifierIgnorable(char ch) + { + return (ch <= '\u009F' && (ch < '\t' || ch >= '\u007F' + || (ch <= '\u001B' && ch >= '\u000E'))) + || getType(ch) == FORMAT; + } + + /** + * Converts a Unicode character into its lowercase equivalent mapping. + * If a mapping does not exist, then the character passed is returned. + * Note that isLowerCase(toLowerCase(ch)) does not always return true. + * + * @param ch character to convert to lowercase + * @return lowercase mapping of ch, or ch if lowercase mapping does + * not exist + * @see #isLowerCase(char) + * @see #isUpperCase(char) + * @see #toTitleCase(char) + * @see #toUpperCase(char) + */ + public static char toLowerCase(char ch) + { + // Signedness doesn't matter, as result is cast back to char. + return (char) (ch + lower[readChar(ch) >> 7]); + } + + /** + * Converts a Unicode character into its uppercase equivalent mapping. + * If a mapping does not exist, then the character passed is returned. + * Note that isUpperCase(toUpperCase(ch)) does not always return true. + * + * @param ch character to convert to uppercase + * @return uppercase mapping of ch, or ch if uppercase mapping does + * not exist + * @see #isLowerCase(char) + * @see #isUpperCase(char) + * @see #toLowerCase(char) + * @see #toTitleCase(char) + */ + public static char toUpperCase(char ch) + { + // Signedness doesn't matter, as result is cast back to char. + return (char) (ch + upper[readChar(ch) >> 7]); + } + + /** + * Converts a Unicode character into its titlecase equivalent mapping. + * If a mapping does not exist, then the character passed is returned. + * Note that isTitleCase(toTitleCase(ch)) does not always return true. + * + * @param ch character to convert to titlecase + * @return titlecase mapping of ch, or ch if titlecase mapping does + * not exist + * @see #isTitleCase(char) + * @see #toLowerCase(char) + * @see #toUpperCase(char) + */ + public static char toTitleCase(char ch) + { + // As title is short, it doesn't hurt to exhaustively iterate over it. + for (int i = title.length - 2; i >= 0; i -= 2) + if (title[i] == ch) + return title[i + 1]; + return toUpperCase(ch); + } + + /** + * Converts a character into a digit of the specified radix. If the radix + * exceeds MIN_RADIX or MAX_RADIX, or if the result of getNumericValue(ch) + * exceeds the radix, or if ch is not a decimal digit or in the case + * insensitive set of 'a'-'z', the result is -1. + * <br> + * character argument boundary = [Nd]|U+0041-U+005A|U+0061-U+007A + * |U+FF21-U+FF3A|U+FF41-U+FF5A + * + * @param ch character to convert into a digit + * @param radix radix in which ch is a digit + * @return digit which ch represents in radix, or -1 not a valid digit + * @see #MIN_RADIX + * @see #MAX_RADIX + * @see #forDigit(int, int) + * @see #isDigit(char) + * @see #getNumericValue(char) + */ + public static int digit(char ch, int radix) + { + if (radix < MIN_RADIX || radix > MAX_RADIX) + return -1; + char attr = readChar(ch); + if (((1 << (attr & TYPE_MASK)) + & ((1 << UPPERCASE_LETTER) + | (1 << LOWERCASE_LETTER) + | (1 << DECIMAL_DIGIT_NUMBER))) != 0) + { + // Signedness doesn't matter; 0xffff vs. -1 are both rejected. + int digit = numValue[attr >> 7]; + return (digit < radix) ? digit : -1; + } + return -1; + } + + /** + * Returns the Unicode numeric value property of a character. For example, + * <code>'\\u216C'</code> (the Roman numeral fifty) returns 50. + * + * <p>This method also returns values for the letters A through Z, (not + * specified by Unicode), in these ranges: <code>'\u0041'</code> + * through <code>'\u005A'</code> (uppercase); <code>'\u0061'</code> + * through <code>'\u007A'</code> (lowercase); and <code>'\uFF21'</code> + * through <code>'\uFF3A'</code>, <code>'\uFF41'</code> through + * <code>'\uFF5A'</code> (full width variants). + * + * <p>If the character lacks a numeric value property, -1 is returned. + * If the character has a numeric value property which is not representable + * as a nonnegative integer, such as a fraction, -2 is returned. + * + * character argument boundary = [Nd]|[Nl]|[No]|U+0041-U+005A|U+0061-U+007A + * |U+FF21-U+FF3A|U+FF41-U+FF5A + * + * @param ch character from which the numeric value property will + * be retrieved + * @return the numeric value property of ch, or -1 if it does not exist, or + * -2 if it is not representable as a nonnegative integer + * @see #forDigit(int, int) + * @see #digit(char, int) + * @see #isDigit(char) + * @since 1.1 + */ + public static int getNumericValue(char ch) + { + // Treat numValue as signed. + return (short) numValue[readChar(ch) >> 7]; + } + + /** + * Determines if a character is a ISO-LATIN-1 space. This is only the five + * characters <code>'\t'</code>, <code>'\n'</code>, <code>'\f'</code>, + * <code>'\r'</code>, and <code>' '</code>. + * <br> + * Java space = U+0020|U+0009|U+000A|U+000C|U+000D + * + * @param ch character to test + * @return true if ch is a space, else false + * @deprecated Replaced by {@link #isWhitespace(char)} + * @see #isSpaceChar(char) + * @see #isWhitespace(char) + */ + public static boolean isSpace(char ch) + { + // Performing the subtraction up front alleviates need to compare longs. + return ch-- <= ' ' && ((1 << ch) + & ((1 << (' ' - 1)) + | (1 << ('\t' - 1)) + | (1 << ('\n' - 1)) + | (1 << ('\r' - 1)) + | (1 << ('\f' - 1)))) != 0; + } + + /** + * Determines if a character is a Unicode space character. This includes + * SPACE_SEPARATOR, LINE_SEPARATOR, and PARAGRAPH_SEPARATOR. + * <br> + * Unicode space = [Zs]|[Zp]|[Zl] + * + * @param ch character to test + * @return true if ch is a Unicode space, else false + * @see #isWhitespace(char) + * @since 1.1 + */ + public static boolean isSpaceChar(char ch) + { + return ((1 << getType(ch)) + & ((1 << SPACE_SEPARATOR) + | (1 << LINE_SEPARATOR) + | (1 << PARAGRAPH_SEPARATOR))) != 0; + } + + /** + * Determines if a character is Java whitespace. This includes Unicode + * space characters (SPACE_SEPARATOR, LINE_SEPARATOR, and + * PARAGRAPH_SEPARATOR) except the non-breaking spaces + * (<code>'\u00A0'</code>, <code>'\u2007'</code>, and <code>'\u202F'</code>); + * and these characters: <code>'\u0009'</code>, <code>'\u000A'</code>, + * <code>'\u000B'</code>, <code>'\u000C'</code>, <code>'\u000D'</code>, + * <code>'\u001C'</code>, <code>'\u001D'</code>, <code>'\u001E'</code>, + * and <code>'\u001F'</code>. + * <br> + * Java whitespace = ([Zs] not Nb)|[Zl]|[Zp]|U+0009-U+000D|U+001C-U+001F + * + * @param ch character to test + * @return true if ch is Java whitespace, else false + * @see #isSpaceChar(char) + * @since 1.1 + */ + public static boolean isWhitespace(char ch) + { + int attr = readChar(ch); + return ((((1 << (attr & TYPE_MASK)) + & ((1 << SPACE_SEPARATOR) + | (1 << LINE_SEPARATOR) + | (1 << PARAGRAPH_SEPARATOR))) != 0) + && (attr & NO_BREAK_MASK) == 0) + || (ch <= '\u001F' && ((1 << ch) + & ((1 << '\t') + | (1 << '\n') + | (1 << '\u000B') + | (1 << '\u000C') + | (1 << '\r') + | (1 << '\u001C') + | (1 << '\u001D') + | (1 << '\u001E') + | (1 << '\u001F'))) != 0); + } + + /** + * Determines if a character has the ISO Control property. + * <br> + * ISO Control = [Cc] + * + * @param ch character to test + * @return true if ch is an ISO Control character, else false + * @see #isSpaceChar(char) + * @see #isWhitespace(char) + * @since 1.1 + */ + public static boolean isISOControl(char ch) + { + return getType(ch) == CONTROL; + } + + /** + * Returns the Unicode general category property of a character. + * + * @param ch character from which the general category property will + * be retrieved + * @return the character category property of ch as an integer + * @see #UNASSIGNED + * @see #UPPERCASE_LETTER + * @see #LOWERCASE_LETTER + * @see #TITLECASE_LETTER + * @see #MODIFIER_LETTER + * @see #OTHER_LETTER + * @see #NON_SPACING_MARK + * @see #ENCLOSING_MARK + * @see #COMBINING_SPACING_MARK + * @see #DECIMAL_DIGIT_NUMBER + * @see #LETTER_NUMBER + * @see #OTHER_NUMBER + * @see #SPACE_SEPARATOR + * @see #LINE_SEPARATOR + * @see #PARAGRAPH_SEPARATOR + * @see #CONTROL + * @see #FORMAT + * @see #PRIVATE_USE + * @see #SURROGATE + * @see #DASH_PUNCTUATION + * @see #START_PUNCTUATION + * @see #END_PUNCTUATION + * @see #CONNECTOR_PUNCTUATION + * @see #OTHER_PUNCTUATION + * @see #MATH_SYMBOL + * @see #CURRENCY_SYMBOL + * @see #MODIFIER_SYMBOL + * @see #INITIAL_QUOTE_PUNCTUATION + * @see #FINAL_QUOTE_PUNCTUATION + * @since 1.1 + */ + public static int getType(char ch) + { + return readChar(ch) & TYPE_MASK; + } + + /** + * Converts a digit into a character which represents that digit + * in a specified radix. If the radix exceeds MIN_RADIX or MAX_RADIX, + * or the digit exceeds the radix, then the null character <code>'\0'</code> + * is returned. Otherwise the return value is in '0'-'9' and 'a'-'z'. + * <br> + * return value boundary = U+0030-U+0039|U+0061-U+007A + * + * @param digit digit to be converted into a character + * @param radix radix of digit + * @return character representing digit in radix, or '\0' + * @see #MIN_RADIX + * @see #MAX_RADIX + * @see #digit(char, int) + */ + public static char forDigit(int digit, int radix) + { + if (radix < MIN_RADIX || radix > MAX_RADIX + || digit < 0 || digit >= radix) + return '\0'; + return Number.digits[digit]; + } + + /** + * Returns the Unicode directionality property of the character. This + * is used in the visual ordering of text. + * + * @param ch the character to look up + * @return the directionality constant, or DIRECTIONALITY_UNDEFINED + * @see #DIRECTIONALITY_UNDEFINED + * @see #DIRECTIONALITY_LEFT_TO_RIGHT + * @see #DIRECTIONALITY_RIGHT_TO_LEFT + * @see #DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC + * @see #DIRECTIONALITY_EUROPEAN_NUMBER + * @see #DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR + * @see #DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR + * @see #DIRECTIONALITY_ARABIC_NUMBER + * @see #DIRECTIONALITY_COMMON_NUMBER_SEPARATOR + * @see #DIRECTIONALITY_NONSPACING_MARK + * @see #DIRECTIONALITY_BOUNDARY_NEUTRAL + * @see #DIRECTIONALITY_PARAGRAPH_SEPARATOR + * @see #DIRECTIONALITY_SEGMENT_SEPARATOR + * @see #DIRECTIONALITY_WHITESPACE + * @see #DIRECTIONALITY_OTHER_NEUTRALS + * @see #DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING + * @see #DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE + * @see #DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING + * @see #DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE + * @see #DIRECTIONALITY_POP_DIRECTIONAL_FORMAT + * @since 1.4 + */ + public static byte getDirectionality(char ch) + { + // The result will correctly be signed. + return (byte) (direction[readChar(ch) >> 7] >> 2); + } + + /** + * Determines whether the character is mirrored according to Unicode. For + * example, <code>\u0028</code> (LEFT PARENTHESIS) appears as '(' in + * left-to-right text, but ')' in right-to-left text. + * + * @param ch the character to look up + * @return true if the character is mirrored + * @since 1.4 + */ + public static boolean isMirrored(char ch) + { + return (readChar(ch) & MIRROR_MASK) != 0; + } + + /** + * Compares another Character to this Character, numerically. + * + * @param anotherCharacter Character to compare with this Character + * @return a negative integer if this Character is less than + * anotherCharacter, zero if this Character is equal, and + * a positive integer if this Character is greater + * @throws NullPointerException if anotherCharacter is null + * @since 1.2 + */ + public int compareTo(Character anotherCharacter) + { + return value - anotherCharacter.value; + } + + /** + * Compares an object to this Character. Assuming the object is a + * Character object, this method performs the same comparison as + * compareTo(Character). + * + * @param o object to compare + * @return the comparison value + * @throws ClassCastException if o is not a Character object + * @throws NullPointerException if o is null + * @see #compareTo(Character) + * @since 1.2 + */ + public int compareTo(Object o) + { + return compareTo((Character) o); + } +} // class Character diff --git a/libjava/classpath/java/lang/Class.java b/libjava/classpath/java/lang/Class.java new file mode 100644 index 0000000..6b8bc93 --- /dev/null +++ b/libjava/classpath/java/lang/Class.java @@ -0,0 +1,1324 @@ +/* Class.java -- Representation of a Java class. + Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import gnu.classpath.VMStackWalker; + +import java.io.InputStream; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.security.AccessController; +import java.security.AllPermission; +import java.security.Permissions; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; + + +/** + * A Class represents a Java type. There will never be multiple Class + * objects with identical names and ClassLoaders. Primitive types, array + * types, and void also have a Class object. + * + * <p>Arrays with identical type and number of dimensions share the same class. + * The array class ClassLoader is the same as the ClassLoader of the element + * type of the array (which can be null to indicate the bootstrap classloader). + * The name of an array class is <code>[<signature format>;</code>. + * <p> For example, + * String[]'s class is <code>[Ljava.lang.String;</code>. boolean, byte, + * short, char, int, long, float and double have the "type name" of + * Z,B,S,C,I,J,F,D for the purposes of array classes. If it's a + * multidimensioned array, the same principle applies: + * <code>int[][][]</code> == <code>[[[I</code>. + * + * <p>There is no public constructor - Class objects are obtained only through + * the virtual machine, as defined in ClassLoaders. + * + * @serialData Class objects serialize specially: + * <code>TC_CLASS ClassDescriptor</code>. For more serialization information, + * see {@link ObjectStreamClass}. + * + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @author Tom Tromey (tromey@cygnus.com) + * @since 1.0 + * @see ClassLoader + */ +public final class Class implements Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 3206093459760846163L; + + /** The class signers. */ + private Object[] signers = null; + /** The class protection domain. */ + private final ProtectionDomain pd; + + /* We use an inner class, so that Class doesn't have a static initializer */ + private static final class StaticData + { + static final ProtectionDomain unknownProtectionDomain; + + static + { + Permissions permissions = new Permissions(); + permissions.add(new AllPermission()); + unknownProtectionDomain = new ProtectionDomain(null, permissions); + } + } + + final transient Object vmdata; + + /** newInstance() caches the default constructor */ + private transient Constructor constructor; + + /** + * Class is non-instantiable from Java code; only the VM can create + * instances of this class. + */ + Class(Object vmdata) + { + this(vmdata, null); + } + + Class(Object vmdata, ProtectionDomain pd) + { + this.vmdata = vmdata; + // If the VM didn't supply a protection domain and the class is an array, + // we "inherit" the protection domain from the component type class. This + // saves the VM from having to worry about protection domains for array + // classes. + if (pd == null && isArray()) + this.pd = getComponentType().pd; + else + this.pd = pd; + } + + /** + * Use the classloader of the current class to load, link, and initialize + * a class. This is equivalent to your code calling + * <code>Class.forName(name, true, getClass().getClassLoader())</code>. + * + * @param name the name of the class to find + * @return the Class object representing the class + * @throws ClassNotFoundException if the class was not found by the + * classloader + * @throws LinkageError if linking the class fails + * @throws ExceptionInInitializerError if the class loads, but an exception + * occurs during initialization + */ + public static Class forName(String name) throws ClassNotFoundException + { + Class result = VMClass.forName (name); + if (result == null) + result = Class.forName(name, true, + VMStackWalker.getCallingClassLoader()); + return result; + } + + /** + * Use the specified classloader to load and link a class. If the loader + * is null, this uses the bootstrap class loader (provide the security + * check succeeds). Unfortunately, this method cannot be used to obtain + * the Class objects for primitive types or for void, you have to use + * the fields in the appropriate java.lang wrapper classes. + * + * <p>Calls <code>classloader.loadclass(name, initialize)</code>. + * + * @param name the name of the class to find + * @param initialize whether or not to initialize the class at this time + * @param classloader the classloader to use to find the class; null means + * to use the bootstrap class loader + * + * @return the class object for the given class + * + * @throws ClassNotFoundException if the class was not found by the + * classloader + * @throws LinkageError if linking the class fails + * @throws ExceptionInInitializerError if the class loads, but an exception + * occurs during initialization + * @throws SecurityException if the <code>classloader</code> argument + * is <code>null</code> and the caller does not have the + * <code>RuntimePermission("getClassLoader")</code> permission + * @see ClassLoader + * @since 1.2 + */ + public static Class forName(String name, boolean initialize, + ClassLoader classloader) + throws ClassNotFoundException + { + if (classloader == null) + { + // Check if we may access the bootstrap classloader + SecurityManager sm = SecurityManager.current; + if (sm != null) + { + // Get the calling classloader + ClassLoader cl = VMStackWalker.getCallingClassLoader(); + if (cl != null) + sm.checkPermission(new RuntimePermission("getClassLoader")); + } + if (name.startsWith("[")) + return VMClass.loadArrayClass(name, null); + Class c = VMClassLoader.loadClass(name, true); + if (c != null) + { + if (initialize) + VMClass.initialize(c); + return c; + } + throw new ClassNotFoundException(name); + } + if (name.startsWith("[")) + return VMClass.loadArrayClass(name, classloader); + Class c = classloader.loadClass(name); + classloader.resolveClass(c); + if (initialize) + VMClass.initialize(c); + return c; + } + + /** + * Get all the public member classes and interfaces declared in this + * class or inherited from superclasses. This returns an array of length + * 0 if there are no member classes, including for primitive types. A + * security check may be performed, with + * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @return all public member classes in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Class[] getClasses() + { + memberAccessCheck(Member.PUBLIC); + return internalGetClasses(); + } + + /** + * Like <code>getClasses()</code> but without the security checks. + */ + private Class[] internalGetClasses() + { + ArrayList list = new ArrayList(); + list.addAll(Arrays.asList(getDeclaredClasses(true))); + Class superClass = getSuperclass(); + if (superClass != null) + list.addAll(Arrays.asList(superClass.internalGetClasses())); + return (Class[])list.toArray(new Class[list.size()]); + } + + /** + * Get the ClassLoader that loaded this class. If the class was loaded + * by the bootstrap classloader, this method will return null. + * If there is a security manager, and the caller's class loader is not + * an ancestor of the requested one, a security check of + * <code>RuntimePermission("getClassLoader")</code> + * must first succeed. Primitive types and void return null. + * + * @return the ClassLoader that loaded this class + * @throws SecurityException if the security check fails + * @see ClassLoader + * @see RuntimePermission + */ + public ClassLoader getClassLoader() + { + if (isPrimitive()) + return null; + + ClassLoader loader = VMClass.getClassLoader(this); + // Check if we may get the classloader + SecurityManager sm = SecurityManager.current; + if (sm != null) + { + // Get the calling classloader + ClassLoader cl = VMStackWalker.getCallingClassLoader(); + if (cl != null && !cl.isAncestorOf(loader)) + sm.checkPermission(new RuntimePermission("getClassLoader")); + } + return loader; + } + + /** + * If this is an array, get the Class representing the type of array. + * Examples: "[[Ljava.lang.String;" would return "[Ljava.lang.String;", and + * calling getComponentType on that would give "java.lang.String". If + * this is not an array, returns null. + * + * @return the array type of this class, or null + * @see Array + * @since 1.1 + */ + public Class getComponentType() + { + return VMClass.getComponentType (this); + } + + /** + * Get a public constructor declared in this class. If the constructor takes + * no argument, an array of zero elements and null are equivalent for the + * types argument. A security check may be performed, with + * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @param types the type of each parameter + * @return the constructor + * @throws NoSuchMethodException if the constructor does not exist + * @throws SecurityException if the security check fails + * @see #getConstructors() + * @since 1.1 + */ + public Constructor getConstructor(Class[] types) throws NoSuchMethodException + { + memberAccessCheck(Member.PUBLIC); + Constructor[] constructors = getDeclaredConstructors(true); + for (int i = 0; i < constructors.length; i++) + { + Constructor constructor = constructors[i]; + if (matchParameters(types, constructor.getParameterTypes())) + return constructor; + } + throw new NoSuchMethodException(); + } + + /** + * Get all the public constructors of this class. This returns an array of + * length 0 if there are no constructors, including for primitive types, + * arrays, and interfaces. It does, however, include the default + * constructor if one was supplied by the compiler. A security check may + * be performed, with <code>checkMemberAccess(this, Member.PUBLIC)</code> + * as well as <code>checkPackageAccess</code> both having to succeed. + * + * @return all public constructors in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Constructor[] getConstructors() + { + memberAccessCheck(Member.PUBLIC); + return getDeclaredConstructors(true); + } + + /** + * Get a constructor declared in this class. If the constructor takes no + * argument, an array of zero elements and null are equivalent for the + * types argument. A security check may be performed, with + * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @param types the type of each parameter + * @return the constructor + * @throws NoSuchMethodException if the constructor does not exist + * @throws SecurityException if the security check fails + * @see #getDeclaredConstructors() + * @since 1.1 + */ + public Constructor getDeclaredConstructor(Class[] types) + throws NoSuchMethodException + { + memberAccessCheck(Member.DECLARED); + Constructor[] constructors = getDeclaredConstructors(false); + for (int i = 0; i < constructors.length; i++) + { + Constructor constructor = constructors[i]; + if (matchParameters(types, constructor.getParameterTypes())) + return constructor; + } + throw new NoSuchMethodException(); + } + + /** + * Get all the declared member classes and interfaces in this class, but + * not those inherited from superclasses. This returns an array of length + * 0 if there are no member classes, including for primitive types. A + * security check may be performed, with + * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @return all declared member classes in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Class[] getDeclaredClasses() + { + memberAccessCheck(Member.DECLARED); + return getDeclaredClasses(false); + } + + Class[] getDeclaredClasses (boolean publicOnly) + { + return VMClass.getDeclaredClasses (this, publicOnly); + } + + /** + * Get all the declared constructors of this class. This returns an array of + * length 0 if there are no constructors, including for primitive types, + * arrays, and interfaces. It does, however, include the default + * constructor if one was supplied by the compiler. A security check may + * be performed, with <code>checkMemberAccess(this, Member.DECLARED)</code> + * as well as <code>checkPackageAccess</code> both having to succeed. + * + * @return all constructors in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Constructor[] getDeclaredConstructors() + { + memberAccessCheck(Member.DECLARED); + return getDeclaredConstructors(false); + } + + Constructor[] getDeclaredConstructors (boolean publicOnly) + { + return VMClass.getDeclaredConstructors (this, publicOnly); + } + + /** + * Get a field declared in this class, where name is its simple name. The + * implicit length field of arrays is not available. A security check may + * be performed, with <code>checkMemberAccess(this, Member.DECLARED)</code> + * as well as <code>checkPackageAccess</code> both having to succeed. + * + * @param name the name of the field + * @return the field + * @throws NoSuchFieldException if the field does not exist + * @throws SecurityException if the security check fails + * @see #getDeclaredFields() + * @since 1.1 + */ + public Field getDeclaredField(String name) throws NoSuchFieldException + { + memberAccessCheck(Member.DECLARED); + Field[] fields = getDeclaredFields(false); + for (int i = 0; i < fields.length; i++) + { + if (fields[i].getName().equals(name)) + return fields[i]; + } + throw new NoSuchFieldException(); + } + + /** + * Get all the declared fields in this class, but not those inherited from + * superclasses. This returns an array of length 0 if there are no fields, + * including for primitive types. This does not return the implicit length + * field of arrays. A security check may be performed, with + * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @return all declared fields in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Field[] getDeclaredFields() + { + memberAccessCheck(Member.DECLARED); + return getDeclaredFields(false); + } + + Field[] getDeclaredFields (boolean publicOnly) + { + return VMClass.getDeclaredFields (this, publicOnly); + } + + /** + * Get a method declared in this class, where name is its simple name. The + * implicit methods of Object are not available from arrays or interfaces. + * Constructors (named "<init>" in the class file) and class initializers + * (name "<clinit>") are not available. The Virtual Machine allows + * multiple methods with the same signature but differing return types; in + * such a case the most specific return types are favored, then the final + * choice is arbitrary. If the method takes no argument, an array of zero + * elements and null are equivalent for the types argument. A security + * check may be performed, with + * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @param methodName the name of the method + * @param types the type of each parameter + * @return the method + * @throws NoSuchMethodException if the method does not exist + * @throws SecurityException if the security check fails + * @see #getDeclaredMethods() + * @since 1.1 + */ + public Method getDeclaredMethod(String methodName, Class[] types) + throws NoSuchMethodException + { + memberAccessCheck(Member.DECLARED); + Method match = matchMethod(getDeclaredMethods(false), methodName, types); + if (match == null) + throw new NoSuchMethodException(methodName); + return match; + } + + /** + * Get all the declared methods in this class, but not those inherited from + * superclasses. This returns an array of length 0 if there are no methods, + * including for primitive types. This does include the implicit methods of + * arrays and interfaces which mirror methods of Object, nor does it + * include constructors or the class initialization methods. The Virtual + * Machine allows multiple methods with the same signature but differing + * return types; all such methods are in the returned array. A security + * check may be performed, with + * <code>checkMemberAccess(this, Member.DECLARED)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @return all declared methods in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Method[] getDeclaredMethods() + { + memberAccessCheck(Member.DECLARED); + return getDeclaredMethods(false); + } + + Method[] getDeclaredMethods (boolean publicOnly) + { + return VMClass.getDeclaredMethods (this, publicOnly); + } + + /** + * If this is a nested or inner class, return the class that declared it. + * If not, return null. + * + * @return the declaring class of this class + * @since 1.1 + */ + public Class getDeclaringClass() + { + return VMClass.getDeclaringClass (this); + } + + /** + * Get a public field declared or inherited in this class, where name is + * its simple name. If the class contains multiple accessible fields by + * that name, an arbitrary one is returned. The implicit length field of + * arrays is not available. A security check may be performed, with + * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @param fieldName the name of the field + * @return the field + * @throws NoSuchFieldException if the field does not exist + * @throws SecurityException if the security check fails + * @see #getFields() + * @since 1.1 + */ + public Field getField(String fieldName) + throws NoSuchFieldException + { + memberAccessCheck(Member.PUBLIC); + Field field = internalGetField(fieldName); + if (field == null) + throw new NoSuchFieldException(fieldName); + return field; + } + + /** + * Get all the public fields declared in this class or inherited from + * superclasses. This returns an array of length 0 if there are no fields, + * including for primitive types. This does not return the implicit length + * field of arrays. A security check may be performed, with + * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @return all public fields in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Field[] getFields() + { + memberAccessCheck(Member.PUBLIC); + return internalGetFields(); + } + + /** + * Like <code>getFields()</code> but without the security checks. + */ + private Field[] internalGetFields() + { + HashSet set = new HashSet(); + set.addAll(Arrays.asList(getDeclaredFields(true))); + Class[] interfaces = getInterfaces(); + for (int i = 0; i < interfaces.length; i++) + set.addAll(Arrays.asList(interfaces[i].internalGetFields())); + Class superClass = getSuperclass(); + if (superClass != null) + set.addAll(Arrays.asList(superClass.internalGetFields())); + return (Field[])set.toArray(new Field[set.size()]); + } + + /** + * Returns the <code>Package</code> in which this class is defined + * Returns null when this information is not available from the + * classloader of this class or when the classloader of this class + * is null. + * + * @return the package for this class, if it is available + * @since 1.2 + */ + public Package getPackage() + { + ClassLoader cl = getClassLoader(); + if (cl != null) + return cl.getPackage(getPackagePortion(getName())); + return null; + } + + /** + * Get the interfaces this class <em>directly</em> implements, in the + * order that they were declared. This returns an empty array, not null, + * for Object, primitives, void, and classes or interfaces with no direct + * superinterface. Array types return Cloneable and Serializable. + * + * @return the interfaces this class directly implements + */ + public Class[] getInterfaces() + { + return VMClass.getInterfaces (this); + } + + private static final class MethodKey + { + private String name; + private Class[] params; + private Class returnType; + private int hash; + + MethodKey(Method m) + { + name = m.getName(); + params = m.getParameterTypes(); + returnType = m.getReturnType(); + hash = name.hashCode() ^ returnType.hashCode(); + for(int i = 0; i < params.length; i++) + { + hash ^= params[i].hashCode(); + } + } + + public boolean equals(Object o) + { + if(o instanceof MethodKey) + { + MethodKey m = (MethodKey)o; + if(m.name.equals(name) && m.params.length == params.length && m.returnType == returnType) + { + for(int i = 0; i < params.length; i++) + { + if(m.params[i] != params[i]) + { + return false; + } + } + return true; + } + } + return false; + } + + public int hashCode() + { + return hash; + } + } + + /** + * Get a public method declared or inherited in this class, where name is + * its simple name. The implicit methods of Object are not available from + * interfaces. Constructors (named "<init>" in the class file) and class + * initializers (name "<clinit>") are not available. The Virtual + * Machine allows multiple methods with the same signature but differing + * return types, and the class can inherit multiple methods of the same + * return type; in such a case the most specific return types are favored, + * then the final choice is arbitrary. If the method takes no argument, an + * array of zero elements and null are equivalent for the types argument. + * A security check may be performed, with + * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @param methodName the name of the method + * @param types the type of each parameter + * @return the method + * @throws NoSuchMethodException if the method does not exist + * @throws SecurityException if the security check fails + * @see #getMethods() + * @since 1.1 + */ + public Method getMethod(String methodName, Class[] types) + throws NoSuchMethodException + { + memberAccessCheck(Member.PUBLIC); + Method method = internalGetMethod(methodName, types); + if (method == null) + throw new NoSuchMethodException(methodName); + return method; + } + + /** + * Like <code>getMethod(String,Class[])</code> but without the security + * checks and returns null instead of throwing NoSuchMethodException. + */ + private Method internalGetMethod(String methodName, Class[] args) + { + Method match = matchMethod(getDeclaredMethods(true), methodName, args); + if (match != null) + return match; + Class superClass = getSuperclass(); + if (superClass != null) + { + match = superClass.internalGetMethod(methodName, args); + if(match != null) + return match; + } + Class[] interfaces = getInterfaces(); + for (int i = 0; i < interfaces.length; i++) + { + match = interfaces[i].internalGetMethod(methodName, args); + if (match != null) + return match; + } + return null; + } + + /** + * Find the best matching method in <code>list</code> according to + * the definition of ``best matching'' used by <code>getMethod()</code> + * + * <p> + * Returns the method if any, otherwise <code>null</code>. + * + * @param list List of methods to search + * @param name Name of method + * @param args Method parameter types + * @see #getMethod() + */ + private static Method matchMethod(Method[] list, String name, Class[] args) + { + Method match = null; + for (int i = 0; i < list.length; i++) + { + Method method = list[i]; + if (!method.getName().equals(name)) + continue; + if (!matchParameters(args, method.getParameterTypes())) + continue; + if (match == null + || match.getReturnType().isAssignableFrom(method.getReturnType())) + match = method; + } + return match; + } + + /** + * Check for an exact match between parameter type lists. + * Either list may be <code>null</code> to mean a list of + * length zero. + */ + private static boolean matchParameters(Class[] types1, Class[] types2) + { + if (types1 == null) + return types2 == null || types2.length == 0; + if (types2 == null) + return types1 == null || types1.length == 0; + if (types1.length != types2.length) + return false; + for (int i = 0; i < types1.length; i++) + { + if (types1[i] != types2[i]) + return false; + } + return true; + } + + /** + * Get all the public methods declared in this class or inherited from + * superclasses. This returns an array of length 0 if there are no methods, + * including for primitive types. This does not include the implicit + * methods of interfaces which mirror methods of Object, nor does it + * include constructors or the class initialization methods. The Virtual + * Machine allows multiple methods with the same signature but differing + * return types; all such methods are in the returned array. A security + * check may be performed, with + * <code>checkMemberAccess(this, Member.PUBLIC)</code> as well as + * <code>checkPackageAccess</code> both having to succeed. + * + * @return all public methods in this class + * @throws SecurityException if the security check fails + * @since 1.1 + */ + public Method[] getMethods() + { + memberAccessCheck(Member.PUBLIC); + // NOTE the API docs claim that no methods are returned for arrays, + // but Sun's implementation *does* return the public methods of Object + // (as would be expected), so we follow their implementation instead + // of their documentation. + return internalGetMethods(); + } + + /** + * Like <code>getMethods()</code> but without the security checks. + */ + private Method[] internalGetMethods() + { + HashMap map = new HashMap(); + Method[] methods; + Class[] interfaces = getInterfaces(); + for(int i = 0; i < interfaces.length; i++) + { + methods = interfaces[i].internalGetMethods(); + for(int j = 0; j < methods.length; j++) + { + map.put(new MethodKey(methods[j]), methods[j]); + } + } + Class superClass = getSuperclass(); + if(superClass != null) + { + methods = superClass.internalGetMethods(); + for(int i = 0; i < methods.length; i++) + { + map.put(new MethodKey(methods[i]), methods[i]); + } + } + methods = getDeclaredMethods(true); + for(int i = 0; i < methods.length; i++) + { + map.put(new MethodKey(methods[i]), methods[i]); + } + return (Method[])map.values().toArray(new Method[map.size()]); + } + + /** + * Get the modifiers of this class. These can be decoded using Modifier, + * and is limited to one of public, protected, or private, and any of + * final, static, abstract, or interface. An array class has the same + * public, protected, or private modifier as its component type, and is + * marked final but not an interface. Primitive types and void are marked + * public and final, but not an interface. + * + * @return the modifiers of this class + * @see Modifer + * @since 1.1 + */ + public int getModifiers() + { + return VMClass.getModifiers (this, false); + } + + /** + * Get the name of this class, separated by dots for package separators. + * If the class represents a primitive type, or void, then the + * name of the type as it appears in the Java programming language + * is returned. For instance, <code>Byte.TYPE.getName()</code> + * returns "byte". + * + * Arrays are specially encoded as shown on this table. + * <pre> + * array type [<em>element type</em> + * (note that the element type is encoded per + * this table) + * boolean Z + * byte B + * char C + * short S + * int I + * long J + * float F + * double D + * void V + * class or interface, alone: <dotted name> + * class or interface, as element type: L<dotted name>; + * </pre> + * + * @return the name of this class + */ + public String getName() + { + return VMClass.getName (this); + } + + /** + * Get a resource URL using this class's package using the + * getClassLoader().getResource() method. If this class was loaded using + * the system classloader, ClassLoader.getSystemResource() is used instead. + * + * <p>If the name you supply is absolute (it starts with a <code>/</code>), + * then the leading <code>/</code> is removed and it is passed on to + * getResource(). If it is relative, the package name is prepended, and + * <code>.</code>'s are replaced with <code>/</code>. + * + * <p>The URL returned is system- and classloader-dependent, and could + * change across implementations. + * + * @param resourceName the name of the resource, generally a path + * @return the URL to the resource + * @throws NullPointerException if name is null + * @since 1.1 + */ + public URL getResource(String resourceName) + { + String name = resourcePath(resourceName); + ClassLoader loader = getClassLoader(); + if (loader == null) + return ClassLoader.getSystemResource(name); + return loader.getResource(name); + } + + /** + * Get a resource using this class's package using the + * getClassLoader().getResourceAsStream() method. If this class was loaded + * using the system classloader, ClassLoader.getSystemResource() is used + * instead. + * + * <p>If the name you supply is absolute (it starts with a <code>/</code>), + * then the leading <code>/</code> is removed and it is passed on to + * getResource(). If it is relative, the package name is prepended, and + * <code>.</code>'s are replaced with <code>/</code>. + * + * <p>The URL returned is system- and classloader-dependent, and could + * change across implementations. + * + * @param resourceName the name of the resource, generally a path + * @return an InputStream with the contents of the resource in it, or null + * @throws NullPointerException if name is null + * @since 1.1 + */ + public InputStream getResourceAsStream(String resourceName) + { + String name = resourcePath(resourceName); + ClassLoader loader = getClassLoader(); + if (loader == null) + return ClassLoader.getSystemResourceAsStream(name); + return loader.getResourceAsStream(name); + } + + private String resourcePath(String resourceName) + { + if (resourceName.length() > 0) + { + if (resourceName.charAt(0) != '/') + { + String pkg = getPackagePortion(getName()); + if (pkg.length() > 0) + resourceName = pkg.replace('.','/') + '/' + resourceName; + } + else + { + resourceName = resourceName.substring(1); + } + } + return resourceName; + } + + /** + * Get the signers of this class. This returns null if there are no signers, + * such as for primitive types or void. + * + * @return the signers of this class + * @since 1.1 + */ + public Object[] getSigners() + { + return signers == null ? null : (Object[]) signers.clone (); + } + + /** + * Set the signers of this class. + * + * @param signers the signers of this class + */ + void setSigners(Object[] signers) + { + this.signers = signers; + } + + /** + * Get the direct superclass of this class. If this is an interface, + * Object, a primitive type, or void, it will return null. If this is an + * array type, it will return Object. + * + * @return the direct superclass of this class + */ + public Class getSuperclass() + { + return VMClass.getSuperclass (this); + } + + /** + * Return whether this class is an array type. + * + * @return whether this class is an array type + * @since 1.1 + */ + public boolean isArray() + { + return VMClass.isArray (this); + } + + /** + * Discover whether an instance of the Class parameter would be an + * instance of this Class as well. Think of doing + * <code>isInstance(c.newInstance())</code> or even + * <code>c.newInstance() instanceof (this class)</code>. While this + * checks widening conversions for objects, it must be exact for primitive + * types. + * + * @param c the class to check + * @return whether an instance of c would be an instance of this class + * as well + * @throws NullPointerException if c is null + * @since 1.1 + */ + public boolean isAssignableFrom(Class c) + { + return VMClass.isAssignableFrom (this, c); + } + + /** + * Discover whether an Object is an instance of this Class. Think of it + * as almost like <code>o instanceof (this class)</code>. + * + * @param o the Object to check + * @return whether o is an instance of this class + * @since 1.1 + */ + public boolean isInstance(Object o) + { + return VMClass.isInstance (this, o); + } + + /** + * Check whether this class is an interface or not. Array types are not + * interfaces. + * + * @return whether this class is an interface or not + */ + public boolean isInterface() + { + return VMClass.isInterface (this); + } + + /** + * Return whether this class is a primitive type. A primitive type class + * is a class representing a kind of "placeholder" for the various + * primitive types, or void. You can access the various primitive type + * classes through java.lang.Boolean.TYPE, java.lang.Integer.TYPE, etc., + * or through boolean.class, int.class, etc. + * + * @return whether this class is a primitive type + * @see Boolean#TYPE + * @see Byte#TYPE + * @see Character#TYPE + * @see Short#TYPE + * @see Integer#TYPE + * @see Long#TYPE + * @see Float#TYPE + * @see Double#TYPE + * @see Void#TYPE + * @since 1.1 + */ + public boolean isPrimitive() + { + return VMClass.isPrimitive (this); + } + + /** + * Get a new instance of this class by calling the no-argument constructor. + * The class is initialized if it has not been already. A security check + * may be performed, with <code>checkMemberAccess(this, Member.PUBLIC)</code> + * as well as <code>checkPackageAccess</code> both having to succeed. + * + * @return a new instance of this class + * @throws InstantiationException if there is not a no-arg constructor + * for this class, including interfaces, abstract classes, arrays, + * primitive types, and void; or if an exception occurred during + * the constructor + * @throws IllegalAccessException if you are not allowed to access the + * no-arg constructor because of scoping reasons + * @throws SecurityException if the security check fails + * @throws ExceptionInInitializerError if class initialization caused by + * this call fails with an exception + */ + public Object newInstance() + throws InstantiationException, IllegalAccessException + { + memberAccessCheck(Member.PUBLIC); + Constructor constructor; + synchronized(this) + { + constructor = this.constructor; + } + if (constructor == null) + { + Constructor[] constructors = getDeclaredConstructors(false); + for (int i = 0; i < constructors.length; i++) + { + if (constructors[i].getParameterTypes().length == 0) + { + constructor = constructors[i]; + break; + } + } + if (constructor == null) + throw new InstantiationException(getName()); + if (!Modifier.isPublic(constructor.getModifiers()) + || !Modifier.isPublic(VMClass.getModifiers(this, true))) + { + final Constructor finalConstructor = constructor; + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + finalConstructor.setAccessible(true); + return null; + } + }); + } + synchronized(this) + { + if (this.constructor == null) + this.constructor = constructor; + } + } + int modifiers = constructor.getModifiers(); + if (!Modifier.isPublic(modifiers) + || !Modifier.isPublic(VMClass.getModifiers(this, true))) + { + Class caller = VMStackWalker.getCallingClass(); + if (caller != null && + caller != this && + (Modifier.isPrivate(modifiers) + || getClassLoader() != caller.getClassLoader() + || !getPackagePortion(getName()) + .equals(getPackagePortion(caller.getName())))) + throw new IllegalAccessException(getName() + + " has an inaccessible constructor"); + } + try + { + return constructor.newInstance(null); + } + catch (InvocationTargetException e) + { + VMClass.throwException(e.getTargetException()); + throw (InternalError) new InternalError + ("VMClass.throwException returned").initCause(e); + } + } + + /** + * Returns the protection domain of this class. If the classloader did not + * record the protection domain when creating this class the unknown + * protection domain is returned which has a <code>null</code> code source + * and all permissions. A security check may be performed, with + * <code>RuntimePermission("getProtectionDomain")</code>. + * + * @return the protection domain + * @throws SecurityException if the security manager exists and the caller + * does not have <code>RuntimePermission("getProtectionDomain")</code>. + * @see RuntimePermission + * @since 1.2 + */ + public ProtectionDomain getProtectionDomain() + { + SecurityManager sm = SecurityManager.current; + if (sm != null) + sm.checkPermission(new RuntimePermission("getProtectionDomain")); + + return pd == null ? StaticData.unknownProtectionDomain : pd; + } + + /** + * Return the human-readable form of this Object. For an object, this + * is either "interface " or "class " followed by <code>getName()</code>, + * for primitive types and void it is just <code>getName()</code>. + * + * @return the human-readable form of this Object + */ + public String toString() + { + if (isPrimitive()) + return getName(); + return (isInterface() ? "interface " : "class ") + getName(); + } + + /** + * Returns the desired assertion status of this class, if it were to be + * initialized at this moment. The class assertion status, if set, is + * returned; the backup is the default package status; then if there is + * a class loader, that default is returned; and finally the system default + * is returned. This method seldom needs calling in user code, but exists + * for compilers to implement the assert statement. Note that there is no + * guarantee that the result of this method matches the class's actual + * assertion status. + * + * @return the desired assertion status + * @see ClassLoader#setClassAssertionStatus(String, boolean) + * @see ClassLoader#setPackageAssertionStatus(String, boolean) + * @see ClassLoader#setDefaultAssertionStatus(boolean) + * @since 1.4 + */ + public boolean desiredAssertionStatus() + { + ClassLoader c = getClassLoader(); + Object status; + if (c == null) + return VMClassLoader.defaultAssertionStatus(); + if (c.classAssertionStatus != null) + synchronized (c) + { + status = c.classAssertionStatus.get(getName()); + if (status != null) + return status.equals(Boolean.TRUE); + } + else + { + status = ClassLoader.StaticData. + systemClassAssertionStatus.get(getName()); + if (status != null) + return status.equals(Boolean.TRUE); + } + if (c.packageAssertionStatus != null) + synchronized (c) + { + String name = getPackagePortion(getName()); + if ("".equals(name)) + status = c.packageAssertionStatus.get(null); + else + do + { + status = c.packageAssertionStatus.get(name); + name = getPackagePortion(name); + } + while (! "".equals(name) && status == null); + if (status != null) + return status.equals(Boolean.TRUE); + } + else + { + String name = getPackagePortion(getName()); + if ("".equals(name)) + status = ClassLoader.StaticData. + systemPackageAssertionStatus.get(null); + else + do + { + status = ClassLoader.StaticData. + systemPackageAssertionStatus.get(name); + name = getPackagePortion(name); + } + while (! "".equals(name) && status == null); + if (status != null) + return status.equals(Boolean.TRUE); + } + return c.defaultAssertionStatus; + } + + /** + * Like <code>getField(String)</code> but without the security checks and returns null + * instead of throwing NoSuchFieldException. + */ + private Field internalGetField(String name) + { + Field[] fields = getDeclaredFields(true); + for (int i = 0; i < fields.length; i++) + { + Field field = fields[i]; + if (field.getName().equals(name)) + return field; + } + Class[] interfaces = getInterfaces(); + for (int i = 0; i < interfaces.length; i++) + { + Field field = interfaces[i].internalGetField(name); + if(field != null) + return field; + } + Class superClass = getSuperclass(); + if (superClass != null) + return superClass.internalGetField(name); + return null; + } + + /** + * Strip the last portion of the name (after the last dot). + * + * @param name the name to get package of + * @return the package name, or "" if no package + */ + private static String getPackagePortion(String name) + { + int lastInd = name.lastIndexOf('.'); + if (lastInd == -1) + return ""; + return name.substring(0, lastInd); + } + + /** + * Perform security checks common to all of the methods that + * get members of this Class. + */ + private void memberAccessCheck(int which) + { + SecurityManager sm = SecurityManager.current; + if (sm != null) + { + sm.checkMemberAccess(this, which); + Package pkg = getPackage(); + if (pkg != null) + sm.checkPackageAccess(pkg.getName()); + } + } +} diff --git a/libjava/classpath/java/lang/ClassCastException.java b/libjava/classpath/java/lang/ClassCastException.java new file mode 100644 index 0000000..c490f42 --- /dev/null +++ b/libjava/classpath/java/lang/ClassCastException.java @@ -0,0 +1,76 @@ +/* ClassCastException.java -- exception thrown on bad cast + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when an attempt is made to cast an object which is not of the + * appropriate runtime type. For example:<br> + * <pre> + * Object o = new Vector(); + * String s = (String) o; + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class ClassCastException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -9223365651070458532L; + + /** + * Create an exception without a message. + */ + public ClassCastException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public ClassCastException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/ClassCircularityError.java b/libjava/classpath/java/lang/ClassCircularityError.java new file mode 100644 index 0000000..ecdfb7a --- /dev/null +++ b/libjava/classpath/java/lang/ClassCircularityError.java @@ -0,0 +1,73 @@ +/* ClassCircularityError.java -- thrown when linking circular classes + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>ClassCircularityError</code> is thrown when a circular dependency + * has been detected while initializing a class. This signals binary + * incompatible versions of class files, as the compiler normally catches this. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class ClassCircularityError extends LinkageError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 1054362542914539689L; + + /** + * Create an error without a message. + */ + public ClassCircularityError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public ClassCircularityError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/ClassFormatError.java b/libjava/classpath/java/lang/ClassFormatError.java new file mode 100644 index 0000000..7f90f5c --- /dev/null +++ b/libjava/classpath/java/lang/ClassFormatError.java @@ -0,0 +1,72 @@ +/* ClassFormatError.java -- thrown if a class file is invalid + Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>ClassFormatError</code> is thrown when a Java Virtual Machine + * unable to read a class file because the file is corrupted or cannot be + * interpreted as a class file. + * + * @author Brian Jones + * @status updated to 1.4 + */ +public class ClassFormatError extends LinkageError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -8420114879011949195L; + + /** + * Create an error without a message. + */ + public ClassFormatError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public ClassFormatError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/ClassLoader.java b/libjava/classpath/java/lang/ClassLoader.java new file mode 100644 index 0000000..b644511 --- /dev/null +++ b/libjava/classpath/java/lang/ClassLoader.java @@ -0,0 +1,1116 @@ +/* ClassLoader.java -- responsible for loading classes into the VM + Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import gnu.classpath.SystemProperties; +import gnu.classpath.VMStackWalker; +import gnu.java.util.DoubleEnumeration; +import gnu.java.util.EmptyEnumeration; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.CodeSource; +import java.security.PermissionCollection; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * The ClassLoader is a way of customizing the way Java gets its classes + * and loads them into memory. The verifier and other standard Java things + * still run, but the ClassLoader is allowed great flexibility in determining + * where to get the classfiles and when to load and resolve them. For that + * matter, a custom ClassLoader can perform on-the-fly code generation or + * modification! + * + * <p>Every classloader has a parent classloader that is consulted before + * the 'child' classloader when classes or resources should be loaded. + * This is done to make sure that classes can be loaded from an hierarchy of + * multiple classloaders and classloaders do not accidentially redefine + * already loaded classes by classloaders higher in the hierarchy. + * + * <p>The grandparent of all classloaders is the bootstrap classloader, which + * loads all the standard system classes as implemented by GNU Classpath. The + * other special classloader is the system classloader (also called + * application classloader) that loads all classes from the CLASSPATH + * (<code>java.class.path</code> system property). The system classloader + * is responsible for finding the application classes from the classpath, + * and delegates all requests for the standard library classes to its parent + * the bootstrap classloader. Most programs will load all their classes + * through the system classloaders. + * + * <p>The bootstrap classloader in GNU Classpath is implemented as a couple of + * static (native) methods on the package private class + * <code>java.lang.VMClassLoader</code>, the system classloader is an + * anonymous inner class of ClassLoader and a subclass of + * <code>java.net.URLClassLoader</code>. + * + * <p>Users of a <code>ClassLoader</code> will normally just use the methods + * <ul> + * <li> <code>loadClass()</code> to load a class.</li> + * <li> <code>getResource()</code> or <code>getResourceAsStream()</code> + * to access a resource.</li> + * <li> <code>getResources()</code> to get an Enumeration of URLs to all + * the resources provided by the classloader and its parents with the + * same name.</li> + * </ul> + * + * <p>Subclasses should implement the methods + * <ul> + * <li> <code>findClass()</code> which is called by <code>loadClass()</code> + * when the parent classloader cannot provide a named class.</li> + * <li> <code>findResource()</code> which is called by + * <code>getResource()</code> when the parent classloader cannot provide + * a named resource.</li> + * <li> <code>findResources()</code> which is called by + * <code>getResource()</code> to combine all the resources with the + * same name from the classloader and its parents.</li> + * <li> <code>findLibrary()</code> which is called by + * <code>Runtime.loadLibrary()</code> when a class defined by the + * classloader wants to load a native library.</li> + * </ul> + * + * @author John Keiser + * @author Mark Wielaard + * @author Eric Blake (ebb9@email.byu.edu) + * @see Class + * @since 1.0 + * @status still missing 1.4 functionality + */ +public abstract class ClassLoader +{ + /** + * All classes loaded by this classloader. VM's may choose to implement + * this cache natively; but it is here available for use if necessary. It + * is not private in order to allow native code (and trusted subclasses) + * access to this field. + */ + final HashMap loadedClasses = new HashMap(); + + /** + * All packages defined by this classloader. It is not private in order to + * allow native code (and trusted subclasses) access to this field. + */ + final HashMap definedPackages = new HashMap(); + + /** + * The classloader that is consulted before this classloader. + * If null then the parent is the bootstrap classloader. + */ + private final ClassLoader parent; + + /** + * This is true if this classloader was successfully initialized. + * This flag is needed to avoid a class loader attack: even if the + * security manager rejects an attempt to create a class loader, the + * malicious class could have a finalize method which proceeds to + * define classes. + */ + private final boolean initialized; + + static class StaticData + { + /** + * The System Class Loader (a.k.a. Application Class Loader). The one + * returned by ClassLoader.getSystemClassLoader. + */ + static final ClassLoader systemClassLoader = + VMClassLoader.getSystemClassLoader(); + static + { + // Find out if we have to install a default security manager. Note that + // this is done here because we potentially need the system class loader + // to load the security manager and note also that we don't need the + // security manager until the system class loader is created. + // If the runtime chooses to use a class loader that doesn't have the + // system class loader as its parent, it is responsible for setting + // up a security manager before doing so. + String secman = SystemProperties.getProperty("java.security.manager"); + if (secman != null && SecurityManager.current == null) + { + if (secman.equals("") || secman.equals("default")) + { + SecurityManager.current = new SecurityManager(); + } + else + { + try + { + Class cl = Class.forName(secman, false, StaticData.systemClassLoader); + SecurityManager.current = (SecurityManager)cl.newInstance(); + } + catch (Exception x) + { + throw (InternalError) + new InternalError("Unable to create SecurityManager") + .initCause(x); + } + } + } + } + + /** + * The default protection domain, used when defining a class with a null + * parameter for the domain. + */ + static final ProtectionDomain defaultProtectionDomain; + static + { + CodeSource cs = new CodeSource(null, null); + PermissionCollection perm = Policy.getPolicy().getPermissions(cs); + defaultProtectionDomain = new ProtectionDomain(cs, perm); + } + /** + * The command-line state of the package assertion status overrides. This + * map is never modified, so it does not need to be synchronized. + */ + // Package visible for use by Class. + static final Map systemPackageAssertionStatus + = VMClassLoader.packageAssertionStatus(); + /** + * The command-line state of the class assertion status overrides. This + * map is never modified, so it does not need to be synchronized. + */ + // Package visible for use by Class. + static final Map systemClassAssertionStatus + = VMClassLoader.classAssertionStatus(); + } + + /** + * The desired assertion status of classes loaded by this loader, if not + * overridden by package or class instructions. + */ + // Package visible for use by Class. + boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus(); + + /** + * The map of package assertion status overrides, or null if no package + * overrides have been specified yet. The values of the map should be + * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented + * by the null key. This map must be synchronized on this instance. + */ + // Package visible for use by Class. + Map packageAssertionStatus; + + /** + * The map of class assertion status overrides, or null if no class + * overrides have been specified yet. The values of the map should be + * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this + * instance. + */ + // Package visible for use by Class. + Map classAssertionStatus; + + /** + * VM private data. + */ + transient Object vmdata; + + /** + * Create a new ClassLoader with as parent the system classloader. There + * may be a security check for <code>checkCreateClassLoader</code>. + * + * @throws SecurityException if the security check fails + */ + protected ClassLoader() throws SecurityException + { + this(StaticData.systemClassLoader); + } + + /** + * Create a new ClassLoader with the specified parent. The parent will + * be consulted when a class or resource is requested through + * <code>loadClass()</code> or <code>getResource()</code>. Only when the + * parent classloader cannot provide the requested class or resource the + * <code>findClass()</code> or <code>findResource()</code> method + * of this classloader will be called. There may be a security check for + * <code>checkCreateClassLoader</code>. + * + * @param parent the classloader's parent, or null for the bootstrap + * classloader + * @throws SecurityException if the security check fails + * @since 1.2 + */ + protected ClassLoader(ClassLoader parent) + { + // May we create a new classloader? + SecurityManager sm = SecurityManager.current; + if (sm != null) + sm.checkCreateClassLoader(); + this.parent = parent; + this.initialized = true; + } + + /** + * Load a class using this ClassLoader or its parent, without resolving + * it. Calls <code>loadClass(name, false)</code>. + * + * <p>Subclasses should not override this method but should override + * <code>findClass()</code> which is called by this method.</p> + * + * @param name the name of the class relative to this ClassLoader + * @return the loaded class + * @throws ClassNotFoundException if the class cannot be found + */ + public Class loadClass(String name) throws ClassNotFoundException + { + return loadClass(name, false); + } + + /** + * Load a class using this ClassLoader or its parent, possibly resolving + * it as well using <code>resolveClass()</code>. It first tries to find + * out if the class has already been loaded through this classloader by + * calling <code>findLoadedClass()</code>. Then it calls + * <code>loadClass()</code> on the parent classloader (or when there is + * no parent it uses the VM bootclassloader). If the class is still + * not loaded it tries to create a new class by calling + * <code>findClass()</code>. Finally when <code>resolve</code> is + * <code>true</code> it also calls <code>resolveClass()</code> on the + * newly loaded class. + * + * <p>Subclasses should not override this method but should override + * <code>findClass()</code> which is called by this method.</p> + * + * @param name the fully qualified name of the class to load + * @param resolve whether or not to resolve the class + * @return the loaded class + * @throws ClassNotFoundException if the class cannot be found + */ + protected synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + // Have we already loaded this class? + Class c = findLoadedClass(name); + if (c == null) + { + // Can the class be loaded by a parent? + try + { + if (parent == null) + { + c = VMClassLoader.loadClass(name, resolve); + if (c != null) + return c; + } + else + { + return parent.loadClass(name, resolve); + } + } + catch (ClassNotFoundException e) + { + } + // Still not found, we have to do it ourself. + c = findClass(name); + } + if (resolve) + resolveClass(c); + return c; + } + + /** + * Called for every class name that is needed but has not yet been + * defined by this classloader or one of its parents. It is called by + * <code>loadClass()</code> after both <code>findLoadedClass()</code> and + * <code>parent.loadClass()</code> couldn't provide the requested class. + * + * <p>The default implementation throws a + * <code>ClassNotFoundException</code>. Subclasses should override this + * method. An implementation of this method in a subclass should get the + * class bytes of the class (if it can find them), if the package of the + * requested class doesn't exist it should define the package and finally + * it should call define the actual class. It does not have to resolve the + * class. It should look something like the following:<br> + * + * <pre> + * // Get the bytes that describe the requested class + * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name); + * // Get the package name + * int lastDot = name.lastIndexOf('.'); + * if (lastDot != -1) + * { + * String packageName = name.substring(0, lastDot); + * // Look if the package already exists + * if (getPackage(packageName) == null) + * { + * // define the package + * definePackage(packageName, ...); + * } + * } + * // Define and return the class + * return defineClass(name, classBytes, 0, classBytes.length); + * </pre> + * + * <p><code>loadClass()</code> makes sure that the <code>Class</code> + * returned by <code>findClass()</code> will later be returned by + * <code>findLoadedClass()</code> when the same class name is requested. + * + * @param name class name to find (including the package name) + * @return the requested Class + * @throws ClassNotFoundException when the class can not be found + * @since 1.2 + */ + protected Class findClass(String name) throws ClassNotFoundException + { + throw new ClassNotFoundException(name); + } + + /** + * Helper to define a class using a string of bytes. This version is not + * secure. + * + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + * @throws IndexOutOfBoundsException if offset or len is negative, or + * offset + len exceeds data + * @deprecated use {@link #defineClass(String, byte[], int, int)} instead + */ + protected final Class defineClass(byte[] data, int offset, int len) + throws ClassFormatError + { + return defineClass(null, data, offset, len); + } + + /** + * Helper to define a class using a string of bytes without a + * ProtectionDomain. Subclasses should call this method from their + * <code>findClass()</code> implementation. The name should use '.' + * separators, and discard the trailing ".class". The default protection + * domain has the permissions of + * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>. + * + * @param name the name to give the class, or null if unknown + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + * @throws IndexOutOfBoundsException if offset or len is negative, or + * offset + len exceeds data + * @throws SecurityException if name starts with "java." + * @since 1.1 + */ + protected final Class defineClass(String name, byte[] data, int offset, + int len) throws ClassFormatError + { + return defineClass(name, data, offset, len, null); + } + + /** + * Helper to define a class using a string of bytes. Subclasses should call + * this method from their <code>findClass()</code> implementation. If the + * domain is null, the default of + * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code> + * is used. Once a class has been defined in a package, all further classes + * in that package must have the same set of certificates or a + * SecurityException is thrown. + * + * @param name the name to give the class. null if unknown + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @param domain the ProtectionDomain to give to the class, null for the + * default protection domain + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + * @throws IndexOutOfBoundsException if offset or len is negative, or + * offset + len exceeds data + * @throws SecurityException if name starts with "java.", or if certificates + * do not match up + * @since 1.2 + */ + protected final synchronized Class defineClass(String name, byte[] data, + int offset, int len, + ProtectionDomain domain) + throws ClassFormatError + { + if (domain == null) + domain = StaticData.defaultProtectionDomain; + if (! initialized) + throw new SecurityException("attempt to define class from uninitialized class loader"); + + Class retval = VMClassLoader.defineClass(this, name, data, + offset, len, domain); + loadedClasses.put(retval.getName(), retval); + return retval; + } + + /** + * Links the class, if that has not already been done. Linking basically + * resolves all references to other classes made by this class. + * + * @param c the class to resolve + * @throws NullPointerException if c is null + * @throws LinkageError if linking fails + */ + protected final void resolveClass(Class c) + { + VMClassLoader.resolveClass(c); + } + + /** + * Helper to find a Class using the system classloader, possibly loading it. + * A subclass usually does not need to call this, if it correctly + * overrides <code>findClass(String)</code>. + * + * @param name the name of the class to find + * @return the found class + * @throws ClassNotFoundException if the class cannot be found + */ + protected final Class findSystemClass(String name) + throws ClassNotFoundException + { + return Class.forName(name, false, StaticData.systemClassLoader); + } + + /** + * Returns the parent of this classloader. If the parent of this + * classloader is the bootstrap classloader then this method returns + * <code>null</code>. A security check may be performed on + * <code>RuntimePermission("getClassLoader")</code>. + * + * @return the parent <code>ClassLoader</code> + * @throws SecurityException if the security check fails + * @since 1.2 + */ + public final ClassLoader getParent() + { + // Check if we may return the parent classloader. + SecurityManager sm = SecurityManager.current; + if (sm != null) + { + ClassLoader cl = VMStackWalker.getCallingClassLoader(); + if (cl != null && ! cl.isAncestorOf(this)) + sm.checkPermission(new RuntimePermission("getClassLoader")); + } + return parent; + } + + /** + * Helper to set the signers of a class. This should be called after + * defining the class. + * + * @param c the Class to set signers of + * @param signers the signers to set + * @since 1.1 + */ + protected final void setSigners(Class c, Object[] signers) + { + c.setSigners(signers); + } + + /** + * Helper to find an already-loaded class in this ClassLoader. + * + * @param name the name of the class to find + * @return the found Class, or null if it is not found + * @since 1.1 + */ + protected final synchronized Class findLoadedClass(String name) + { + // NOTE: If the VM is keeping its own cache, it may make sense to have + // this method be native. + return (Class) loadedClasses.get(name); + } + + /** + * Get the URL to a resource using this classloader or one of its parents. + * First tries to get the resource by calling <code>getResource()</code> + * on the parent classloader. If the parent classloader returns null then + * it tries finding the resource by calling <code>findResource()</code> on + * this classloader. The resource name should be separated by '/' for path + * elements. + * + * <p>Subclasses should not override this method but should override + * <code>findResource()</code> which is called by this method. + * + * @param name the name of the resource relative to this classloader + * @return the URL to the resource or null when not found + */ + public URL getResource(String name) + { + URL result; + + if (parent == null) + result = VMClassLoader.getResource(name); + else + result = parent.getResource(name); + + if (result == null) + result = findResource(name); + return result; + } + + /** + * Returns an Enumeration of all resources with a given name that can + * be found by this classloader and its parents. Certain classloaders + * (such as the URLClassLoader when given multiple jar files) can have + * multiple resources with the same name that come from multiple locations. + * It can also occur that a parent classloader offers a resource with a + * certain name and the child classloader also offers a resource with that + * same name. <code>getResource()</code> only offers the first resource (of the + * parent) with a given name. This method lists all resources with the + * same name. The name should use '/' as path separators. + * + * <p>The Enumeration is created by first calling <code>getResources()</code> + * on the parent classloader and then calling <code>findResources()</code> + * on this classloader.</p> + * + * @param name the resource name + * @return an enumaration of all resources found + * @throws IOException if I/O errors occur in the process + * @since 1.2 + */ + public final Enumeration getResources(String name) throws IOException + { + Enumeration parentResources; + if (parent == null) + parentResources = VMClassLoader.getResources(name); + else + parentResources = parent.getResources(name); + return new DoubleEnumeration(parentResources, findResources(name)); + } + + /** + * Called whenever all locations of a named resource are needed. + * It is called by <code>getResources()</code> after it has called + * <code>parent.getResources()</code>. The results are combined by + * the <code>getResources()</code> method. + * + * <p>The default implementation always returns an empty Enumeration. + * Subclasses should override it when they can provide an Enumeration of + * URLs (possibly just one element) to the named resource. + * The first URL of the Enumeration should be the same as the one + * returned by <code>findResource</code>. + * + * @param name the name of the resource to be found + * @return a possibly empty Enumeration of URLs to the named resource + * @throws IOException if I/O errors occur in the process + * @since 1.2 + */ + protected Enumeration findResources(String name) throws IOException + { + return EmptyEnumeration.getInstance(); + } + + /** + * Called whenever a resource is needed that could not be provided by + * one of the parents of this classloader. It is called by + * <code>getResource()</code> after <code>parent.getResource()</code> + * couldn't provide the requested resource. + * + * <p>The default implementation always returns null. Subclasses should + * override this method when they can provide a way to return a URL + * to a named resource. + * + * @param name the name of the resource to be found + * @return a URL to the named resource or null when not found + * @since 1.2 + */ + protected URL findResource(String name) + { + return null; + } + + /** + * Get the URL to a resource using the system classloader. + * + * @param name the name of the resource relative to the system classloader + * @return the URL to the resource + * @since 1.1 + */ + public static final URL getSystemResource(String name) + { + return StaticData.systemClassLoader.getResource(name); + } + + /** + * Get an Enumeration of URLs to resources with a given name using the + * the system classloader. The enumeration firsts lists the resources with + * the given name that can be found by the bootstrap classloader followed + * by the resources with the given name that can be found on the classpath. + * + * @param name the name of the resource relative to the system classloader + * @return an Enumeration of URLs to the resources + * @throws IOException if I/O errors occur in the process + * @since 1.2 + */ + public static Enumeration getSystemResources(String name) throws IOException + { + return StaticData.systemClassLoader.getResources(name); + } + + /** + * Get a resource as stream using this classloader or one of its parents. + * First calls <code>getResource()</code> and if that returns a URL to + * the resource then it calls and returns the InputStream given by + * <code>URL.openStream()</code>. + * + * <p>Subclasses should not override this method but should override + * <code>findResource()</code> which is called by this method. + * + * @param name the name of the resource relative to this classloader + * @return an InputStream to the resource, or null + * @since 1.1 + */ + public InputStream getResourceAsStream(String name) + { + try + { + URL url = getResource(name); + if (url == null) + return null; + return url.openStream(); + } + catch (IOException e) + { + return null; + } + } + + /** + * Get a resource using the system classloader. + * + * @param name the name of the resource relative to the system classloader + * @return an input stream for the resource, or null + * @since 1.1 + */ + public static final InputStream getSystemResourceAsStream(String name) + { + try + { + URL url = getSystemResource(name); + if (url == null) + return null; + return url.openStream(); + } + catch (IOException e) + { + return null; + } + } + + /** + * Returns the system classloader. The system classloader (also called + * the application classloader) is the classloader that is used to + * load the application classes on the classpath (given by the system + * property <code>java.class.path</code>. This is set as the context + * class loader for a thread. The system property + * <code>java.system.class.loader</code>, if defined, is taken to be the + * name of the class to use as the system class loader, which must have + * a public constructor which takes a ClassLoader as a parent. The parent + * class loader passed in the constructor is the default system class + * loader. + * + * <p>Note that this is different from the bootstrap classloader that + * actually loads all the real "system" classes. + * + * <p>A security check will be performed for + * <code>RuntimePermission("getClassLoader")</code> if the calling class + * is not a parent of the system class loader. + * + * @return the system class loader + * @throws SecurityException if the security check fails + * @throws IllegalStateException if this is called recursively + * @throws Error if <code>java.system.class.loader</code> fails to load + * @since 1.2 + */ + public static ClassLoader getSystemClassLoader() + { + // Check if we may return the system classloader + SecurityManager sm = SecurityManager.current; + if (sm != null) + { + ClassLoader cl = VMStackWalker.getCallingClassLoader(); + if (cl != null && cl != StaticData.systemClassLoader) + sm.checkPermission(new RuntimePermission("getClassLoader")); + } + + return StaticData.systemClassLoader; + } + + /** + * Defines a new package and creates a Package object. The package should + * be defined before any class in the package is defined with + * <code>defineClass()</code>. The package should not yet be defined + * before in this classloader or in one of its parents (which means that + * <code>getPackage()</code> should return <code>null</code>). All + * parameters except the <code>name</code> of the package may be + * <code>null</code>. + * + * <p>Subclasses should call this method from their <code>findClass()</code> + * implementation before calling <code>defineClass()</code> on a Class + * in a not yet defined Package (which can be checked by calling + * <code>getPackage()</code>). + * + * @param name the name of the Package + * @param specTitle the name of the specification + * @param specVendor the name of the specification designer + * @param specVersion the version of this specification + * @param implTitle the name of the implementation + * @param implVendor the vendor that wrote this implementation + * @param implVersion the version of this implementation + * @param sealed if sealed the origin of the package classes + * @return the Package object for the specified package + * @throws IllegalArgumentException if the package name is null or it + * was already defined by this classloader or one of its parents + * @see Package + * @since 1.2 + */ + protected Package definePackage(String name, String specTitle, + String specVendor, String specVersion, + String implTitle, String implVendor, + String implVersion, URL sealed) + { + if (getPackage(name) != null) + throw new IllegalArgumentException("Package " + name + + " already defined"); + Package p = new Package(name, specTitle, specVendor, specVersion, + implTitle, implVendor, implVersion, sealed); + synchronized (definedPackages) + { + definedPackages.put(name, p); + } + return p; + } + + /** + * Returns the Package object for the requested package name. It returns + * null when the package is not defined by this classloader or one of its + * parents. + * + * @param name the package name to find + * @return the package, if defined + * @since 1.2 + */ + protected Package getPackage(String name) + { + Package p; + if (parent == null) + p = VMClassLoader.getPackage(name); + else + p = parent.getPackage(name); + + if (p == null) + { + synchronized (definedPackages) + { + p = (Package) definedPackages.get(name); + } + } + return p; + } + + /** + * Returns all Package objects defined by this classloader and its parents. + * + * @return an array of all defined packages + * @since 1.2 + */ + protected Package[] getPackages() + { + // Get all our packages. + Package[] packages; + synchronized(definedPackages) + { + packages = new Package[definedPackages.size()]; + definedPackages.values().toArray(packages); + } + + // If we have a parent get all packages defined by our parents. + Package[] parentPackages; + if (parent == null) + parentPackages = VMClassLoader.getPackages(); + else + parentPackages = parent.getPackages(); + + Package[] allPackages = new Package[parentPackages.length + + packages.length]; + System.arraycopy(parentPackages, 0, allPackages, 0, + parentPackages.length); + System.arraycopy(packages, 0, allPackages, parentPackages.length, + packages.length); + return allPackages; + } + + /** + * Called by <code>Runtime.loadLibrary()</code> to get an absolute path + * to a (system specific) library that was requested by a class loaded + * by this classloader. The default implementation returns + * <code>null</code>. It should be implemented by subclasses when they + * have a way to find the absolute path to a library. If this method + * returns null the library is searched for in the default locations + * (the directories listed in the <code>java.library.path</code> system + * property). + * + * @param name the (system specific) name of the requested library + * @return the full pathname to the requested library, or null + * @see Runtime#loadLibrary() + * @since 1.2 + */ + protected String findLibrary(String name) + { + return null; + } + + /** + * Set the default assertion status for classes loaded by this classloader, + * used unless overridden by a package or class request. + * + * @param enabled true to set the default to enabled + * @see #setClassAssertionStatus(String, boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @see #clearAssertionStatus() + * @since 1.4 + */ + public void setDefaultAssertionStatus(boolean enabled) + { + defaultAssertionStatus = enabled; + } + + /** + * Set the default assertion status for packages, used unless overridden + * by a class request. This default also covers subpackages, unless they + * are also specified. The unnamed package should use null for the name. + * + * @param name the package (and subpackages) to affect + * @param enabled true to set the default to enabled + * @see #setDefaultAssertionStatus(String, boolean) + * @see #setClassAssertionStatus(String, boolean) + * @see #clearAssertionStatus() + * @since 1.4 + */ + public synchronized void setPackageAssertionStatus(String name, + boolean enabled) + { + if (packageAssertionStatus == null) + packageAssertionStatus + = new HashMap(StaticData.systemPackageAssertionStatus); + packageAssertionStatus.put(name, Boolean.valueOf(enabled)); + } + + /** + * Set the default assertion status for a class. This only affects the + * status of top-level classes, any other string is harmless. + * + * @param name the class to affect + * @param enabled true to set the default to enabled + * @throws NullPointerException if name is null + * @see #setDefaultAssertionStatus(String, boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @see #clearAssertionStatus() + * @since 1.4 + */ + public synchronized void setClassAssertionStatus(String name, + boolean enabled) + { + if (classAssertionStatus == null) + classAssertionStatus = + new HashMap(StaticData.systemClassAssertionStatus); + // The toString() hack catches null, as required. + classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); + } + + /** + * Resets the default assertion status of this classloader, its packages + * and classes, all to false. This allows overriding defaults inherited + * from the command line. + * + * @see #setDefaultAssertionStatus(boolean) + * @see #setClassAssertionStatus(String, boolean) + * @see #setPackageAssertionStatus(String, boolean) + * @since 1.4 + */ + public synchronized void clearAssertionStatus() + { + defaultAssertionStatus = false; + packageAssertionStatus = new HashMap(); + classAssertionStatus = new HashMap(); + } + + /** + * Return true if this loader is either the specified class loader + * or an ancestor thereof. + * @param loader the class loader to check + */ + final boolean isAncestorOf(ClassLoader loader) + { + while (loader != null) + { + if (this == loader) + return true; + loader = loader.parent; + } + return false; + } + + private static URL[] getExtClassLoaderUrls() + { + String classpath = SystemProperties.getProperty("java.ext.dirs", ""); + StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator); + ArrayList list = new ArrayList(); + while (tok.hasMoreTokens()) + { + try + { + File f = new File(tok.nextToken()); + File[] files = f.listFiles(); + if (files != null) + for (int i = 0; i < files.length; i++) + list.add(files[i].toURL()); + } + catch(Exception x) + { + } + } + URL[] urls = new URL[list.size()]; + list.toArray(urls); + return urls; + } + + private static void addFileURL(ArrayList list, String file) + { + try + { + list.add(new File(file).toURL()); + } + catch(java.net.MalformedURLException x) + { + } + } + + private static URL[] getSystemClassLoaderUrls() + { + String classpath = SystemProperties.getProperty("java.class.path", "."); + StringTokenizer tok = new StringTokenizer(classpath, File.pathSeparator, true); + ArrayList list = new ArrayList(); + while (tok.hasMoreTokens()) + { + String s = tok.nextToken(); + if (s.equals(File.pathSeparator)) + addFileURL(list, "."); + else + { + addFileURL(list, s); + if (tok.hasMoreTokens()) + { + // Skip the separator. + tok.nextToken(); + // If the classpath ended with a separator, + // append the current directory. + if (!tok.hasMoreTokens()) + addFileURL(list, "."); + } + } + } + URL[] urls = new URL[list.size()]; + list.toArray(urls); + return urls; + } + + static ClassLoader defaultGetSystemClassLoader() + { + return createAuxiliarySystemClassLoader( + createSystemClassLoader(getSystemClassLoaderUrls(), + createExtClassLoader(getExtClassLoaderUrls(), null))); + } + + static ClassLoader createExtClassLoader(URL[] urls, ClassLoader parent) + { + if (urls.length > 0) + return new URLClassLoader(urls, parent); + else + return parent; + } + + static ClassLoader createSystemClassLoader(URL[] urls, ClassLoader parent) + { + return + new URLClassLoader(urls, parent) + { + protected synchronized Class loadClass(String name, + boolean resolve) + throws ClassNotFoundException + { + SecurityManager sm = SecurityManager.current; + if (sm != null) + { + int lastDot = name.lastIndexOf('.'); + if (lastDot != -1) + sm.checkPackageAccess(name.substring(0, lastDot)); + } + return super.loadClass(name, resolve); + } + }; + } + + static ClassLoader createAuxiliarySystemClassLoader(ClassLoader parent) + { + String loader = SystemProperties.getProperty("java.system.class.loader", null); + if (loader == null) + { + return parent; + } + try + { + Constructor c = Class.forName(loader, false, parent) + .getConstructor(new Class[] { ClassLoader.class }); + return (ClassLoader)c.newInstance(new Object[] { parent }); + } + catch (Exception e) + { + System.err.println("Requested system classloader " + loader + " failed."); + throw (Error) + new Error("Requested system classloader " + loader + " failed.") + .initCause(e); + } + } +} diff --git a/libjava/classpath/java/lang/ClassNotFoundException.java b/libjava/classpath/java/lang/ClassNotFoundException.java new file mode 100644 index 0000000..6b6ae94 --- /dev/null +++ b/libjava/classpath/java/lang/ClassNotFoundException.java @@ -0,0 +1,125 @@ +/* ClassNotFoundException.java -- thrown when class definition cannot be found + Copyright (C) 1998, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when a class is requested by reflection, but the class definition + * cannot be found. This exception is often chained from another Throwable. + * + * @author Brian Jones + * @author Eric Blake (ebb9@email.byu.edu) + * @see Class#forName(String) + * @see ClassLoader#findSystemClass(String) + * @see ClassLoader#loadClass(String, boolean) + * @status updated to 1.4 + */ +public class ClassNotFoundException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 9176873029745254542L; + + /** + * The cause of this exception (duplicates the one stored in Throwable). + * + * @serial the exception cause + * @since 1.2 + */ + private final Throwable ex; + + /** + * Create an exception without a message. Note that this initializes the + * cause to null. + */ + public ClassNotFoundException() + { + this(null, null); + } + + /** + * Create an exception with a message. Note that this initializes the + * cause to null. + * + * @param s the message + */ + public ClassNotFoundException(String s) + { + this(s, null); + } + + /** + * Create an exception with a message and chain it to the exception + * which occurred while loading the class. + * + * @param s the message + * @param ex the chained exception + * @since 1.2 + */ + public ClassNotFoundException(String s, Throwable ex) + { + super(s, ex); + this.ex = ex; + } + + /** + * Returns the exception which occurred while loading the class, + * otherwise returns null. This is a legacy method; the preferred choice + * now is {@link Throwable#getCause()}. + * + * @return the cause of this exception + * @since 1.2 + */ + public Throwable getException() + { + return ex; + } + + /** + * Returns the exception which occurred while loading the class, + * otherwise returns null. + * + * @return the cause of this exception + * @since 1.4 + */ + public Throwable getCause() + { + return ex; + } +} diff --git a/libjava/classpath/java/lang/CloneNotSupportedException.java b/libjava/classpath/java/lang/CloneNotSupportedException.java new file mode 100644 index 0000000..9d10cf3 --- /dev/null +++ b/libjava/classpath/java/lang/CloneNotSupportedException.java @@ -0,0 +1,92 @@ +/* CloneNotSupportedException.java -- thrown when an object cannot be cloned + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown to indicate an object should not or could not be cloned. This + * includes the case when {@link Object#clone()} is called on an object + * which does not implement the {@link Cloneable} interface. For example:<br> + * <pre> + * void m() throws CloneNotSupportedException + * { + * clone(); + * } + * </pre> + * + * <p>Notice that calling <code>clone()</code> on an array will never produce + * this exception, as the VM will always succeed in copying the array, or + * cause an OutOfMemoryError first. For example:<br> + * <pre> + * void m(int[] array) + * { + * int[] copy = (int[]) array.clone(); + * } + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see Cloneable + * @see Object#clone() + * @status updated to 1.4 + */ +public class CloneNotSupportedException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 5195511250079656443L; + + /** + * Create an exception without a message. + */ + public CloneNotSupportedException() + { + } + + /** + * Create an exception with a message. + * + * @param s the error message + */ + public CloneNotSupportedException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Cloneable.java b/libjava/classpath/java/lang/Cloneable.java new file mode 100644 index 0000000..10f20ce --- /dev/null +++ b/libjava/classpath/java/lang/Cloneable.java @@ -0,0 +1,78 @@ +/* Cloneable.java -- Interface for marking objects cloneable by Object.clone() + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * This interface should be implemented by classes wishing to + * support of override <code>Object.clone()</code>. The default + * behaviour of <code>clone()</code> performs a shallow copy, but + * subclasses often change this to perform a deep copy. Therefore, + * it is a good idea to document how deep your clone will go. + * If <code>clone()</code> is called on an object which does not + * implement this interface, a <code>CloneNotSupportedException</code> + * will be thrown. + * + * <p>This interface is simply a tagging interface; it carries no + * requirements on methods to implement. However, it is typical for + * a Cloneable class to implement at least <code>equals</code>, + * <code>hashCode</code>, and <code>clone</code>, sometimes + * increasing the accessibility of clone to be public. The typical + * implementation of <code>clone</code> invokes <code>super.clone()</code> + * rather than a constructor, but this is not a requirement. + * + * <p>If an object that implement Cloneable should not be cloned, + * simply override the <code>clone</code> method to throw a + * <code>CloneNotSupportedException</code>. + * + * <p>All array types implement Cloneable, and have a public + * <code>clone</code> method that will never fail with a + * <code>CloneNotSupportedException</code>. + * + * @author Paul Fisher + * @author Eric Blake (ebb9@email.byu.edu) + * @author Warren Levy (warrenl@cygnus.com) + * @see Object#clone() + * @see CloneNotSupportedException + * @since 1.0 + * @status updated to 1.4 + */ +public interface Cloneable +{ + // Tagging interface only. +} diff --git a/libjava/classpath/java/lang/Comparable.java b/libjava/classpath/java/lang/Comparable.java new file mode 100644 index 0000000..a8afe1e --- /dev/null +++ b/libjava/classpath/java/lang/Comparable.java @@ -0,0 +1,98 @@ +/* Comparable.java -- Interface for comparaing objects to obtain an ordering + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Interface for objects that can be ordering among other objects. The + * ordering can be <em>total</em>, such that two objects only compare equal + * if they are also equal by the equals method, or <em>partial</em> such + * that this is not necessarily true. For example, a case-sensitive + * dictionary order comparison of Strings is total, but if it is + * case-insensitive it is partial, because "abc" and "ABC" compare as + * equal even though "abc".equals("ABC") returns false. However, if you use + * a partial ordering, it is a good idea to document your class as + * "inconsistent with equals", because the behavior of your class in a + * SortedMap will be different than in a HashMap. + * + * <p>Lists, arrays, and sets of objects that implement this interface can + * be sorted automatically, without the need for an explicit + * {@link java.util.Comparator}. Note that <code>e1.compareTo(null)</code> + * should throw an Exception; as should comparison between incompatible + * classes. + * + * @author Geoff Berry + * @author Warren Levy (warrenl@cygnus.com) + * @see java.util.Comparator + * @see java.util.Collections#sort(java.util.List) + * @see java.util.Arrays#sort(Object[]) + * @see java.util.SortedSet + * @see java.util.SortedMap + * @see java.util.TreeSet + * @see java.util.TreeMap + * @since 1.2 + * @status updated to 1.4 + */ +public interface Comparable +{ + /** + * Compares this object with another, and returns a numerical result based + * on the comparison. If the result is negative, this object sorts less + * than the other; if 0, the two are equal, and if positive, this object + * sorts greater than the other. To translate this into boolean, simply + * perform <code>o1.compareTo(o2) <em><op></em> 0</code>, where op + * is one of <, <=, =, !=, >, or >=. + * + * <p>You must make sure that the comparison is mutual, ie. + * <code>sgn(x.compareTo(y)) == -sgn(y.compareTo(x))</code> (where sgn() is + * defined as -1, 0, or 1 based on the sign). This includes throwing an + * exception in either direction if the two are not comparable; hence, + * <code>compareTo(null)</code> should always throw an Exception. + * + * <p>You should also ensure transitivity, in two forms: + * <code>x.compareTo(y) > 0 && y.compareTo(z) > 0</code> implies + * <code>x.compareTo(z) > 0</code>; and <code>x.compareTo(y) == 0</code> + * implies <code>x.compareTo(z) == y.compareTo(z)</code>. + * + * @param o the object to be compared + * @return an integer describing the comparison + * @throws NullPointerException if o is null + * @throws ClassCastException if o cannot be compared + */ + int compareTo(Object o); +} diff --git a/libjava/classpath/java/lang/Compiler.java b/libjava/classpath/java/lang/Compiler.java new file mode 100644 index 0000000..56fb951 --- /dev/null +++ b/libjava/classpath/java/lang/Compiler.java @@ -0,0 +1,127 @@ +/* Compiler.java -- placeholder for Java-to-native runtime compilers + Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * The <code>Compiler</code> class is a placeholder for a JIT compiler + * implementation, and does nothing unless there is such a compiler. + * + * <p>The system property <code>java.compiler</code> may contain the name + * of a library to load with <code>System.loadLibrary</code> when the + * virtual machine first starts. If so, and loading the library succeeds, + * then a function by the name of <code>java_lang_Compiler_start()</code> + * in that library is called. + * + * <p>Note that a VM might not have implemented any of this. + * + * @author Tom Tromey (tromey@cygnus.com) + * @see System#getProperty(String) + * @see System#getProperty(String, String) + * @see System#loadLibrary(String) + * @since JDK 1.0 + * @status updated to 1.4 + */ +public final class Compiler +{ + /** + * Don't allow new `Compiler's to be made. + */ + private Compiler() + { + } + + /** + * Compile the class named by <code>oneClass</code>. + * + * @param oneClass the class to compile + * @return <code>false</code> if no compiler is available or + * compilation failed, <code>true</code> if compilation succeeded + * @throws NullPointerException if oneClass is null + */ + public static boolean compileClass(Class oneClass) + { + return VMCompiler.compileClass(oneClass); + } + + /** + * Compile the classes whose name matches <code>classNames</code>. + * + * @param classNames the name of classes to compile + * @return <code>false</code> if no compiler is available or + * compilation failed, <code>true</code> if compilation succeeded + * @throws NullPointerException if classNames is null + */ + public static boolean compileClasses(String classNames) + { + return VMCompiler.compileClasses(classNames); + } + + /** + * This method examines the argument and performs an operation + * according to the compilers documentation. No specific operation + * is required. + * + * @param arg a compiler-specific argument + * @return a compiler-specific value, including null + * @throws NullPointerException if the compiler doesn't like a null arg + */ + public static Object command(Object arg) + { + return VMCompiler.command(arg); + } + + /** + * Calling <code>Compiler.enable()</code> will cause the compiler + * to resume operation if it was previously disabled; provided that a + * compiler even exists. + */ + public static void enable() + { + VMCompiler.enable(); + } + + /** + * Calling <code>Compiler.disable()</code> will cause the compiler + * to be suspended; provided that a compiler even exists. + */ + public static void disable() + { + VMCompiler.disable(); + } +} diff --git a/libjava/classpath/java/lang/Double.java b/libjava/classpath/java/lang/Double.java new file mode 100644 index 0000000..4fa47f4 --- /dev/null +++ b/libjava/classpath/java/lang/Double.java @@ -0,0 +1,521 @@ +/* Double.java -- object wrapper for double + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import gnu.classpath.Configuration; + +/** + * Instances of class <code>Double</code> represent primitive + * <code>double</code> values. + * + * Additionally, this class provides various helper functions and variables + * related to doubles. + * + * @author Paul Fisher + * @author Andrew Haley (aph@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public final class Double extends Number implements Comparable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -9172774392245257468L; + + /** + * The maximum positive value a <code>double</code> may represent + * is 1.7976931348623157e+308. + */ + public static final double MAX_VALUE = 1.7976931348623157e+308; + + /** + * The minimum positive value a <code>double</code> may represent + * is 5e-324. + */ + public static final double MIN_VALUE = 5e-324; + + /** + * The value of a double representation -1.0/0.0, negative + * infinity. + */ + public static final double NEGATIVE_INFINITY = -1.0 / 0.0; + + /** + * The value of a double representing 1.0/0.0, positive infinity. + */ + public static final double POSITIVE_INFINITY = 1.0 / 0.0; + + /** + * All IEEE 754 values of NaN have the same value in Java. + */ + public static final double NaN = 0.0 / 0.0; + + /** + * The primitive type <code>double</code> is represented by this + * <code>Class</code> object. + * @since 1.1 + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('D'); + + /** + * The immutable value of this Double. + * + * @serial the wrapped double + */ + private final double value; + + /** + * Create a <code>Double</code> from the primitive <code>double</code> + * specified. + * + * @param value the <code>double</code> argument + */ + public Double(double value) + { + this.value = value; + } + + /** + * Create a <code>Double</code> from the specified <code>String</code>. + * This method calls <code>Double.parseDouble()</code>. + * + * @param s the <code>String</code> to convert + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>double</code> + * @throws NullPointerException if <code>s</code> is null + * @see #parseDouble(String) + */ + public Double(String s) + { + value = parseDouble(s); + } + + /** + * Convert the <code>double</code> to a <code>String</code>. + * Floating-point string representation is fairly complex: here is a + * rundown of the possible values. "<code>[-]</code>" indicates that a + * negative sign will be printed if the value (or exponent) is negative. + * "<code><number></code>" means a string of digits ('0' to '9'). + * "<code><digit></code>" means a single digit ('0' to '9').<br> + * + * <table border=1> + * <tr><th>Value of Double</th><th>String Representation</th></tr> + * <tr><td>[+-] 0</td> <td><code>[-]0.0</code></td></tr> + * <tr><td>Between [+-] 10<sup>-3</sup> and 10<sup>7</sup>, exclusive</td> + * <td><code>[-]number.number</code></td></tr> + * <tr><td>Other numeric value</td> + * <td><code>[-]<digit>.<number> + * E[-]<number></code></td></tr> + * <tr><td>[+-] infinity</td> <td><code>[-]Infinity</code></td></tr> + * <tr><td>NaN</td> <td><code>NaN</code></td></tr> + * </table> + * + * Yes, negative zero <em>is</em> a possible value. Note that there is + * <em>always</em> a <code>.</code> and at least one digit printed after + * it: even if the number is 3, it will be printed as <code>3.0</code>. + * After the ".", all digits will be printed except trailing zeros. The + * result is rounded to the shortest decimal number which will parse back + * to the same double. + * + * <p>To create other output formats, use {@link java.text.NumberFormat}. + * + * @XXX specify where we are not in accord with the spec. + * + * @param d the <code>double</code> to convert + * @return the <code>String</code> representing the <code>double</code> + */ + public static String toString(double d) + { + return VMDouble.toString(d, false); + } + + /** + * Create a new <code>Double</code> object using the <code>String</code>. + * + * @param s the <code>String</code> to convert + * @return the new <code>Double</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>double</code> + * @throws NullPointerException if <code>s</code> is null. + * @see #parseDouble(String) + */ + public static Double valueOf(String s) + { + return new Double(parseDouble(s)); + } + + /** + * Parse the specified <code>String</code> as a <code>double</code>. The + * extended BNF grammar is as follows:<br> + * <pre> + * <em>DecodableString</em>: + * ( [ <code>-</code> | <code>+</code> ] <code>NaN</code> ) + * | ( [ <code>-</code> | <code>+</code> ] <code>Infinity</code> ) + * | ( [ <code>-</code> | <code>+</code> ] <em>FloatingPoint</em> + * [ <code>f</code> | <code>F</code> | <code>d</code> + * | <code>D</code>] ) + * <em>FloatingPoint</em>: + * ( { <em>Digit</em> }+ [ <code>.</code> { <em>Digit</em> } ] + * [ <em>Exponent</em> ] ) + * | ( <code>.</code> { <em>Digit</em> }+ [ <em>Exponent</em> ] ) + * <em>Exponent</em>: + * ( ( <code>e</code> | <code>E</code> ) + * [ <code>-</code> | <code>+</code> ] { <em>Digit</em> }+ ) + * <em>Digit</em>: <em><code>'0'</code> through <code>'9'</code></em> + * </pre> + * + * <p>NaN and infinity are special cases, to allow parsing of the output + * of toString. Otherwise, the result is determined by calculating + * <em>n * 10<sup>exponent</sup></em> to infinite precision, then rounding + * to the nearest double. Remember that many numbers cannot be precisely + * represented in floating point. In case of overflow, infinity is used, + * and in case of underflow, signed zero is used. Unlike Integer.parseInt, + * this does not accept Unicode digits outside the ASCII range. + * + * <p>If an unexpected character is found in the <code>String</code>, a + * <code>NumberFormatException</code> will be thrown. Leading and trailing + * 'whitespace' is ignored via <code>String.trim()</code>, but spaces + * internal to the actual number are not allowed. + * + * <p>To parse numbers according to another format, consider using + * {@link java.text.NumberFormat}. + * + * @XXX specify where/how we are not in accord with the spec. + * + * @param str the <code>String</code> to convert + * @return the <code>double</code> value of <code>s</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>double</code> + * @throws NullPointerException if <code>s</code> is null + * @see #MIN_VALUE + * @see #MAX_VALUE + * @see #POSITIVE_INFINITY + * @see #NEGATIVE_INFINITY + * @since 1.2 + */ + public static double parseDouble(String str) + { + return VMDouble.parseDouble(str); + } + + /** + * Return <code>true</code> if the <code>double</code> has the same + * value as <code>NaN</code>, otherwise return <code>false</code>. + * + * @param v the <code>double</code> to compare + * @return whether the argument is <code>NaN</code>. + */ + public static boolean isNaN(double v) + { + // This works since NaN != NaN is the only reflexive inequality + // comparison which returns true. + return v != v; + } + + /** + * Return <code>true</code> if the <code>double</code> has a value + * equal to either <code>NEGATIVE_INFINITY</code> or + * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>. + * + * @param v the <code>double</code> to compare + * @return whether the argument is (-/+) infinity. + */ + public static boolean isInfinite(double v) + { + return v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY; + } + + /** + * Return <code>true</code> if the value of this <code>Double</code> + * is the same as <code>NaN</code>, otherwise return <code>false</code>. + * + * @return whether this <code>Double</code> is <code>NaN</code> + */ + public boolean isNaN() + { + return isNaN(value); + } + + /** + * Return <code>true</code> if the value of this <code>Double</code> + * is the same as <code>NEGATIVE_INFINITY</code> or + * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>. + * + * @return whether this <code>Double</code> is (-/+) infinity + */ + public boolean isInfinite() + { + return isInfinite(value); + } + + /** + * Convert the <code>double</code> value of this <code>Double</code> + * to a <code>String</code>. This method calls + * <code>Double.toString(double)</code> to do its dirty work. + * + * @return the <code>String</code> representation + * @see #toString(double) + */ + public String toString() + { + return toString(value); + } + + /** + * Return the value of this <code>Double</code> as a <code>byte</code>. + * + * @return the byte value + * @since 1.1 + */ + public byte byteValue() + { + return (byte) value; + } + + /** + * Return the value of this <code>Double</code> as a <code>short</code>. + * + * @return the short value + * @since 1.1 + */ + public short shortValue() + { + return (short) value; + } + + /** + * Return the value of this <code>Double</code> as an <code>int</code>. + * + * @return the int value + */ + public int intValue() + { + return (int) value; + } + + /** + * Return the value of this <code>Double</code> as a <code>long</code>. + * + * @return the long value + */ + public long longValue() + { + return (long) value; + } + + /** + * Return the value of this <code>Double</code> as a <code>float</code>. + * + * @return the float value + */ + public float floatValue() + { + return (float) value; + } + + /** + * Return the value of this <code>Double</code>. + * + * @return the double value + */ + public double doubleValue() + { + return value; + } + + /** + * Return a hashcode representing this Object. <code>Double</code>'s hash + * code is calculated by:<br> + * <code>long v = Double.doubleToLongBits(doubleValue());<br> + * int hash = (int)(v^(v>>32))</code>. + * + * @return this Object's hash code + * @see #doubleToLongBits(double) + */ + public int hashCode() + { + long v = doubleToLongBits(value); + return (int) (v ^ (v >>> 32)); + } + + /** + * Returns <code>true</code> if <code>obj</code> is an instance of + * <code>Double</code> and represents the same double value. Unlike comparing + * two doubles with <code>==</code>, this treats two instances of + * <code>Double.NaN</code> as equal, but treats <code>0.0</code> and + * <code>-0.0</code> as unequal. + * + * <p>Note that <code>d1.equals(d2)</code> is identical to + * <code>doubleToLongBits(d1.doubleValue()) == + * doubleToLongBits(d2.doubleValue())</code>. + * + * @param obj the object to compare + * @return whether the objects are semantically equal + */ + public boolean equals(Object obj) + { + if (! (obj instanceof Double)) + return false; + + double d = ((Double) obj).value; + + // Avoid call to native method. However, some implementations, like gcj, + // are better off using floatToIntBits(value) == floatToIntBits(f). + // Check common case first, then check NaN and 0. + if (value == d) + return (value != 0) || (1 / value == 1 / d); + return isNaN(value) && isNaN(d); + } + + /** + * Convert the double to the IEEE 754 floating-point "double format" bit + * layout. Bit 63 (the most significant) is the sign bit, bits 62-52 + * (masked by 0x7ff0000000000000L) represent the exponent, and bits 51-0 + * (masked by 0x000fffffffffffffL) are the mantissa. This function + * collapses all versions of NaN to 0x7ff8000000000000L. The result of this + * function can be used as the argument to + * <code>Double.longBitsToDouble(long)</code> to obtain the original + * <code>double</code> value. + * + * @param value the <code>double</code> to convert + * @return the bits of the <code>double</code> + * @see #longBitsToDouble(long) + */ + public static long doubleToLongBits(double value) + { + return VMDouble.doubleToLongBits(value); + } + + /** + * Convert the double to the IEEE 754 floating-point "double format" bit + * layout. Bit 63 (the most significant) is the sign bit, bits 62-52 + * (masked by 0x7ff0000000000000L) represent the exponent, and bits 51-0 + * (masked by 0x000fffffffffffffL) are the mantissa. This function + * leaves NaN alone, rather than collapsing to a canonical value. The + * result of this function can be used as the argument to + * <code>Double.longBitsToDouble(long)</code> to obtain the original + * <code>double</code> value. + * + * @param value the <code>double</code> to convert + * @return the bits of the <code>double</code> + * @see #longBitsToDouble(long) + */ + public static long doubleToRawLongBits(double value) + { + return VMDouble.doubleToRawLongBits(value); + } + + /** + * Convert the argument in IEEE 754 floating-point "double format" bit + * layout to the corresponding float. Bit 63 (the most significant) is the + * sign bit, bits 62-52 (masked by 0x7ff0000000000000L) represent the + * exponent, and bits 51-0 (masked by 0x000fffffffffffffL) are the mantissa. + * This function leaves NaN alone, so that you can recover the bit pattern + * with <code>Double.doubleToRawLongBits(double)</code>. + * + * @param bits the bits to convert + * @return the <code>double</code> represented by the bits + * @see #doubleToLongBits(double) + * @see #doubleToRawLongBits(double) + */ + public static double longBitsToDouble(long bits) + { + return VMDouble.longBitsToDouble(bits); + } + + /** + * Compare two Doubles numerically by comparing their <code>double</code> + * values. The result is positive if the first is greater, negative if the + * second is greater, and 0 if the two are equal. However, this special + * cases NaN and signed zero as follows: NaN is considered greater than + * all other doubles, including <code>POSITIVE_INFINITY</code>, and positive + * zero is considered greater than negative zero. + * + * @param d the Double to compare + * @return the comparison + * @since 1.2 + */ + public int compareTo(Double d) + { + return compare(value, d.value); + } + + /** + * Behaves like <code>compareTo(Double)</code> unless the Object + * is not an <code>Double</code>. + * + * @param o the object to compare + * @return the comparison + * @throws ClassCastException if the argument is not a <code>Double</code> + * @see #compareTo(Double) + * @see Comparable + * @since 1.2 + */ + public int compareTo(Object o) + { + return compare(value, ((Double) o).value); + } + + /** + * Behaves like <code>new Double(x).compareTo(new Double(y))</code>; in + * other words this compares two doubles, special casing NaN and zero, + * without the overhead of objects. + * + * @param x the first double to compare + * @param y the second double to compare + * @return the comparison + * @since 1.4 + */ + public static int compare(double x, double y) + { + if (isNaN(x)) + return isNaN(y) ? 0 : 1; + if (isNaN(y)) + return -1; + // recall that 0.0 == -0.0, so we convert to infinites and try again + if (x == 0 && y == 0) + return (int) (1 / x - 1 / y); + if (x == y) + return 0; + + return x > y ? 1 : -1; + } +} diff --git a/libjava/classpath/java/lang/Error.java b/libjava/classpath/java/lang/Error.java new file mode 100644 index 0000000..f66c754 --- /dev/null +++ b/libjava/classpath/java/lang/Error.java @@ -0,0 +1,107 @@ +/* Error.java -- Indication of fatal abnormal conditions + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Applications should not try to catch errors since they indicate + * abnormal conditions. An abnormal condition is something which should not + * occur, or which should not be recovered from. This latter category + * includes <code>ThreadDeath</code> and <code>AssertionError</code>. + * + * <p>A method is not required to declare any subclass of <code>Error</code> in + * its <code>throws</code> clause which might be thrown but not caught while + * executing the method. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public class Error extends Throwable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 4980196508277280342L; + + /** + * Create an error without a message. The cause remains uninitialized. + * + * @see #initCause(Throwable) + */ + public Error() + { + } + + /** + * Create an error with a message. The cause remains uninitialized. + * + * @param s the message string + * @see #initCause(Throwable) + */ + public Error(String s) + { + super(s); + } + + /** + * Create an error with a message and a cause. + * + * @param s the message string + * @param cause the cause of this error + * @since 1.4 + */ + public Error(String s, Throwable cause) + { + super(s, cause); + } + + /** + * Create an error with a given cause, and a message of + * <code>cause == null ? null : cause.toString()</code>. + * + * @param cause the cause of this error + * @since 1.4 + */ + public Error(Throwable cause) + { + super(cause); + } +} diff --git a/libjava/classpath/java/lang/Exception.java b/libjava/classpath/java/lang/Exception.java new file mode 100644 index 0000000..42f7c64 --- /dev/null +++ b/libjava/classpath/java/lang/Exception.java @@ -0,0 +1,104 @@ +/* Exception.java -- generic exception thrown to indicate an exceptional + condition has occurred. + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * The root class of all exceptions worth catching in a program. This + * includes the special category of <code>RuntimeException</code>, which + * does not need to be declared in a throws clause. Exceptions can be used + * to represent almost any exceptional behavior, such as programming errors, + * mouse movements, keyboard clicking, etc. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @status updated to 1.4 + */ +public class Exception extends Throwable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -3387516993124229948L; + + /** + * Create an exception without a message. The cause remains uninitialized. + * + * @see #initCause(Throwable) + */ + public Exception() + { + } + + /** + * Create an exception with a message. The cause remains uninitialized. + * + * @param s the message + * @see #initCause(Throwable) + */ + public Exception(String s) + { + super(s); + } + + /** + * Create an exception with a message and a cause. + * + * @param s the message string + * @param cause the cause of this error + * @since 1.4 + */ + public Exception(String s, Throwable cause) + { + super(s, cause); + } + + /** + * Create an exception with a given cause, and a message of + * <code>cause == null ? null : cause.toString()</code>. + * + * @param cause the cause of this exception + * @since 1.4 + */ + public Exception(Throwable cause) + { + super(cause); + } +} diff --git a/libjava/classpath/java/lang/ExceptionInInitializerError.java b/libjava/classpath/java/lang/ExceptionInInitializerError.java new file mode 100644 index 0000000..1e58095 --- /dev/null +++ b/libjava/classpath/java/lang/ExceptionInInitializerError.java @@ -0,0 +1,123 @@ +/* ExceptionInInitializerError.java -- thrown when class initialization fails + with an uncaught exception + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>ExceptionInInitializerError</code> is thrown when an uncaught + * exception has occurred in a static initializer or the initializer for a + * static variable. In general, this wraps only RuntimeExceptions, since the + * compiler does not allow a checked exception to be uncaught in an + * initializer. This exception only occurs during reflection, when a class + * is initialized as part of another action. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.1 + * @status updated to 1.4 + */ +public class ExceptionInInitializerError extends LinkageError +{ + /** + * Compatible with JDK 1.1+. + */ + static final long serialVersionUID = 1521711792217232256L; + + /** + * The cause of this exception (duplicates the one stored in Throwable). + * + * @serial the exception cause + */ + private final Throwable exception; + + /** + * Create an error without a message. The cause is initialized as null. + */ + public ExceptionInInitializerError() + { + this((String) null); + } + + /** + * Create an error with a message. The cause is initialized as null. + * + * @param s the message + */ + public ExceptionInInitializerError(String s) + { + super(s); + exception = null; + } + + /** + * Creates an error an saves a reference to the <code>Throwable</code> + * object. The message string is null. + * + * @param t the exception thrown + */ + public ExceptionInInitializerError(Throwable t) + { + super(null); + initCause(t); + exception = t; + } + + /** + * Return the exception that caused this error to be created. This is a + * legacy method; the preferred choice now is {@link Throwable#getCause()}. + * + * @return the cause, or null if unknown + */ + public Throwable getException() + { + return exception; + } + + /** + * Return the exception that cause this error to be created. + * + * @return the cause, or null if unknown + * @since 1.4 + */ + public Throwable getCause() + { + return exception; + } +} diff --git a/libjava/classpath/java/lang/Float.java b/libjava/classpath/java/lang/Float.java new file mode 100644 index 0000000..e6200da --- /dev/null +++ b/libjava/classpath/java/lang/Float.java @@ -0,0 +1,527 @@ +/* Float.java -- object wrapper for float + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Instances of class <code>Float</code> represent primitive + * <code>float</code> values. + * + * Additionally, this class provides various helper functions and variables + * related to floats. + * + * @author Paul Fisher + * @author Andrew Haley (aph@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public final class Float extends Number implements Comparable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -2671257302660747028L; + + /** + * The maximum positive value a <code>double</code> may represent + * is 3.4028235e+38f. + */ + public static final float MAX_VALUE = 3.4028235e+38f; + + /** + * The minimum positive value a <code>float</code> may represent + * is 1.4e-45. + */ + public static final float MIN_VALUE = 1.4e-45f; + + /** + * The value of a float representation -1.0/0.0, negative infinity. + */ + public static final float NEGATIVE_INFINITY = -1.0f / 0.0f; + + /** + * The value of a float representation 1.0/0.0, positive infinity. + */ + public static final float POSITIVE_INFINITY = 1.0f / 0.0f; + + /** + * All IEEE 754 values of NaN have the same value in Java. + */ + public static final float NaN = 0.0f / 0.0f; + + /** + * The primitive type <code>float</code> is represented by this + * <code>Class</code> object. + * @since 1.1 + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('F'); + + /** + * The immutable value of this Float. + * + * @serial the wrapped float + */ + private final float value; + + /** + * Create a <code>Float</code> from the primitive <code>float</code> + * specified. + * + * @param value the <code>float</code> argument + */ + public Float(float value) + { + this.value = value; + } + + /** + * Create a <code>Float</code> from the primitive <code>double</code> + * specified. + * + * @param value the <code>double</code> argument + */ + public Float(double value) + { + this.value = (float) value; + } + + /** + * Create a <code>Float</code> from the specified <code>String</code>. + * This method calls <code>Float.parseFloat()</code>. + * + * @param s the <code>String</code> to convert + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>float</code> + * @throws NullPointerException if <code>s</code> is null + * @see #parseFloat(String) + */ + public Float(String s) + { + value = parseFloat(s); + } + + /** + * Convert the <code>float</code> to a <code>String</code>. + * Floating-point string representation is fairly complex: here is a + * rundown of the possible values. "<code>[-]</code>" indicates that a + * negative sign will be printed if the value (or exponent) is negative. + * "<code><number></code>" means a string of digits ('0' to '9'). + * "<code><digit></code>" means a single digit ('0' to '9').<br> + * + * <table border=1> + * <tr><th>Value of Float</th><th>String Representation</th></tr> + * <tr><td>[+-] 0</td> <td><code>[-]0.0</code></td></tr> + * <tr><td>Between [+-] 10<sup>-3</sup> and 10<sup>7</sup>, exclusive</td> + * <td><code>[-]number.number</code></td></tr> + * <tr><td>Other numeric value</td> + * <td><code>[-]<digit>.<number> + * E[-]<number></code></td></tr> + * <tr><td>[+-] infinity</td> <td><code>[-]Infinity</code></td></tr> + * <tr><td>NaN</td> <td><code>NaN</code></td></tr> + * </table> + * + * Yes, negative zero <em>is</em> a possible value. Note that there is + * <em>always</em> a <code>.</code> and at least one digit printed after + * it: even if the number is 3, it will be printed as <code>3.0</code>. + * After the ".", all digits will be printed except trailing zeros. The + * result is rounded to the shortest decimal number which will parse back + * to the same float. + * + * <p>To create other output formats, use {@link java.text.NumberFormat}. + * + * @XXX specify where we are not in accord with the spec. + * + * @param f the <code>float</code> to convert + * @return the <code>String</code> representing the <code>float</code> + */ + public static String toString(float f) + { + return VMDouble.toString(f, true); + } + + /** + * Creates a new <code>Float</code> object using the <code>String</code>. + * + * @param s the <code>String</code> to convert + * @return the new <code>Float</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>float</code> + * @throws NullPointerException if <code>s</code> is null + * @see #parseFloat(String) + */ + public static Float valueOf(String s) + { + return new Float(parseFloat(s)); + } + + /** + * Parse the specified <code>String</code> as a <code>float</code>. The + * extended BNF grammar is as follows:<br> + * <pre> + * <em>DecodableString</em>: + * ( [ <code>-</code> | <code>+</code> ] <code>NaN</code> ) + * | ( [ <code>-</code> | <code>+</code> ] <code>Infinity</code> ) + * | ( [ <code>-</code> | <code>+</code> ] <em>FloatingPoint</em> + * [ <code>f</code> | <code>F</code> | <code>d</code> + * | <code>D</code>] ) + * <em>FloatingPoint</em>: + * ( { <em>Digit</em> }+ [ <code>.</code> { <em>Digit</em> } ] + * [ <em>Exponent</em> ] ) + * | ( <code>.</code> { <em>Digit</em> }+ [ <em>Exponent</em> ] ) + * <em>Exponent</em>: + * ( ( <code>e</code> | <code>E</code> ) + * [ <code>-</code> | <code>+</code> ] { <em>Digit</em> }+ ) + * <em>Digit</em>: <em><code>'0'</code> through <code>'9'</code></em> + * </pre> + * + * <p>NaN and infinity are special cases, to allow parsing of the output + * of toString. Otherwise, the result is determined by calculating + * <em>n * 10<sup>exponent</sup></em> to infinite precision, then rounding + * to the nearest float. Remember that many numbers cannot be precisely + * represented in floating point. In case of overflow, infinity is used, + * and in case of underflow, signed zero is used. Unlike Integer.parseInt, + * this does not accept Unicode digits outside the ASCII range. + * + * <p>If an unexpected character is found in the <code>String</code>, a + * <code>NumberFormatException</code> will be thrown. Leading and trailing + * 'whitespace' is ignored via <code>String.trim()</code>, but spaces + * internal to the actual number are not allowed. + * + * <p>To parse numbers according to another format, consider using + * {@link java.text.NumberFormat}. + * + * @XXX specify where/how we are not in accord with the spec. + * + * @param str the <code>String</code> to convert + * @return the <code>float</code> value of <code>s</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>float</code> + * @throws NullPointerException if <code>s</code> is null + * @see #MIN_VALUE + * @see #MAX_VALUE + * @see #POSITIVE_INFINITY + * @see #NEGATIVE_INFINITY + * @since 1.2 + */ + public static float parseFloat(String str) + { + // XXX Rounding parseDouble() causes some errors greater than 1 ulp from + // the infinitely precise decimal. + return (float) Double.parseDouble(str); + } + + /** + * Return <code>true</code> if the <code>float</code> has the same + * value as <code>NaN</code>, otherwise return <code>false</code>. + * + * @param v the <code>float</code> to compare + * @return whether the argument is <code>NaN</code> + */ + public static boolean isNaN(float v) + { + // This works since NaN != NaN is the only reflexive inequality + // comparison which returns true. + return v != v; + } + + /** + * Return <code>true</code> if the <code>float</code> has a value + * equal to either <code>NEGATIVE_INFINITY</code> or + * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>. + * + * @param v the <code>float</code> to compare + * @return whether the argument is (-/+) infinity + */ + public static boolean isInfinite(float v) + { + return v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY; + } + + /** + * Return <code>true</code> if the value of this <code>Float</code> + * is the same as <code>NaN</code>, otherwise return <code>false</code>. + * + * @return whether this <code>Float</code> is <code>NaN</code> + */ + public boolean isNaN() + { + return isNaN(value); + } + + /** + * Return <code>true</code> if the value of this <code>Float</code> + * is the same as <code>NEGATIVE_INFINITY</code> or + * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>. + * + * @return whether this <code>Float</code> is (-/+) infinity + */ + public boolean isInfinite() + { + return isInfinite(value); + } + + /** + * Convert the <code>float</code> value of this <code>Float</code> + * to a <code>String</code>. This method calls + * <code>Float.toString(float)</code> to do its dirty work. + * + * @return the <code>String</code> representation + * @see #toString(float) + */ + public String toString() + { + return toString(value); + } + + /** + * Return the value of this <code>Float</code> as a <code>byte</code>. + * + * @return the byte value + * @since 1.1 + */ + public byte byteValue() + { + return (byte) value; + } + + /** + * Return the value of this <code>Float</code> as a <code>short</code>. + * + * @return the short value + * @since 1.1 + */ + public short shortValue() + { + return (short) value; + } + + /** + * Return the value of this <code>Integer</code> as an <code>int</code>. + * + * @return the int value + */ + public int intValue() + { + return (int) value; + } + + /** + * Return the value of this <code>Integer</code> as a <code>long</code>. + * + * @return the long value + */ + public long longValue() + { + return (long) value; + } + + /** + * Return the value of this <code>Float</code>. + * + * @return the float value + */ + public float floatValue() + { + return value; + } + + /** + * Return the value of this <code>Float</code> as a <code>double</code> + * + * @return the double value + */ + public double doubleValue() + { + return value; + } + + /** + * Return a hashcode representing this Object. <code>Float</code>'s hash + * code is calculated by calling <code>floatToIntBits(floatValue())</code>. + * + * @return this Object's hash code + * @see #floatToIntBits(float) + */ + public int hashCode() + { + return floatToIntBits(value); + } + + /** + * Returns <code>true</code> if <code>obj</code> is an instance of + * <code>Float</code> and represents the same float value. Unlike comparing + * two floats with <code>==</code>, this treats two instances of + * <code>Float.NaN</code> as equal, but treats <code>0.0</code> and + * <code>-0.0</code> as unequal. + * + * <p>Note that <code>f1.equals(f2)</code> is identical to + * <code>floatToIntBits(f1.floatValue()) == + * floatToIntBits(f2.floatValue())</code>. + * + * @param obj the object to compare + * @return whether the objects are semantically equal + */ + public boolean equals(Object obj) + { + if (! (obj instanceof Float)) + return false; + + float f = ((Float) obj).value; + + // Avoid call to native method. However, some implementations, like gcj, + // are better off using floatToIntBits(value) == floatToIntBits(f). + // Check common case first, then check NaN and 0. + if (value == f) + return (value != 0) || (1 / value == 1 / f); + return isNaN(value) && isNaN(f); + } + + /** + * Convert the float to the IEEE 754 floating-point "single format" bit + * layout. Bit 31 (the most significant) is the sign bit, bits 30-23 + * (masked by 0x7f800000) represent the exponent, and bits 22-0 + * (masked by 0x007fffff) are the mantissa. This function collapses all + * versions of NaN to 0x7fc00000. The result of this function can be used + * as the argument to <code>Float.intBitsToFloat(int)</code> to obtain the + * original <code>float</code> value. + * + * @param value the <code>float</code> to convert + * @return the bits of the <code>float</code> + * @see #intBitsToFloat(int) + */ + public static int floatToIntBits(float value) + { + return VMFloat.floatToIntBits(value); + } + + /** + * Convert the float to the IEEE 754 floating-point "single format" bit + * layout. Bit 31 (the most significant) is the sign bit, bits 30-23 + * (masked by 0x7f800000) represent the exponent, and bits 22-0 + * (masked by 0x007fffff) are the mantissa. This function leaves NaN alone, + * rather than collapsing to a canonical value. The result of this function + * can be used as the argument to <code>Float.intBitsToFloat(int)</code> to + * obtain the original <code>float</code> value. + * + * @param value the <code>float</code> to convert + * @return the bits of the <code>float</code> + * @see #intBitsToFloat(int) + */ + public static int floatToRawIntBits(float value) + { + return VMFloat.floatToRawIntBits(value); + } + + /** + * Convert the argument in IEEE 754 floating-point "single format" bit + * layout to the corresponding float. Bit 31 (the most significant) is the + * sign bit, bits 30-23 (masked by 0x7f800000) represent the exponent, and + * bits 22-0 (masked by 0x007fffff) are the mantissa. This function leaves + * NaN alone, so that you can recover the bit pattern with + * <code>Float.floatToRawIntBits(float)</code>. + * + * @param bits the bits to convert + * @return the <code>float</code> represented by the bits + * @see #floatToIntBits(float) + * @see #floatToRawIntBits(float) + */ + public static float intBitsToFloat(int bits) + { + return VMFloat.intBitsToFloat(bits); + } + + /** + * Compare two Floats numerically by comparing their <code>float</code> + * values. The result is positive if the first is greater, negative if the + * second is greater, and 0 if the two are equal. However, this special + * cases NaN and signed zero as follows: NaN is considered greater than + * all other floats, including <code>POSITIVE_INFINITY</code>, and positive + * zero is considered greater than negative zero. + * + * @param f the Float to compare + * @return the comparison + * @since 1.2 + */ + public int compareTo(Float f) + { + return compare(value, f.value); + } + + /** + * Behaves like <code>compareTo(Float)</code> unless the Object + * is not an <code>Float</code>. + * + * @param o the object to compare + * @return the comparison + * @throws ClassCastException if the argument is not a <code>Float</code> + * @see #compareTo(Float) + * @see Comparable + * @since 1.2 + */ + public int compareTo(Object o) + { + return compare(value, ((Float) o).value); + } + + /** + * Behaves like <code>new Float(x).compareTo(new Float(y))</code>; in + * other words this compares two floats, special casing NaN and zero, + * without the overhead of objects. + * + * @param x the first float to compare + * @param y the second float to compare + * @return the comparison + * @since 1.4 + */ + public static int compare(float x, float y) + { + if (isNaN(x)) + return isNaN(y) ? 0 : 1; + if (isNaN(y)) + return -1; + // recall that 0.0 == -0.0, so we convert to infinities and try again + if (x == 0 && y == 0) + return (int) (1 / x - 1 / y); + if (x == y) + return 0; + + return x > y ? 1 : -1; + } +} diff --git a/libjava/classpath/java/lang/IllegalAccessError.java b/libjava/classpath/java/lang/IllegalAccessError.java new file mode 100644 index 0000000..e482160 --- /dev/null +++ b/libjava/classpath/java/lang/IllegalAccessError.java @@ -0,0 +1,76 @@ +/* IllegalAccessError.java -- thrown when linking to an inaccessible member + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>IllegalAccessError</code> is thrown when an attempt is made to + * call a method, or access or modify a field that the application does not + * have access to. Because this error is usually caught by a compiler, + * the error only occurs at runtime when the definition of a class has + * changed in a way that is incompatible with the previously compiled + * application. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class IllegalAccessError extends IncompatibleClassChangeError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -8988904074992417891L; + + /** + * Create an error without a message. + */ + public IllegalAccessError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public IllegalAccessError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/IllegalAccessException.java b/libjava/classpath/java/lang/IllegalAccessException.java new file mode 100644 index 0000000..a352c8b --- /dev/null +++ b/libjava/classpath/java/lang/IllegalAccessException.java @@ -0,0 +1,99 @@ +/* IllegalAccessException.java -- thrown on attempt to reflect on + inaccessible data + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Thrown whenever a reflective method tries to do something that the + * compiler would not allow. For example, using reflection to set a private + * variable that belongs to a class in another package is bad. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @see Class#newInstance() + * @see Field#set(Object, Object) + * @see Field#setBoolean(Object, boolean) + * @see Field#setByte(Object, byte) + * @see Field#setShort(Object, short) + * @see Field#setChar(Object, char) + * @see Field#setInt(Object, int) + * @see Field#setLong(Object, long) + * @see Field#setFloat(Object, float) + * @see Field#setDouble(Object, double) + * @see Field#get(Object) + * @see Field#getBoolean(Object) + * @see Field#getByte(Object) + * @see Field#getShort(Object) + * @see Field#getChar(Object) + * @see Field#getInt(Object) + * @see Field#getLong(Object) + * @see Field#getFloat(Object) + * @see Field#getDouble(Object) + * @see Method#invoke(Object, Object[]) + * @see Constructor#newInstance(Object[]) + * @status updated to 1.4 + */ +public class IllegalAccessException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 6616958222490762034L; + + /** + * Create an exception without a message. + */ + public IllegalAccessException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public IllegalAccessException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/IllegalArgumentException.java b/libjava/classpath/java/lang/IllegalArgumentException.java new file mode 100644 index 0000000..7b822b9 --- /dev/null +++ b/libjava/classpath/java/lang/IllegalArgumentException.java @@ -0,0 +1,75 @@ +/* IllegalArgumentException.java -- thrown when a method is passed an + illegal or inappropriate argument + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +/** + * Thrown when a method is passed an illegal or inappropriate argument. For + * example:<br> + * <pre> + * wait(-1); + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class IllegalArgumentException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -5365630128856068164L; + + /** + * Create an exception without a message. + */ + public IllegalArgumentException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public IllegalArgumentException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/IllegalMonitorStateException.java b/libjava/classpath/java/lang/IllegalMonitorStateException.java new file mode 100644 index 0000000..13b3f95 --- /dev/null +++ b/libjava/classpath/java/lang/IllegalMonitorStateException.java @@ -0,0 +1,78 @@ +/* IllegalMonitorStateException.java -- thrown when trying to wait or + notify a monitor that is not owned + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when a thread attempts to wait or notify on a monitor that it + * does not own (ie. it has not synchronized on the object). For example:<br> + * <pre> + * void m() { + * notify(); + * } + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class IllegalMonitorStateException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 3713306369498869069L; + + /** + * Create an exception without a message. + */ + public IllegalMonitorStateException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public IllegalMonitorStateException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/IllegalStateException.java b/libjava/classpath/java/lang/IllegalStateException.java new file mode 100644 index 0000000..5c2bbad --- /dev/null +++ b/libjava/classpath/java/lang/IllegalStateException.java @@ -0,0 +1,80 @@ +/* IllegalStateException.java -- thrown when invoking a method at + an illegal or inappropriate time + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when a method is invoked at an illegal or inappropriate time. For + * example:<br> + * <pre> + * void m(Collecion c) + * { + * c.iterator().remove(); + * } + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @since 1.1 + * @status updated to 1.4 + */ +public class IllegalStateException extends RuntimeException +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -1848914673093119416L; + + /** + * Create an exception without a message. + */ + public IllegalStateException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public IllegalStateException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/IllegalThreadStateException.java b/libjava/classpath/java/lang/IllegalThreadStateException.java new file mode 100644 index 0000000..e14385a --- /dev/null +++ b/libjava/classpath/java/lang/IllegalThreadStateException.java @@ -0,0 +1,75 @@ +/* IllegalThreadStateException.java -- thrown when trying to manipulate a + Thread when it is not in an appropriate state + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown When trying to manipulate a Thread which is in an inappropriate + * state. Since the documentation suggests that this can happen with + * <code>Thread.suspend</code> or <code>Thread.resume</code>, but these + * two methods are deprecated, this exception is likely very rare. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class IllegalThreadStateException extends IllegalArgumentException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -7626246362397460174L; + + /** + * Create an exception without a message. + */ + public IllegalThreadStateException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public IllegalThreadStateException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/IncompatibleClassChangeError.java b/libjava/classpath/java/lang/IncompatibleClassChangeError.java new file mode 100644 index 0000000..637410a --- /dev/null +++ b/libjava/classpath/java/lang/IncompatibleClassChangeError.java @@ -0,0 +1,73 @@ +/* IncompatibleClassChangeError.java -- thrown for binary incompatible classes + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>IncompatibleClassChangeError</code> is thrown when the definition + * of a class used by the currently executing method has changed in an + * incompatible way. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class IncompatibleClassChangeError extends LinkageError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -4914975503642802119L; + + /** + * Create an error without a message. + */ + public IncompatibleClassChangeError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public IncompatibleClassChangeError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/IndexOutOfBoundsException.java b/libjava/classpath/java/lang/IndexOutOfBoundsException.java new file mode 100644 index 0000000..c53c67e --- /dev/null +++ b/libjava/classpath/java/lang/IndexOutOfBoundsException.java @@ -0,0 +1,75 @@ +/* IndexOutOfBoundsException.java -- thrown for an invalid index + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * This exception can be thrown to indicate an attempt to access an + * index which is out of bounds on objects like String, Array, or Vector. + * Usually any negative integer less than or equal to -1 and positive + * integer greater than or equal to the size of the object is an index + * which would be out of bounds. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class IndexOutOfBoundsException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 234122996006267687L; + + /** + * Create an exception without a message. + */ + public IndexOutOfBoundsException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public IndexOutOfBoundsException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/InheritableThreadLocal.java b/libjava/classpath/java/lang/InheritableThreadLocal.java new file mode 100644 index 0000000..69ff613 --- /dev/null +++ b/libjava/classpath/java/lang/InheritableThreadLocal.java @@ -0,0 +1,116 @@ +/* InheritableThreadLocal -- a ThreadLocal which inherits values across threads + Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.util.Iterator; +import java.util.WeakHashMap; + +/** + * A ThreadLocal whose value is inherited by child Threads. The value of the + * InheritableThreadLocal associated with the (parent) Thread is copied to + * the new (child) Thread at the moment of creation. + * + * <p>It is possible to make the value associated with the child Thread a + * function of the value that is associated with the parent Thread by + * overriding the <code>childValue()</code> method. The utility of this class + * is in transferring items like User ID or Transaction ID across threads + * automatically. + * + * @author Mark Wielaard (mark@klomp.org) + * @author Eric Blake (ebb9@email.byu.edu) + * @see ThreadLocal + * @since 1.2 + * @status updated to 1.4 + */ +public class InheritableThreadLocal extends ThreadLocal +{ + /** + * Creates a new InheritableThreadLocal that has no values associated + * with it yet. + */ + public InheritableThreadLocal() + { + } + + /** + * Determines the value associated with a newly created child Thread as a + * function of the value associated with the currently executing (parent) + * Thread. The default implementation just returns the parentValue. + * + * @param parentValue the value of this object in the parent thread at + * the moment of creation of the child + * @return the initial value for the child thread + */ + protected Object childValue(Object parentValue) + { + return parentValue; + } + + /** + * Generates the childValues of all <code>InheritableThreadLocal</code>s + * that are in the heritage of the current Thread for the newly created + * childThread. Should be called from the contructor Thread. + * + * @param childThread the newly created thread, to inherit from this thread + * @see Thread#Thread(ThreadGroup, Runnable, String) + */ + static void newChildThread(Thread childThread) + { + // The currentThread is the parent of the new thread. + Thread parentThread = Thread.currentThread(); + if (parentThread.locals != null) + { + Iterator keys = parentThread.locals.keySet().iterator(); + while (keys.hasNext()) + { + Key key = (Key)keys.next(); + if (key.get() instanceof InheritableThreadLocal) + { + InheritableThreadLocal local = (InheritableThreadLocal)key.get(); + Object parentValue = parentThread.locals.get(key); + Object childValue = local.childValue(parentValue == NULL + ? null : parentValue); + if (childThread.locals == null) + childThread.locals = new WeakHashMap(); + childThread.locals.put(key, (childValue == null + ? NULL : childValue)); + } + } + } + } +} diff --git a/libjava/classpath/java/lang/InstantiationError.java b/libjava/classpath/java/lang/InstantiationError.java new file mode 100644 index 0000000..dd12b51 --- /dev/null +++ b/libjava/classpath/java/lang/InstantiationError.java @@ -0,0 +1,75 @@ +/* InstantiationError.java -- thrown when the linker cannot create an instance + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>InstantiationError</code> is thrown when an attempt is made to + * create an instance of an abstract class or an interface. Because this + * error is usually caught by a compiler, the error only occurs at runtime + * when the definition of a class has changed in a way that is incompatible + * with the previously compiled application. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class InstantiationError extends IncompatibleClassChangeError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -4885810657349421204L; + + /** + * Create an error without a message. + */ + public InstantiationError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public InstantiationError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/InstantiationException.java b/libjava/classpath/java/lang/InstantiationException.java new file mode 100644 index 0000000..367b14b --- /dev/null +++ b/libjava/classpath/java/lang/InstantiationException.java @@ -0,0 +1,74 @@ +/* InstantiationException.java -- thrown when reflection cannot create an + instance + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when an attempt is made to use reflection to build a + * non-instantiable class (an interface or abstract class). + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @see Class#newInstance() + * @status updated to 1.4 + */ +public class InstantiationException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -8441929162975509110L; + + /** + * Create an exception without a message. + */ + public InstantiationException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public InstantiationException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Integer.java b/libjava/classpath/java/lang/Integer.java new file mode 100644 index 0000000..07be4e3 --- /dev/null +++ b/libjava/classpath/java/lang/Integer.java @@ -0,0 +1,772 @@ +/* Integer.java -- object wrapper for int + Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Instances of class <code>Integer</code> represent primitive + * <code>int</code> values. + * + * Additionally, this class provides various helper functions and variables + * related to ints. + * + * @author Paul Fisher + * @author John Keiser + * @author Warren Levy + * @author Eric Blake (ebb9@email.byu.edu) + * @author Tom Tromey (tromey@redhat.com) + * @since 1.0 + * @status largely updated to 1.5 + */ +public final class Integer extends Number implements Comparable +{ + /** + * Compatible with JDK 1.0.2+. + */ + private static final long serialVersionUID = 1360826667806852920L; + + /** + * The minimum value an <code>int</code> can represent is -2147483648 (or + * -2<sup>31</sup>). + */ + public static final int MIN_VALUE = 0x80000000; + + /** + * The maximum value an <code>int</code> can represent is 2147483647 (or + * 2<sup>31</sup> - 1). + */ + public static final int MAX_VALUE = 0x7fffffff; + + /** + * The primitive type <code>int</code> is represented by this + * <code>Class</code> object. + * @since 1.1 + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('I'); + + /** + * The number of bits needed to represent an <code>int</code>. + * @since 1.5 + */ + public static final int SIZE = 32; + + // This caches some Integer values, and is used by boxing + // conversions via valueOf(). We must cache at least -128..127; + // these constants control how much we actually cache. + private static final int MIN_CACHE = -128; + private static final int MAX_CACHE = 127; + private static Integer[] intCache = new Integer[MAX_CACHE - MIN_CACHE + 1]; + + /** + * The immutable value of this Integer. + * + * @serial the wrapped int + */ + private final int value; + + /** + * Create an <code>Integer</code> object representing the value of the + * <code>int</code> argument. + * + * @param value the value to use + */ + public Integer(int value) + { + this.value = value; + } + + /** + * Create an <code>Integer</code> object representing the value of the + * argument after conversion to an <code>int</code>. + * + * @param s the string to convert + * @throws NumberFormatException if the String does not contain an int + * @see #valueOf(String) + */ + public Integer(String s) + { + value = parseInt(s, 10, false); + } + + /** + * Converts the <code>int</code> to a <code>String</code> using + * the specified radix (base). If the radix exceeds + * <code>Character.MIN_RADIX</code> or <code>Character.MAX_RADIX</code>, 10 + * is used instead. If the result is negative, the leading character is + * '-' ('\\u002D'). The remaining characters come from + * <code>Character.forDigit(digit, radix)</code> ('0'-'9','a'-'z'). + * + * @param num the <code>int</code> to convert to <code>String</code> + * @param radix the radix (base) to use in the conversion + * @return the <code>String</code> representation of the argument + */ + public static String toString(int num, int radix) + { + if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) + radix = 10; + + // For negative numbers, print out the absolute value w/ a leading '-'. + // Use an array large enough for a binary number. + char[] buffer = new char[33]; + int i = 33; + boolean isNeg = false; + if (num < 0) + { + isNeg = true; + num = -num; + + // When the value is MIN_VALUE, it overflows when made positive + if (num < 0) + { + buffer[--i] = digits[(int) (-(num + radix) % radix)]; + num = -(num / radix); + } + } + + do + { + buffer[--i] = digits[num % radix]; + num /= radix; + } + while (num > 0); + + if (isNeg) + buffer[--i] = '-'; + + // Package constructor avoids an array copy. + return new String(buffer, i, 33 - i, true); + } + + /** + * Converts the <code>int</code> to a <code>String</code> assuming it is + * unsigned in base 16. + * + * @param i the <code>int</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toHexString(int i) + { + return toUnsignedString(i, 4); + } + + /** + * Converts the <code>int</code> to a <code>String</code> assuming it is + * unsigned in base 8. + * + * @param i the <code>int</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toOctalString(int i) + { + return toUnsignedString(i, 3); + } + + /** + * Converts the <code>int</code> to a <code>String</code> assuming it is + * unsigned in base 2. + * + * @param i the <code>int</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toBinaryString(int i) + { + return toUnsignedString(i, 1); + } + + /** + * Converts the <code>int</code> to a <code>String</code> and assumes + * a radix of 10. + * + * @param i the <code>int</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + * @see #toString(int, int) + */ + public static String toString(int i) + { + // This is tricky: in libgcj, String.valueOf(int) is a fast native + // implementation. In Classpath it just calls back to + // Integer.toString(int, int). + return String.valueOf(i); + } + + /** + * Converts the specified <code>String</code> into an <code>int</code> + * using the specified radix (base). The string must not be <code>null</code> + * or empty. It may begin with an optional '-', which will negate the answer, + * provided that there are also valid digits. Each digit is parsed as if by + * <code>Character.digit(d, radix)</code>, and must be in the range + * <code>0</code> to <code>radix - 1</code>. Finally, the result must be + * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive. + * Unlike Double.parseDouble, you may not have a leading '+'. + * + * @param str the <code>String</code> to convert + * @param radix the radix (base) to use in the conversion + * @return the <code>String</code> argument converted to <code>int</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as an + * <code>int</code> + */ + public static int parseInt(String str, int radix) + { + return parseInt(str, radix, false); + } + + /** + * Converts the specified <code>String</code> into an <code>int</code>. + * This function assumes a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the <code>int</code> value of <code>s</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as an + * <code>int</code> + * @see #parseInt(String, int) + */ + public static int parseInt(String s) + { + return parseInt(s, 10, false); + } + + /** + * Creates a new <code>Integer</code> object using the <code>String</code> + * and specified radix (base). + * + * @param s the <code>String</code> to convert + * @param radix the radix (base) to convert with + * @return the new <code>Integer</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as an + * <code>int</code> + * @see #parseInt(String, int) + */ + public static Integer valueOf(String s, int radix) + { + return new Integer(parseInt(s, radix, false)); + } + + /** + * Creates a new <code>Integer</code> object using the <code>String</code>, + * assuming a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the new <code>Integer</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as an + * <code>int</code> + * @see #Integer(String) + * @see #parseInt(String) + */ + public static Integer valueOf(String s) + { + return new Integer(parseInt(s, 10, false)); + } + + /** + * Returns an <code>Integer</code> object wrapping the value. + * In contrast to the <code>Integer</code> constructor, this method + * will cache some values. It is used by boxing conversion. + * + * @param val the value to wrap + * @return the <code>Integer</code> + */ + public static Integer valueOf(int val) + { + if (val < MIN_CACHE || val > MAX_CACHE) + return new Integer(val); + synchronized (intCache) + { + if (intCache[val - MIN_CACHE] == null) + intCache[val - MIN_CACHE] = new Integer(val); + return intCache[val - MIN_CACHE]; + } + } + + /** + * Return the value of this <code>Integer</code> as a <code>byte</code>. + * + * @return the byte value + */ + public byte byteValue() + { + return (byte) value; + } + + /** + * Return the value of this <code>Integer</code> as a <code>short</code>. + * + * @return the short value + */ + public short shortValue() + { + return (short) value; + } + + /** + * Return the value of this <code>Integer</code>. + * @return the int value + */ + public int intValue() + { + return value; + } + + /** + * Return the value of this <code>Integer</code> as a <code>long</code>. + * + * @return the long value + */ + public long longValue() + { + return value; + } + + /** + * Return the value of this <code>Integer</code> as a <code>float</code>. + * + * @return the float value + */ + public float floatValue() + { + return value; + } + + /** + * Return the value of this <code>Integer</code> as a <code>double</code>. + * + * @return the double value + */ + public double doubleValue() + { + return value; + } + + /** + * Converts the <code>Integer</code> value to a <code>String</code> and + * assumes a radix of 10. + * + * @return the <code>String</code> representation + */ + public String toString() + { + return String.valueOf(value); + } + + /** + * Return a hashcode representing this Object. <code>Integer</code>'s hash + * code is simply its value. + * + * @return this Object's hash code + */ + public int hashCode() + { + return value; + } + + /** + * Returns <code>true</code> if <code>obj</code> is an instance of + * <code>Integer</code> and represents the same int value. + * + * @param obj the object to compare + * @return whether these Objects are semantically equal + */ + public boolean equals(Object obj) + { + return obj instanceof Integer && value == ((Integer) obj).value; + } + + /** + * Get the specified system property as an <code>Integer</code>. The + * <code>decode()</code> method will be used to interpret the value of + * the property. + * + * @param nm the name of the system property + * @return the system property as an <code>Integer</code>, or null if the + * property is not found or cannot be decoded + * @throws SecurityException if accessing the system property is forbidden + * @see System#getProperty(String) + * @see #decode(String) + */ + public static Integer getInteger(String nm) + { + return getInteger(nm, null); + } + + /** + * Get the specified system property as an <code>Integer</code>, or use a + * default <code>int</code> value if the property is not found or is not + * decodable. The <code>decode()</code> method will be used to interpret + * the value of the property. + * + * @param nm the name of the system property + * @param val the default value + * @return the value of the system property, or the default + * @throws SecurityException if accessing the system property is forbidden + * @see System#getProperty(String) + * @see #decode(String) + */ + public static Integer getInteger(String nm, int val) + { + Integer result = getInteger(nm, null); + return result == null ? new Integer(val) : result; + } + + /** + * Get the specified system property as an <code>Integer</code>, or use a + * default <code>Integer</code> value if the property is not found or is + * not decodable. The <code>decode()</code> method will be used to + * interpret the value of the property. + * + * @param nm the name of the system property + * @param def the default value + * @return the value of the system property, or the default + * @throws SecurityException if accessing the system property is forbidden + * @see System#getProperty(String) + * @see #decode(String) + */ + public static Integer getInteger(String nm, Integer def) + { + if (nm == null || "".equals(nm)) + return def; + nm = System.getProperty(nm); + if (nm == null) + return def; + try + { + return decode(nm); + } + catch (NumberFormatException e) + { + return def; + } + } + + /** + * Convert the specified <code>String</code> into an <code>Integer</code>. + * The <code>String</code> may represent decimal, hexadecimal, or + * octal numbers. + * + * <p>The extended BNF grammar is as follows:<br> + * <pre> + * <em>DecodableString</em>: + * ( [ <code>-</code> ] <em>DecimalNumber</em> ) + * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code> + * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } ) + * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } ) + * <em>DecimalNumber</em>: + * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> } + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 10) has value 0 to 9</em> + * <em>OctalDigit</em>: + * <em>Character.digit(d, 8) has value 0 to 7</em> + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 16) has value 0 to 15</em> + * </pre> + * Finally, the value must be in the range <code>MIN_VALUE</code> to + * <code>MAX_VALUE</code>, or an exception is thrown. + * + * @param str the <code>String</code> to interpret + * @return the value of the String as an <code>Integer</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>int</code> + * @throws NullPointerException if <code>s</code> is null + * @since 1.2 + */ + public static Integer decode(String str) + { + return new Integer(parseInt(str, 10, true)); + } + + /** + * Compare two Integers numerically by comparing their <code>int</code> + * values. The result is positive if the first is greater, negative if the + * second is greater, and 0 if the two are equal. + * + * @param i the Integer to compare + * @return the comparison + * @since 1.2 + */ + public int compareTo(Integer i) + { + if (value == i.value) + return 0; + // Returns just -1 or 1 on inequality; doing math might overflow. + return value > i.value ? 1 : -1; + } + + /** + * Behaves like <code>compareTo(Integer)</code> unless the Object + * is not an <code>Integer</code>. + * + * @param o the object to compare + * @return the comparison + * @throws ClassCastException if the argument is not an <code>Integer</code> + * @see #compareTo(Integer) + * @see Comparable + * @since 1.2 + */ + public int compareTo(Object o) + { + return compareTo((Integer) o); + } + + /** + * Return the number of bits set in x. + * @param x value to examine + * @since 1.5 + */ + public static int bitCount(int x) + { + // Successively collapse alternating bit groups into a sum. + x = ((x >> 1) & 0x55555555) + (x & 0x55555555); + x = ((x >> 2) & 0x33333333) + (x & 0x33333333); + x = ((x >> 4) & 0x0f0f0f0f) + (x & 0x0f0f0f0f); + x = ((x >> 8) & 0x00ff00ff) + (x & 0x00ff00ff); + return ((x >> 16) & 0x0000ffff) + (x & 0x0000ffff); + } + + /** + * Rotate x to the left by distance bits. + * @param x the value to rotate + * @param distance the number of bits by which to rotate + * @since 1.5 + */ + public static int rotateLeft(int x, int distance) + { + // This trick works because the shift operators implicitly mask + // the shift count. + return (x << distance) | (x >>> - distance); + } + + /** + * Rotate x to the right by distance bits. + * @param x the value to rotate + * @param distance the number of bits by which to rotate + * @since 1.5 + */ + public static int rotateRight(int x, int distance) + { + // This trick works because the shift operators implicitly mask + // the shift count. + return (x << - distance) | (x >>> distance); + } + + /** + * Find the highest set bit in value, and return a new value + * with only that bit set. + * @param value the value to examine + * @since 1.5 + */ + public static int highestOneBit(int value) + { + value |= value >>> 1; + value |= value >>> 2; + value |= value >>> 4; + value |= value >>> 8; + value |= value >>> 16; + return value ^ (value >>> 1); + } + + /** + * Return the number of leading zeros in value. + * @param value the value to examine + * @since 1.5 + */ + public static int numberOfLeadingZeros(int value) + { + value |= value >>> 1; + value |= value >>> 2; + value |= value >>> 4; + value |= value >>> 8; + value |= value >>> 16; + return bitCount(~value); + } + + /** + * Find the lowest set bit in value, and return a new value + * with only that bit set. + * @param value the value to examine + * @since 1.5 + */ + public static int lowestOneBit(int value) + { + // Classic assembly trick. + return value & - value; + } + + /** + * Find the number of trailing zeros in value. + * @param value the value to examine + * @since 1.5 + */ + public static int numberOfTrailingZeros(int value) + { + return bitCount((value & -value) - 1); + } + + /** + * Return 1 if x is positive, -1 if it is negative, and 0 if it is + * zero. + * @param x the value to examine + * @since 1.5 + */ + public static int signum(int x) + { + return x < 0 ? -1 : (x > 0 ? 1 : 0); + } + + /** + * Reverse the bytes in val. + * @since 1.5 + */ + public static int reverseBytes(int val) + { + return ( ((val >> 24) & 0xff) + | ((val >> 8) & 0xff00) + | ((val << 8) & 0xff0000) + | ((val << 24) & 0xff000000)); + } + + /** + * Reverse the bits in val. + * @since 1.5 + */ + public static int reverse(int val) + { + // Successively swap alternating bit groups. + val = ((val >> 1) & 0x55555555) + ((val << 1) & ~0x55555555); + val = ((val >> 2) & 0x33333333) + ((val << 2) & ~0x33333333); + val = ((val >> 4) & 0x0f0f0f0f) + ((val << 4) & ~0x0f0f0f0f); + val = ((val >> 8) & 0x00ff00ff) + ((val << 8) & ~0x00ff00ff); + return ((val >> 16) & 0x0000ffff) + ((val << 16) & ~0x0000ffff); + } + + /** + * Helper for converting unsigned numbers to String. + * + * @param num the number + * @param exp log2(digit) (ie. 1, 3, or 4 for binary, oct, hex) + */ + // Package visible for use by Long. + static String toUnsignedString(int num, int exp) + { + // Use an array large enough for a binary number. + int mask = (1 << exp) - 1; + char[] buffer = new char[32]; + int i = 32; + do + { + buffer[--i] = digits[num & mask]; + num >>>= exp; + } + while (num != 0); + + // Package constructor avoids an array copy. + return new String(buffer, i, 32 - i, true); + } + + /** + * Helper for parsing ints, used by Integer, Short, and Byte. + * + * @param str the string to parse + * @param radix the radix to use, must be 10 if decode is true + * @param decode if called from decode + * @return the parsed int value + * @throws NumberFormatException if there is an error + * @throws NullPointerException if decode is true and str if null + * @see #parseInt(String, int) + * @see #decode(String) + * @see Byte#parseInt(String, int) + * @see Short#parseInt(String, int) + */ + static int parseInt(String str, int radix, boolean decode) + { + if (! decode && str == null) + throw new NumberFormatException(); + int index = 0; + int len = str.length(); + boolean isNeg = false; + if (len == 0) + throw new NumberFormatException(); + int ch = str.charAt(index); + if (ch == '-') + { + if (len == 1) + throw new NumberFormatException(); + isNeg = true; + ch = str.charAt(++index); + } + if (decode) + { + if (ch == '0') + { + if (++index == len) + return 0; + if ((str.charAt(index) & ~('x' ^ 'X')) == 'X') + { + radix = 16; + index++; + } + else + radix = 8; + } + else if (ch == '#') + { + radix = 16; + index++; + } + } + if (index == len) + throw new NumberFormatException(); + + int max = MAX_VALUE / radix; + // We can't directly write `max = (MAX_VALUE + 1) / radix'. + // So instead we fake it. + if (isNeg && MAX_VALUE % radix == radix - 1) + ++max; + + int val = 0; + while (index < len) + { + if (val < 0 || val > max) + throw new NumberFormatException(); + + ch = Character.digit(str.charAt(index++), radix); + val = val * radix + ch; + if (ch < 0 || (val < 0 && (! isNeg || val != MIN_VALUE))) + throw new NumberFormatException(); + } + return isNeg ? -val : val; + } +} diff --git a/libjava/classpath/java/lang/InternalError.java b/libjava/classpath/java/lang/InternalError.java new file mode 100644 index 0000000..3a95bbea --- /dev/null +++ b/libjava/classpath/java/lang/InternalError.java @@ -0,0 +1,72 @@ +/* InternalError.java -- thrown when the VM encounters an internal error + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>InternalError</code> is thrown when a mystical error has + * occurred in the Java Virtual Machine. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class InternalError extends VirtualMachineError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -9062593416125562365L; + + /** + * Create an error without a message. + */ + public InternalError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public InternalError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/InterruptedException.java b/libjava/classpath/java/lang/InterruptedException.java new file mode 100644 index 0000000..da2173c --- /dev/null +++ b/libjava/classpath/java/lang/InterruptedException.java @@ -0,0 +1,80 @@ +/* InterruptedException.java -- thrown when a thread is interrupted + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when a thread interrupts another thread which was previously + * sleeping, waiting, or paused in some other way. See the + * <code>interrupt</code> method of class <code>Thread</code>. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @see Object#wait() + * @see Object#wait(long) + * @see Object#wait(long, int) + * @see Thread#sleep(long) + * @see Thread#interrupt() + * @see Thread#interrupted() + * @status updated to 1.4 + */ +public class InterruptedException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 6700697376100628473L; + + /** + * Create an exception without a message. + */ + public InterruptedException() + { + } + + /** + * Create an exception with a message. + * + * + * @param s the message + */ + public InterruptedException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/LinkageError.java b/libjava/classpath/java/lang/LinkageError.java new file mode 100644 index 0000000..0287020 --- /dev/null +++ b/libjava/classpath/java/lang/LinkageError.java @@ -0,0 +1,74 @@ +/* LinkageError.java -- thrown when classes valid at separate compile times + cannot be linked to each other + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Subclasses of <code>LinkageError</code> are thrown to indicate that two + * classes which were compatible at separate compilation times cannot be + * linked to one another. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class LinkageError extends Error +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 3579600108157160122L; + + /** + * Create an error without a message. + */ + public LinkageError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public LinkageError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Long.java b/libjava/classpath/java/lang/Long.java new file mode 100644 index 0000000..703eab8 --- /dev/null +++ b/libjava/classpath/java/lang/Long.java @@ -0,0 +1,614 @@ +/* Long.java -- object wrapper for long + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Instances of class <code>Long</code> represent primitive + * <code>long</code> values. + * + * Additionally, this class provides various helper functions and variables + * related to longs. + * + * @author Paul Fisher + * @author John Keiser + * @author Warren Levy + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public final class Long extends Number implements Comparable +{ + /** + * Compatible with JDK 1.0.2+. + */ + private static final long serialVersionUID = 4290774380558885855L; + + /** + * The minimum value a <code>long</code> can represent is + * -9223372036854775808L (or -2<sup>63</sup>). + */ + public static final long MIN_VALUE = 0x8000000000000000L; + + /** + * The maximum value a <code>long</code> can represent is + * 9223372036854775807 (or 2<sup>63</sup> - 1). + */ + public static final long MAX_VALUE = 0x7fffffffffffffffL; + + /** + * The primitive type <code>long</code> is represented by this + * <code>Class</code> object. + * @since 1.1 + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass ('J'); + + /** + * The immutable value of this Long. + * + * @serial the wrapped long + */ + private final long value; + + /** + * Create a <code>Long</code> object representing the value of the + * <code>long</code> argument. + * + * @param value the value to use + */ + public Long(long value) + { + this.value = value; + } + + /** + * Create a <code>Long</code> object representing the value of the + * argument after conversion to a <code>long</code>. + * + * @param s the string to convert + * @throws NumberFormatException if the String does not contain a long + * @see #valueOf(String) + */ + public Long(String s) + { + value = parseLong(s, 10, false); + } + + /** + * Converts the <code>long</code> to a <code>String</code> using + * the specified radix (base). If the radix exceeds + * <code>Character.MIN_RADIX</code> or <code>Character.MAX_RADIX</code>, 10 + * is used instead. If the result is negative, the leading character is + * '-' ('\\u002D'). The remaining characters come from + * <code>Character.forDigit(digit, radix)</code> ('0'-'9','a'-'z'). + * + * @param num the <code>long</code> to convert to <code>String</code> + * @param radix the radix (base) to use in the conversion + * @return the <code>String</code> representation of the argument + */ + public static String toString(long num, int radix) + { + // Use the Integer toString for efficiency if possible. + if ((int) num == num) + return Integer.toString((int) num, radix); + + if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) + radix = 10; + + // For negative numbers, print out the absolute value w/ a leading '-'. + // Use an array large enough for a binary number. + char[] buffer = new char[65]; + int i = 65; + boolean isNeg = false; + if (num < 0) + { + isNeg = true; + num = -num; + + // When the value is MIN_VALUE, it overflows when made positive + if (num < 0) + { + buffer[--i] = digits[(int) (-(num + radix) % radix)]; + num = -(num / radix); + } + } + + do + { + buffer[--i] = digits[(int) (num % radix)]; + num /= radix; + } + while (num > 0); + + if (isNeg) + buffer[--i] = '-'; + + // Package constructor avoids an array copy. + return new String(buffer, i, 65 - i, true); + } + + /** + * Converts the <code>long</code> to a <code>String</code> assuming it is + * unsigned in base 16. + * + * @param l the <code>long</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toHexString(long l) + { + return toUnsignedString(l, 4); + } + + /** + * Converts the <code>long</code> to a <code>String</code> assuming it is + * unsigned in base 8. + * + * @param l the <code>long</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toOctalString(long l) + { + return toUnsignedString(l, 3); + } + + /** + * Converts the <code>long</code> to a <code>String</code> assuming it is + * unsigned in base 2. + * + * @param l the <code>long</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toBinaryString(long l) + { + return toUnsignedString(l, 1); + } + + /** + * Converts the <code>long</code> to a <code>String</code> and assumes + * a radix of 10. + * + * @param num the <code>long</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + * @see #toString(long, int) + */ + public static String toString(long num) + { + return toString(num, 10); + } + + /** + * Converts the specified <code>String</code> into an <code>int</code> + * using the specified radix (base). The string must not be <code>null</code> + * or empty. It may begin with an optional '-', which will negate the answer, + * provided that there are also valid digits. Each digit is parsed as if by + * <code>Character.digit(d, radix)</code>, and must be in the range + * <code>0</code> to <code>radix - 1</code>. Finally, the result must be + * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive. + * Unlike Double.parseDouble, you may not have a leading '+'; and 'l' or + * 'L' as the last character is only valid in radices 22 or greater, where + * it is a digit and not a type indicator. + * + * @param str the <code>String</code> to convert + * @param radix the radix (base) to use in the conversion + * @return the <code>String</code> argument converted to <code>long</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>long</code> + */ + public static long parseLong(String str, int radix) + { + return parseLong(str, radix, false); + } + + /** + * Converts the specified <code>String</code> into a <code>long</code>. + * This function assumes a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the <code>int</code> value of <code>s</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>long</code> + * @see #parseLong(String, int) + */ + public static long parseLong(String s) + { + return parseLong(s, 10, false); + } + + /** + * Creates a new <code>Long</code> object using the <code>String</code> + * and specified radix (base). + * + * @param s the <code>String</code> to convert + * @param radix the radix (base) to convert with + * @return the new <code>Long</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>long</code> + * @see #parseLong(String, int) + */ + public static Long valueOf(String s, int radix) + { + return new Long(parseLong(s, radix, false)); + } + + /** + * Creates a new <code>Long</code> object using the <code>String</code>, + * assuming a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the new <code>Long</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>long</code> + * @see #Long(String) + * @see #parseLong(String) + */ + public static Long valueOf(String s) + { + return new Long(parseLong(s, 10, false)); + } + + /** + * Convert the specified <code>String</code> into a <code>Long</code>. + * The <code>String</code> may represent decimal, hexadecimal, or + * octal numbers. + * + * <p>The extended BNF grammar is as follows:<br> + * <pre> + * <em>DecodableString</em>: + * ( [ <code>-</code> ] <em>DecimalNumber</em> ) + * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code> + * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } ) + * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } ) + * <em>DecimalNumber</em>: + * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> } + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 10) has value 0 to 9</em> + * <em>OctalDigit</em>: + * <em>Character.digit(d, 8) has value 0 to 7</em> + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 16) has value 0 to 15</em> + * </pre> + * Finally, the value must be in the range <code>MIN_VALUE</code> to + * <code>MAX_VALUE</code>, or an exception is thrown. Note that you cannot + * use a trailing 'l' or 'L', unlike in Java source code. + * + * @param str the <code>String</code> to interpret + * @return the value of the String as a <code>Long</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>long</code> + * @throws NullPointerException if <code>s</code> is null + * @since 1.2 + */ + public static Long decode(String str) + { + return new Long(parseLong(str, 10, true)); + } + + /** + * Return the value of this <code>Long</code> as a <code>byte</code>. + * + * @return the byte value + */ + public byte byteValue() + { + return (byte) value; + } + + /** + * Return the value of this <code>Long</code> as a <code>short</code>. + * + * @return the short value + */ + public short shortValue() + { + return (short) value; + } + + /** + * Return the value of this <code>Long</code> as an <code>int</code>. + * + * @return the int value + */ + public int intValue() + { + return (int) value; + } + + /** + * Return the value of this <code>Long</code>. + * + * @return the long value + */ + public long longValue() + { + return value; + } + + /** + * Return the value of this <code>Long</code> as a <code>float</code>. + * + * @return the float value + */ + public float floatValue() + { + return value; + } + + /** + * Return the value of this <code>Long</code> as a <code>double</code>. + * + * @return the double value + */ + public double doubleValue() + { + return value; + } + + /** + * Converts the <code>Long</code> value to a <code>String</code> and + * assumes a radix of 10. + * + * @return the <code>String</code> representation + */ + public String toString() + { + return toString(value, 10); + } + + /** + * Return a hashcode representing this Object. <code>Long</code>'s hash + * code is calculated by <code>(int) (value ^ (value >> 32))</code>. + * + * @return this Object's hash code + */ + public int hashCode() + { + return (int) (value ^ (value >>> 32)); + } + + /** + * Returns <code>true</code> if <code>obj</code> is an instance of + * <code>Long</code> and represents the same long value. + * + * @param obj the object to compare + * @return whether these Objects are semantically equal + */ + public boolean equals(Object obj) + { + return obj instanceof Long && value == ((Long) obj).value; + } + + /** + * Get the specified system property as a <code>Long</code>. The + * <code>decode()</code> method will be used to interpret the value of + * the property. + * + * @param nm the name of the system property + * @return the system property as a <code>Long</code>, or null if the + * property is not found or cannot be decoded + * @throws SecurityException if accessing the system property is forbidden + * @see System#getProperty(String) + * @see #decode(String) + */ + public static Long getLong(String nm) + { + return getLong(nm, null); + } + + /** + * Get the specified system property as a <code>Long</code>, or use a + * default <code>long</code> value if the property is not found or is not + * decodable. The <code>decode()</code> method will be used to interpret + * the value of the property. + * + * @param nm the name of the system property + * @param val the default value + * @return the value of the system property, or the default + * @throws SecurityException if accessing the system property is forbidden + * @see System#getProperty(String) + * @see #decode(String) + */ + public static Long getLong(String nm, long val) + { + Long result = getLong(nm, null); + return result == null ? new Long(val) : result; + } + + /** + * Get the specified system property as a <code>Long</code>, or use a + * default <code>Long</code> value if the property is not found or is + * not decodable. The <code>decode()</code> method will be used to + * interpret the value of the property. + * + * @param nm the name of the system property + * @param def the default value + * @return the value of the system property, or the default + * @throws SecurityException if accessing the system property is forbidden + * @see System#getProperty(String) + * @see #decode(String) + */ + public static Long getLong(String nm, Long def) + { + if (nm == null || "".equals(nm)) + return def; + nm = System.getProperty(nm); + if (nm == null) + return def; + try + { + return decode(nm); + } + catch (NumberFormatException e) + { + return def; + } + } + + /** + * Compare two Longs numerically by comparing their <code>long</code> + * values. The result is positive if the first is greater, negative if the + * second is greater, and 0 if the two are equal. + * + * @param l the Long to compare + * @return the comparison + * @since 1.2 + */ + public int compareTo(Long l) + { + if (value == l.value) + return 0; + // Returns just -1 or 1 on inequality; doing math might overflow the long. + return value > l.value ? 1 : -1; + } + + /** + * Behaves like <code>compareTo(Long)</code> unless the Object + * is not a <code>Long</code>. + * + * @param o the object to compare + * @return the comparison + * @throws ClassCastException if the argument is not a <code>Long</code> + * @see #compareTo(Long) + * @see Comparable + * @since 1.2 + */ + public int compareTo(Object o) + { + return compareTo((Long) o); + } + + /** + * Helper for converting unsigned numbers to String. + * + * @param num the number + * @param exp log2(digit) (ie. 1, 3, or 4 for binary, oct, hex) + */ + private static String toUnsignedString(long num, int exp) + { + // Use the Integer toUnsignedString for efficiency if possible. + // If NUM<0 then this particular optimization doesn't work + // properly. + if (num >= 0 && (int) num == num) + return Integer.toUnsignedString((int) num, exp); + + // Use an array large enough for a binary number. + int mask = (1 << exp) - 1; + char[] buffer = new char[64]; + int i = 64; + do + { + buffer[--i] = digits[(int) num & mask]; + num >>>= exp; + } + while (num != 0); + + // Package constructor avoids an array copy. + return new String(buffer, i, 64 - i, true); + } + + /** + * Helper for parsing longs. + * + * @param str the string to parse + * @param radix the radix to use, must be 10 if decode is true + * @param decode if called from decode + * @return the parsed long value + * @throws NumberFormatException if there is an error + * @throws NullPointerException if decode is true and str is null + * @see #parseLong(String, int) + * @see #decode(String) + */ + private static long parseLong(String str, int radix, boolean decode) + { + if (! decode && str == null) + throw new NumberFormatException(); + int index = 0; + int len = str.length(); + boolean isNeg = false; + if (len == 0) + throw new NumberFormatException(); + int ch = str.charAt(index); + if (ch == '-') + { + if (len == 1) + throw new NumberFormatException(); + isNeg = true; + ch = str.charAt(++index); + } + if (decode) + { + if (ch == '0') + { + if (++index == len) + return 0; + if ((str.charAt(index) & ~('x' ^ 'X')) == 'X') + { + radix = 16; + index++; + } + else + radix = 8; + } + else if (ch == '#') + { + radix = 16; + index++; + } + } + if (index == len) + throw new NumberFormatException(); + + long max = MAX_VALUE / radix; + // We can't directly write `max = (MAX_VALUE + 1) / radix'. + // So instead we fake it. + if (isNeg && MAX_VALUE % radix == radix - 1) + ++max; + + long val = 0; + while (index < len) + { + if (val < 0 || val > max) + throw new NumberFormatException(); + + ch = Character.digit(str.charAt(index++), radix); + val = val * radix + ch; + if (ch < 0 || (val < 0 && (! isNeg || val != MIN_VALUE))) + throw new NumberFormatException(); + } + return isNeg ? -val : val; + } +} diff --git a/libjava/classpath/java/lang/Math.java b/libjava/classpath/java/lang/Math.java new file mode 100644 index 0000000..08081e2 --- /dev/null +++ b/libjava/classpath/java/lang/Math.java @@ -0,0 +1,650 @@ +/* java.lang.Math -- common mathematical functions, native allowed + Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import gnu.classpath.Configuration; + +import java.util.Random; + +/** + * Helper class containing useful mathematical functions and constants. + * <P> + * + * Note that angles are specified in radians. Conversion functions are + * provided for your convenience. + * + * @author Paul Fisher + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + */ +public final class Math +{ + /** + * Math is non-instantiable + */ + private Math() + { + } + + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javalang"); + } + } + + /** + * A random number generator, initialized on first use. + */ + private static Random rand; + + /** + * The most accurate approximation to the mathematical constant <em>e</em>: + * <code>2.718281828459045</code>. Used in natural log and exp. + * + * @see #log(double) + * @see #exp(double) + */ + public static final double E = 2.718281828459045; + + /** + * The most accurate approximation to the mathematical constant <em>pi</em>: + * <code>3.141592653589793</code>. This is the ratio of a circle's diameter + * to its circumference. + */ + public static final double PI = 3.141592653589793; + + /** + * Take the absolute value of the argument. + * (Absolute value means make it positive.) + * <P> + * + * Note that the the largest negative value (Integer.MIN_VALUE) cannot + * be made positive. In this case, because of the rules of negation in + * a computer, MIN_VALUE is what will be returned. + * This is a <em>negative</em> value. You have been warned. + * + * @param i the number to take the absolute value of + * @return the absolute value + * @see Integer#MIN_VALUE + */ + public static int abs(int i) + { + return (i < 0) ? -i : i; + } + + /** + * Take the absolute value of the argument. + * (Absolute value means make it positive.) + * <P> + * + * Note that the the largest negative value (Long.MIN_VALUE) cannot + * be made positive. In this case, because of the rules of negation in + * a computer, MIN_VALUE is what will be returned. + * This is a <em>negative</em> value. You have been warned. + * + * @param l the number to take the absolute value of + * @return the absolute value + * @see Long#MIN_VALUE + */ + public static long abs(long l) + { + return (l < 0) ? -l : l; + } + + /** + * Take the absolute value of the argument. + * (Absolute value means make it positive.) + * <P> + * + * This is equivalent, but faster than, calling + * <code>Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))</code>. + * + * @param f the number to take the absolute value of + * @return the absolute value + */ + public static float abs(float f) + { + return (f <= 0) ? 0 - f : f; + } + + /** + * Take the absolute value of the argument. + * (Absolute value means make it positive.) + * + * This is equivalent, but faster than, calling + * <code>Double.longBitsToDouble(Double.doubleToLongBits(a) + * << 1) >>> 1);</code>. + * + * @param d the number to take the absolute value of + * @return the absolute value + */ + public static double abs(double d) + { + return (d <= 0) ? 0 - d : d; + } + + /** + * Return whichever argument is smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static int min(int a, int b) + { + return (a < b) ? a : b; + } + + /** + * Return whichever argument is smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static long min(long a, long b) + { + return (a < b) ? a : b; + } + + /** + * Return whichever argument is smaller. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, -0 is always smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static float min(float a, float b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; < will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return -(-a - b); + return (a < b) ? a : b; + } + + /** + * Return whichever argument is smaller. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, -0 is always smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static double min(double a, double b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; < will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return -(-a - b); + return (a < b) ? a : b; + } + + /** + * Return whichever argument is larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static int max(int a, int b) + { + return (a > b) ? a : b; + } + + /** + * Return whichever argument is larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static long max(long a, long b) + { + return (a > b) ? a : b; + } + + /** + * Return whichever argument is larger. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, 0 is always larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static float max(float a, float b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; > will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return a - -b; + return (a > b) ? a : b; + } + + /** + * Return whichever argument is larger. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, 0 is always larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static double max(double a, double b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; > will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return a - -b; + return (a > b) ? a : b; + } + + /** + * The trigonometric function <em>sin</em>. The sine of NaN or infinity is + * NaN, and the sine of 0 retains its sign. This is accurate within 1 ulp, + * and is semi-monotonic. + * + * @param a the angle (in radians) + * @return sin(a) + */ + public static native double sin(double a); + + /** + * The trigonometric function <em>cos</em>. The cosine of NaN or infinity is + * NaN. This is accurate within 1 ulp, and is semi-monotonic. + * + * @param a the angle (in radians) + * @return cos(a) + */ + public static native double cos(double a); + + /** + * The trigonometric function <em>tan</em>. The tangent of NaN or infinity + * is NaN, and the tangent of 0 retains its sign. This is accurate within 1 + * ulp, and is semi-monotonic. + * + * @param a the angle (in radians) + * @return tan(a) + */ + public static native double tan(double a); + + /** + * The trigonometric function <em>arcsin</em>. The range of angles returned + * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN or + * its absolute value is beyond 1, the result is NaN; and the arcsine of + * 0 retains its sign. This is accurate within 1 ulp, and is semi-monotonic. + * + * @param a the sin to turn back into an angle + * @return arcsin(a) + */ + public static native double asin(double a); + + /** + * The trigonometric function <em>arccos</em>. The range of angles returned + * is 0 to pi radians (0 to 180 degrees). If the argument is NaN or + * its absolute value is beyond 1, the result is NaN. This is accurate + * within 1 ulp, and is semi-monotonic. + * + * @param a the cos to turn back into an angle + * @return arccos(a) + */ + public static native double acos(double a); + + /** + * The trigonometric function <em>arcsin</em>. The range of angles returned + * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN, the + * result is NaN; and the arctangent of 0 retains its sign. This is accurate + * within 1 ulp, and is semi-monotonic. + * + * @param a the tan to turn back into an angle + * @return arcsin(a) + * @see #atan2(double, double) + */ + public static native double atan(double a); + + /** + * A special version of the trigonometric function <em>arctan</em>, for + * converting rectangular coordinates <em>(x, y)</em> to polar + * <em>(r, theta)</em>. This computes the arctangent of x/y in the range + * of -pi to pi radians (-180 to 180 degrees). Special cases:<ul> + * <li>If either argument is NaN, the result is NaN.</li> + * <li>If the first argument is positive zero and the second argument is + * positive, or the first argument is positive and finite and the second + * argument is positive infinity, then the result is positive zero.</li> + * <li>If the first argument is negative zero and the second argument is + * positive, or the first argument is negative and finite and the second + * argument is positive infinity, then the result is negative zero.</li> + * <li>If the first argument is positive zero and the second argument is + * negative, or the first argument is positive and finite and the second + * argument is negative infinity, then the result is the double value + * closest to pi.</li> + * <li>If the first argument is negative zero and the second argument is + * negative, or the first argument is negative and finite and the second + * argument is negative infinity, then the result is the double value + * closest to -pi.</li> + * <li>If the first argument is positive and the second argument is + * positive zero or negative zero, or the first argument is positive + * infinity and the second argument is finite, then the result is the + * double value closest to pi/2.</li> + * <li>If the first argument is negative and the second argument is + * positive zero or negative zero, or the first argument is negative + * infinity and the second argument is finite, then the result is the + * double value closest to -pi/2.</li> + * <li>If both arguments are positive infinity, then the result is the + * double value closest to pi/4.</li> + * <li>If the first argument is positive infinity and the second argument + * is negative infinity, then the result is the double value closest to + * 3*pi/4.</li> + * <li>If the first argument is negative infinity and the second argument + * is positive infinity, then the result is the double value closest to + * -pi/4.</li> + * <li>If both arguments are negative infinity, then the result is the + * double value closest to -3*pi/4.</li> + * + * </ul><p>This is accurate within 2 ulps, and is semi-monotonic. To get r, + * use sqrt(x*x+y*y). + * + * @param y the y position + * @param x the x position + * @return <em>theta</em> in the conversion of (x, y) to (r, theta) + * @see #atan(double) + */ + public static native double atan2(double y, double x); + + /** + * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the + * argument is NaN, the result is NaN; if the argument is positive infinity, + * the result is positive infinity; and if the argument is negative + * infinity, the result is positive zero. This is accurate within 1 ulp, + * and is semi-monotonic. + * + * @param a the number to raise to the power + * @return the number raised to the power of <em>e</em> + * @see #log(double) + * @see #pow(double, double) + */ + public static native double exp(double a); + + /** + * Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the + * argument is NaN or negative, the result is NaN; if the argument is + * positive infinity, the result is positive infinity; and if the argument + * is either zero, the result is negative infinity. This is accurate within + * 1 ulp, and is semi-monotonic. + * + * <p>Note that the way to get log<sub>b</sub>(a) is to do this: + * <code>ln(a) / ln(b)</code>. + * + * @param a the number to take the natural log of + * @return the natural log of <code>a</code> + * @see #exp(double) + */ + public static native double log(double a); + + /** + * Take a square root. If the argument is NaN or negative, the result is + * NaN; if the argument is positive infinity, the result is positive + * infinity; and if the result is either zero, the result is the same. + * This is accurate within the limits of doubles. + * + * <p>For other roots, use pow(a, 1 / rootNumber). + * + * @param a the numeric argument + * @return the square root of the argument + * @see #pow(double, double) + */ + public static native double sqrt(double a); + + /** + * Raise a number to a power. Special cases:<ul> + * <li>If the second argument is positive or negative zero, then the result + * is 1.0.</li> + * <li>If the second argument is 1.0, then the result is the same as the + * first argument.</li> + * <li>If the second argument is NaN, then the result is NaN.</li> + * <li>If the first argument is NaN and the second argument is nonzero, + * then the result is NaN.</li> + * <li>If the absolute value of the first argument is greater than 1 and + * the second argument is positive infinity, or the absolute value of the + * first argument is less than 1 and the second argument is negative + * infinity, then the result is positive infinity.</li> + * <li>If the absolute value of the first argument is greater than 1 and + * the second argument is negative infinity, or the absolute value of the + * first argument is less than 1 and the second argument is positive + * infinity, then the result is positive zero.</li> + * <li>If the absolute value of the first argument equals 1 and the second + * argument is infinite, then the result is NaN.</li> + * <li>If the first argument is positive zero and the second argument is + * greater than zero, or the first argument is positive infinity and the + * second argument is less than zero, then the result is positive zero.</li> + * <li>If the first argument is positive zero and the second argument is + * less than zero, or the first argument is positive infinity and the + * second argument is greater than zero, then the result is positive + * infinity.</li> + * <li>If the first argument is negative zero and the second argument is + * greater than zero but not a finite odd integer, or the first argument is + * negative infinity and the second argument is less than zero but not a + * finite odd integer, then the result is positive zero.</li> + * <li>If the first argument is negative zero and the second argument is a + * positive finite odd integer, or the first argument is negative infinity + * and the second argument is a negative finite odd integer, then the result + * is negative zero.</li> + * <li>If the first argument is negative zero and the second argument is + * less than zero but not a finite odd integer, or the first argument is + * negative infinity and the second argument is greater than zero but not a + * finite odd integer, then the result is positive infinity.</li> + * <li>If the first argument is negative zero and the second argument is a + * negative finite odd integer, or the first argument is negative infinity + * and the second argument is a positive finite odd integer, then the result + * is negative infinity.</li> + * <li>If the first argument is less than zero and the second argument is a + * finite even integer, then the result is equal to the result of raising + * the absolute value of the first argument to the power of the second + * argument.</li> + * <li>If the first argument is less than zero and the second argument is a + * finite odd integer, then the result is equal to the negative of the + * result of raising the absolute value of the first argument to the power + * of the second argument.</li> + * <li>If the first argument is finite and less than zero and the second + * argument is finite and not an integer, then the result is NaN.</li> + * <li>If both arguments are integers, then the result is exactly equal to + * the mathematical result of raising the first argument to the power of + * the second argument if that result can in fact be represented exactly as + * a double value.</li> + * + * </ul><p>(In the foregoing descriptions, a floating-point value is + * considered to be an integer if and only if it is a fixed point of the + * method {@link #ceil(double)} or, equivalently, a fixed point of the + * method {@link #floor(double)}. A value is a fixed point of a one-argument + * method if and only if the result of applying the method to the value is + * equal to the value.) This is accurate within 1 ulp, and is semi-monotonic. + * + * @param a the number to raise + * @param b the power to raise it to + * @return a<sup>b</sup> + */ + public static native double pow(double a, double b); + + /** + * Get the IEEE 754 floating point remainder on two numbers. This is the + * value of <code>x - y * <em>n</em></code>, where <em>n</em> is the closest + * double to <code>x / y</code> (ties go to the even n); for a zero + * remainder, the sign is that of <code>x</code>. If either argument is NaN, + * the first argument is infinite, or the second argument is zero, the result + * is NaN; if x is finite but y is infinite, the result is x. This is + * accurate within the limits of doubles. + * + * @param x the dividend (the top half) + * @param y the divisor (the bottom half) + * @return the IEEE 754-defined floating point remainder of x/y + * @see #rint(double) + */ + public static native double IEEEremainder(double x, double y); + + /** + * Take the nearest integer that is that is greater than or equal to the + * argument. If the argument is NaN, infinite, or zero, the result is the + * same; if the argument is between -1 and 0, the result is negative zero. + * Note that <code>Math.ceil(x) == -Math.floor(-x)</code>. + * + * @param a the value to act upon + * @return the nearest integer >= <code>a</code> + */ + public static native double ceil(double a); + + /** + * Take the nearest integer that is that is less than or equal to the + * argument. If the argument is NaN, infinite, or zero, the result is the + * same. Note that <code>Math.ceil(x) == -Math.floor(-x)</code>. + * + * @param a the value to act upon + * @return the nearest integer <= <code>a</code> + */ + public static native double floor(double a); + + /** + * Take the nearest integer to the argument. If it is exactly between + * two integers, the even integer is taken. If the argument is NaN, + * infinite, or zero, the result is the same. + * + * @param a the value to act upon + * @return the nearest integer to <code>a</code> + */ + public static native double rint(double a); + + /** + * Take the nearest integer to the argument. This is equivalent to + * <code>(int) Math.floor(a + 0.5f)</code>. If the argument is NaN, the result + * is 0; otherwise if the argument is outside the range of int, the result + * will be Integer.MIN_VALUE or Integer.MAX_VALUE, as appropriate. + * + * @param a the argument to round + * @return the nearest integer to the argument + * @see Integer#MIN_VALUE + * @see Integer#MAX_VALUE + */ + public static int round(float a) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return 0; + return (int) floor(a + 0.5f); + } + + /** + * Take the nearest long to the argument. This is equivalent to + * <code>(long) Math.floor(a + 0.5)</code>. If the argument is NaN, the + * result is 0; otherwise if the argument is outside the range of long, the + * result will be Long.MIN_VALUE or Long.MAX_VALUE, as appropriate. + * + * @param a the argument to round + * @return the nearest long to the argument + * @see Long#MIN_VALUE + * @see Long#MAX_VALUE + */ + public static long round(double a) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return 0; + return (long) floor(a + 0.5d); + } + + /** + * Get a random number. This behaves like Random.nextDouble(), seeded by + * System.currentTimeMillis() when first called. In other words, the number + * is from a pseudorandom sequence, and lies in the range [+0.0, 1.0). + * This random sequence is only used by this method, and is threadsafe, + * although you may want your own random number generator if it is shared + * among threads. + * + * @return a random number + * @see Random#nextDouble() + * @see System#currentTimeMillis() + */ + public static synchronized double random() + { + if (rand == null) + rand = new Random(); + return rand.nextDouble(); + } + + /** + * Convert from degrees to radians. The formula for this is + * radians = degrees * (pi/180); however it is not always exact given the + * limitations of floating point numbers. + * + * @param degrees an angle in degrees + * @return the angle in radians + * @since 1.2 + */ + public static double toRadians(double degrees) + { + return (degrees * PI) / 180; + } + + /** + * Convert from radians to degrees. The formula for this is + * degrees = radians * (180/pi); however it is not always exact given the + * limitations of floating point numbers. + * + * @param rads an angle in radians + * @return the angle in degrees + * @since 1.2 + */ + public static double toDegrees(double rads) + { + return (rads * 180) / PI; + } +} diff --git a/libjava/classpath/java/lang/NegativeArraySizeException.java b/libjava/classpath/java/lang/NegativeArraySizeException.java new file mode 100644 index 0000000..fcfa52e --- /dev/null +++ b/libjava/classpath/java/lang/NegativeArraySizeException.java @@ -0,0 +1,77 @@ +/* NegativeArraySizeException.java -- thrown on attempt to create array + with a negative size + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when an attempt is made to create an array with a negative + * size. For example:<br> + * <pre> + * int i = -1; + * int[] array = new int[i]; + * </pre> + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class NegativeArraySizeException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -8960118058596991861L; + + /** + * Create an exception without a message. + */ + public NegativeArraySizeException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public NegativeArraySizeException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/NoClassDefFoundError.java b/libjava/classpath/java/lang/NoClassDefFoundError.java new file mode 100644 index 0000000..7e8e6ca --- /dev/null +++ b/libjava/classpath/java/lang/NoClassDefFoundError.java @@ -0,0 +1,76 @@ +/* NoClassDefFoundError.java -- thrown when a ClassLoader cannot find a class + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>NoClassDefFoundError</code> is thrown when a classloader or the + * Java Virtual Machine tries to load a class and no definition of the class + * can be found. This could happen when using the <code>new</code> expression + * or during a normal method call. The reason this would occur at runtime is + * because the missing class definition existed when the currently executing + * class was compiled, but now that definition cannot be found. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class NoClassDefFoundError extends LinkageError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 9095859863287012458L; + + /** + * Create an error without a message. + */ + public NoClassDefFoundError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public NoClassDefFoundError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/NoSuchFieldError.java b/libjava/classpath/java/lang/NoSuchFieldError.java new file mode 100644 index 0000000..af42e35 --- /dev/null +++ b/libjava/classpath/java/lang/NoSuchFieldError.java @@ -0,0 +1,74 @@ +/* NoSuchFieldError.java -- thrown when the linker does not find a field + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>NoSuchFieldError</code> is thrown if an application attempts + * to access a field of a class, and that class no longer has that field. + * This is normally detected by the compiler, so it signals that you are + * using binary incompatible class versions. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class NoSuchFieldError extends IncompatibleClassChangeError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -3456430195886129035L; + + /** + * Create an error without a message. + */ + public NoSuchFieldError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public NoSuchFieldError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/NoSuchFieldException.java b/libjava/classpath/java/lang/NoSuchFieldException.java new file mode 100644 index 0000000..74d52d1 --- /dev/null +++ b/libjava/classpath/java/lang/NoSuchFieldException.java @@ -0,0 +1,73 @@ +/* NoSuchFieldException.java -- thrown when reflecting a non-existant field + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown to indicate the class does not have the specified field. This is + * caused by a variety of reflection methods, when looking up a field by name. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @since 1.1 + * @status updated to 1.4 + */ +public class NoSuchFieldException extends Exception +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -6143714805279938260L; + + /** + * Create an exception without a message. + */ + public NoSuchFieldException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public NoSuchFieldException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/NoSuchMethodError.java b/libjava/classpath/java/lang/NoSuchMethodError.java new file mode 100644 index 0000000..2bda776 --- /dev/null +++ b/libjava/classpath/java/lang/NoSuchMethodError.java @@ -0,0 +1,74 @@ +/* NoSuchMethodError.java -- thrown when the linker does not find a method + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>NoSuchMethodError</code> is thrown if an application attempts + * to access a method of a class, and that class no longer has that method. + * This is normally detected by the compiler, so it signals that you are + * using binary incompatible class versions. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class NoSuchMethodError extends IncompatibleClassChangeError +{ + /** + * Compatible with JDK 1.0+. + */ + static final long serialVersionUID = -3765521442372831335L; + + /** + * Create an error without a message. + */ + public NoSuchMethodError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public NoSuchMethodError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/NoSuchMethodException.java b/libjava/classpath/java/lang/NoSuchMethodException.java new file mode 100644 index 0000000..e423efb --- /dev/null +++ b/libjava/classpath/java/lang/NoSuchMethodException.java @@ -0,0 +1,72 @@ +/* NoSuchMethodException.java -- thrown when reflecting a non-existant method + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown to indicate the class does not have the specified method. This is + * caused by a variety of reflection methods, when looking up a method by name. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class NoSuchMethodException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 5034388446362600923L; + + /** + * Create an exception without a message. + */ + public NoSuchMethodException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public NoSuchMethodException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/NullPointerException.java b/libjava/classpath/java/lang/NullPointerException.java new file mode 100644 index 0000000..29a4ee0 --- /dev/null +++ b/libjava/classpath/java/lang/NullPointerException.java @@ -0,0 +1,82 @@ +/* NullPointerException.java -- thrown when using null instead of an object + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when attempting to use <code>null</code> where an object + * is required. The Virtual Machine automatically throws this exception + * for the following:<br><ul> + * <li>Calling an instance method on a null object</li> + * <li>Accessing or modifying a field of a null object</li> + * <li>Taking the array length of a null array</li> + * <li>Accessing or modifying the slots of a null array</li> + * <li>Throwing a null Throwable</li> + * <li>Synchronizing on a null object</li> + * </ul> + * <p>Applications should also throw NullPointerExceptions whenever + * <code>null</code> is an inappropriate parameter to a method. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class NullPointerException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 5162710183389028792L; + + /** + * Create an exception without a message. + */ + public NullPointerException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public NullPointerException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Number.java b/libjava/classpath/java/lang/Number.java new file mode 100644 index 0000000..eb81f78 --- /dev/null +++ b/libjava/classpath/java/lang/Number.java @@ -0,0 +1,131 @@ +/* Number.java =- abstract superclass of numeric objects + Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.io.Serializable; + +/** + * Number is a generic superclass of all the numeric classes, including + * the wrapper classes {@link Byte}, {@link Short}, {@link Integer}, + * {@link Long}, {@link Float}, and {@link Double}. Also worth mentioning + * are the classes in {@link java.math}. + * + * It provides ways to convert numeric objects to any primitive. + * + * @author Paul Fisher + * @author John Keiser + * @author Warren Levy + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public abstract class Number implements Serializable +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = -8742448824652078965L; + + /** + * Table for calculating digits, used in Character, Long, and Integer. + */ + static final char[] digits = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + 'u', 'v', 'w', 'x', 'y', 'z', + }; + + /** + * The basic constructor (often called implicitly). + */ + public Number() + { + } + + /** + * Return the value of this <code>Number</code> as an <code>int</code>. + * + * @return the int value + */ + public abstract int intValue(); + + /** + * Return the value of this <code>Number</code> as a <code>long</code>. + * + * @return the long value + */ + public abstract long longValue(); + + /** + * Return the value of this <code>Number</code> as a <code>float</code>. + * + * @return the float value + */ + public abstract float floatValue(); + + /** + * Return the value of this <code>Number</code> as a <code>float</code>. + * + * @return the double value + */ + public abstract double doubleValue(); + + /** + * Return the value of this <code>Number</code> as a <code>byte</code>. + * + * @return the byte value + * @since 1.1 + */ + public byte byteValue() + { + return (byte) intValue(); + } + + /** + * Return the value of this <code>Number</code> as a <code>short</code>. + * + * @return the short value + * @since 1.1 + */ + public short shortValue() + { + return (short) intValue(); + } +} diff --git a/libjava/classpath/java/lang/NumberFormatException.java b/libjava/classpath/java/lang/NumberFormatException.java new file mode 100644 index 0000000..bf98156 --- /dev/null +++ b/libjava/classpath/java/lang/NumberFormatException.java @@ -0,0 +1,73 @@ +/* NumberFormatException.java -- thrown when parsing a bad string as a number + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Can be thrown when attempting to convert a <code>String</code> to + * one of the numeric types, but the operation fails because the string + * has the wrong format. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class NumberFormatException extends IllegalArgumentException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -2848938806368998894L; + + /** + * Create an exception without a message. + */ + public NumberFormatException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public NumberFormatException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Object.java b/libjava/classpath/java/lang/Object.java new file mode 100644 index 0000000..f8c389a --- /dev/null +++ b/libjava/classpath/java/lang/Object.java @@ -0,0 +1,530 @@ +/* java.lang.Object - The universal superclass in Java + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + + +/** + * Object is the ultimate superclass of every class + * (excepting interfaces). When you define a class that + * does not extend any other class, it implicitly extends + * java.lang.Object. Also, an anonymous class based on + * an interface will extend Object. + * + * <p>It provides general-purpose methods that every single + * Object, regardless of race, sex or creed, implements. + * All of the public methods may be invoked on arrays or + * interfaces. The protected methods <code>clone</code> + * and <code>finalize</code> are not accessible on arrays + * or interfaces, but all array types have a public version + * of <code>clone</code> which is accessible. + * + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @author Tom Tromey (tromey@cygnus.com) + */ +public class Object +{ + // WARNING: Object is a CORE class in the bootstrap cycle. See the comments + // in vm/reference/java/lang/Runtime for implications of this fact. + + // Many JVMs do not allow for static initializers in this class, + // hence we do not use them in the default implementation. + + // Some VM's rely on the order that these methods appear when laying + // out their internal structure. Therefore, do not haphazardly + // rearrange these methods. + + /** + * The basic constructor. Object is special, because it has no + * superclass, so there is no call to super(). + * + * @throws OutOfMemoryError Technically, this constructor never + * throws an OutOfMemoryError, because the memory has + * already been allocated by this point. But as all + * instance creation expressions eventually trace back + * to this constructor, and creating an object allocates + * memory, we list that possibility here. + */ + // This could be implicit, but then javadoc would not document it! + public Object() {} + + /** + * Determine whether this Object is semantically equal + * to another Object. + * + * <p>There are some fairly strict requirements on this + * method which subclasses must follow:<br> + * <ul> + * <li>It must be transitive. If <code>a.equals(b)</code> and + * <code>b.equals(c)</code>, then <code>a.equals(c)</code> + * must be true as well.</li> + * <li>It must be symmetric. <code>a.equals(b)</code> and + * <code>b.equals(a)</code> must have the same value.</li> + * <li>It must be reflexive. <code>a.equals(a)</code> must + * always be true.</li> + * <li>It must be consistent. Whichever value a.equals(b) + * returns on the first invocation must be the value + * returned on all later invocations.</li> + * <li><code>a.equals(null)</code> must be false.</li> + * <li>It must be consistent with hashCode(). That is, + * <code>a.equals(b)</code> must imply + * <code>a.hashCode() == b.hashCode()</code>. + * The reverse is not true; two objects that are not + * equal may have the same hashcode, but that has + * the potential to harm hashing performance.</li> + * </ul> + * + * <p>This is typically overridden to throw a {@link ClassCastException} + * if the argument is not comparable to the class performing + * the comparison, but that is not a requirement. It is legal + * for <code>a.equals(b)</code> to be true even though + * <code>a.getClass() != b.getClass()</code>. Also, it + * is typical to never cause a {@link NullPointerException}. + * + * <p>In general, the Collections API ({@link java.util}) use the + * <code>equals</code> method rather than the <code>==</code> + * operator to compare objects. However, {@link java.util.IdentityHashMap} + * is an exception to this rule, for its own good reasons. + * + * <p>The default implementation returns <code>this == o</code>. + * + * @param obj the Object to compare to + * @return whether this Object is semantically equal to another + * @see #hashCode() + */ + public boolean equals(Object obj) + { + return this == obj; + } + + /** + * Get a value that represents this Object, as uniquely as + * possible within the confines of an int. + * + * <p>There are some requirements on this method which + * subclasses must follow:<br> + * + * <ul> + * <li>Semantic equality implies identical hashcodes. In other + * words, if <code>a.equals(b)</code> is true, then + * <code>a.hashCode() == b.hashCode()</code> must be as well. + * However, the reverse is not necessarily true, and two + * objects may have the same hashcode without being equal.</li> + * <li>It must be consistent. Whichever value o.hashCode() + * returns on the first invocation must be the value + * returned on all later invocations as long as the object + * exists. Notice, however, that the result of hashCode may + * change between separate executions of a Virtual Machine, + * because it is not invoked on the same object.</li> + * </ul> + * + * <p>Notice that since <code>hashCode</code> is used in + * {@link java.util.Hashtable} and other hashing classes, + * a poor implementation will degrade the performance of hashing + * (so don't blindly implement it as returning a constant!). Also, + * if calculating the hash is time-consuming, a class may consider + * caching the results. + * + * <p>The default implementation returns + * <code>System.identityHashCode(this)</code> + * + * @return the hash code for this Object + * @see #equals(Object) + * @see System#identityHashCode(Object) + */ + public int hashCode() + { + return System.identityHashCode(this); + } + + /** + * Convert this Object to a human-readable String. + * There are no limits placed on how long this String + * should be or what it should contain. We suggest you + * make it as intuitive as possible to be able to place + * it into {@link java.io.PrintStream#println() System.out.println()} + * and such. + * + * <p>It is typical, but not required, to ensure that this method + * never completes abruptly with a {@link RuntimeException}. + * + * <p>This method will be called when performing string + * concatenation with this object. If the result is + * <code>null</code>, string concatenation will instead + * use <code>"null"</code>. + * + * <p>The default implementation returns + * <code>getClass().getName() + "@" + + * Integer.toHexString(hashCode())</code>. + * + * @return the String representing this Object, which may be null + * @throws OutOfMemoryError The default implementation creates a new + * String object, therefore it must allocate memory + * @see #getClass() + * @see #hashCode() + * @see Class#getName() + * @see Integer#toHexString(int) + */ + public String toString() + { + return getClass().getName() + '@' + Integer.toHexString(hashCode()); + } + + /** + * Called on an object by the Virtual Machine at most once, + * at some point after the Object is determined unreachable + * but before it is destroyed. You would think that this + * means it eventually is called on every Object, but this is + * not necessarily the case. If execution terminates + * abnormally, garbage collection does not always happen. + * Thus you cannot rely on this method to always work. + * For finer control over garbage collection, use references + * from the {@link java.lang.ref} package. + * + * <p>Virtual Machines are free to not call this method if + * they can determine that it does nothing important; for + * example, if your class extends Object and overrides + * finalize to do simply <code>super.finalize()</code>. + * + * <p>finalize() will be called by a {@link Thread} that has no + * locks on any Objects, and may be called concurrently. + * There are no guarantees on the order in which multiple + * objects are finalized. This means that finalize() is + * usually unsuited for performing actions that must be + * thread-safe, and that your implementation must be + * use defensive programming if it is to always work. + * + * <p>If an Exception is thrown from finalize() during garbage + * collection, it will be patently ignored and the Object will + * still be destroyed. + * + * <p>It is allowed, although not typical, for user code to call + * finalize() directly. User invocation does not affect whether + * automatic invocation will occur. It is also permitted, + * although not recommended, for a finalize() method to "revive" + * an object by making it reachable from normal code again. + * + * <p>Unlike constructors, finalize() does not get called + * for an object's superclass unless the implementation + * specifically calls <code>super.finalize()</code>. + * + * <p>The default implementation does nothing. + * + * @throws Throwable permits a subclass to throw anything in an + * overridden version; but the default throws nothing + * @see System#gc() + * @see System#runFinalizersOnExit(boolean) + * @see java.lang.ref + */ + protected void finalize() throws Throwable + { + } + + /** + * This method may be called to create a new copy of the + * Object. The typical behavior is as follows:<br> + * <ul> + * <li><code>o == o.clone()</code> is false</li> + * <li><code>o.getClass() == o.clone().getClass()</code> + * is true</li> + * <li><code>o.equals(o)</code> is true</li> + * </ul> + * + * <p>However, these are not strict requirements, and may + * be violated if necessary. Of the three requirements, the + * last is the most commonly violated, particularly if the + * subclass does not override {@link #equals(Object)}. + * + * <p>If the Object you call clone() on does not implement + * {@link Cloneable} (which is a placeholder interface), then + * a CloneNotSupportedException is thrown. Notice that + * Object does not implement Cloneable; this method exists + * as a convenience for subclasses that do. + * + * <p>Object's implementation of clone allocates space for the + * new Object using the correct class, without calling any + * constructors, and then fills in all of the new field values + * with the old field values. Thus, it is a shallow copy. + * However, subclasses are permitted to make a deep copy. + * + * <p>All array types implement Cloneable, and override + * this method as follows (it should never fail):<br> + * <pre> + * public Object clone() + * { + * try + * { + * super.clone(); + * } + * catch (CloneNotSupportedException e) + * { + * throw new InternalError(e.getMessage()); + * } + * } + * </pre> + * + * @return a copy of the Object + * @throws CloneNotSupportedException If this Object does not + * implement Cloneable + * @throws OutOfMemoryError Since cloning involves memory allocation, + * even though it may bypass constructors, you might run + * out of memory + * @see Cloneable + */ + protected Object clone() throws CloneNotSupportedException + { + if (this instanceof Cloneable) + return VMObject.clone((Cloneable) this); + throw new CloneNotSupportedException("Object not cloneable"); + } + + /** + * Returns the runtime {@link Class} of this Object. + * + * <p>The class object can also be obtained without a runtime + * instance by using the class literal, as in: + * <code>Foo.class</code>. Notice that the class literal + * also works on primitive types, making it useful for + * reflection purposes. + * + * @return the class of this Object + */ + public final Class getClass() + { + return VMObject.getClass(this); + } + + /** + * Wakes up one of the {@link Thread}s that has called + * <code>wait</code> on this Object. Only the owner + * of a lock on this Object may call this method. This lock + * is obtained by a <code>synchronized</code> method or statement. + * + * <p>The Thread to wake up is chosen arbitrarily. The + * awakened thread is not guaranteed to be the next thread + * to actually obtain the lock on this object. + * + * <p>This thread still holds a lock on the object, so it is + * typical to release the lock by exiting the synchronized + * code, calling wait(), or calling {@link Thread#sleep()}, so + * that the newly awakened thread can actually resume. The + * awakened thread will most likely be awakened with an + * {@link InterruptedException}, but that is not guaranteed. + * + * @throws IllegalMonitorStateException if this Thread + * does not own the lock on the Object + * @see #notifyAll() + * @see #wait() + * @see #wait(long) + * @see #wait(long, int) + * @see Thread + */ + public final void notify() throws IllegalMonitorStateException + { + VMObject.notify(this); + } + + /** + * Wakes up all of the {@link Thread}s that have called + * <code>wait</code> on this Object. Only the owner + * of a lock on this Object may call this method. This lock + * is obtained by a <code>synchronized</code> method or statement. + * + * <p>There are no guarantees as to which thread will next + * obtain the lock on the object. + * + * <p>This thread still holds a lock on the object, so it is + * typical to release the lock by exiting the synchronized + * code, calling wait(), or calling {@link Thread#sleep()}, so + * that one of the newly awakened threads can actually resume. + * The resuming thread will most likely be awakened with an + * {@link InterruptedException}, but that is not guaranteed. + * + * @throws IllegalMonitorStateException if this Thread + * does not own the lock on the Object + * @see #notify() + * @see #wait() + * @see #wait(long) + * @see #wait(long, int) + * @see Thread + */ + public final void notifyAll() throws IllegalMonitorStateException + { + VMObject.notifyAll(this); + } + + /** + * Waits indefinitely for notify() or notifyAll() to be + * called on the Object in question. Implementation is + * identical to wait(0). + * + * <p>The Thread that calls wait must have a lock on this Object, + * obtained by a <code>synchronized</code> method or statement. + * After calling wait, the thread loses the lock on this + * object until the method completes (abruptly or normally), + * at which time it regains the lock. All locks held on + * other objects remain in force, even though the thread is + * inactive. Therefore, caution must be used to avoid deadlock. + * + * <p>While it is typical that this method will complete abruptly + * with an {@link InterruptedException}, it is not guaranteed. So, + * it is typical to call wait inside an infinite loop:<br> + * + * <pre> + * try + * { + * while (true) + * lock.wait(); + * } + * catch (InterruptedException e) + * { + * } + * </pre> + * + * @throws IllegalMonitorStateException if this Thread + * does not own a lock on this Object + * @throws InterruptedException if some other Thread + * interrupts this Thread + * @see #notify() + * @see #notifyAll() + * @see #wait(long) + * @see #wait(long, int) + * @see Thread + */ + public final void wait() + throws IllegalMonitorStateException, InterruptedException + { + VMObject.wait(this, 0, 0); + } + + /** + * Waits a specified amount of time (or indefinitely if + * the time specified is 0) for someone to call notify() + * or notifyAll() on this Object, waking up this Thread. + * + * <p>The Thread that calls wait must have a lock on this Object, + * obtained by a <code>synchronized</code> method or statement. + * After calling wait, the thread loses the lock on this + * object until the method completes (abruptly or normally), + * at which time it regains the lock. All locks held on + * other objects remain in force, even though the thread is + * inactive. Therefore, caution must be used to avoid deadlock. + * + * <p>Usually, this call will complete normally if the time + * expires, or abruptly with {@link InterruptedException} + * if another thread called notify, but neither result + * is guaranteed. + * + * <p>The waiting period is only *roughly* the amount of time + * you requested. It cannot be exact because of the overhead + * of the call itself. Most Virtual Machiness treat the + * argument as a lower limit on the time spent waiting, but + * even that is not guaranteed. Besides, some other thread + * may hold the lock on the object when the time expires, so + * the current thread may still have to wait to reobtain the + * lock. + * + * @param ms the minimum number of milliseconds to wait (1000 + * milliseconds = 1 second), or 0 for an indefinite wait + * @throws IllegalArgumentException if ms < 0 + * @throws IllegalMonitorStateException if this Thread + * does not own a lock on this Object + * @throws InterruptedException if some other Thread + * interrupts this Thread + * @see #notify() + * @see #notifyAll() + * @see #wait() + * @see #wait(long, int) + * @see Thread + */ + public final void wait(long ms) + throws IllegalMonitorStateException, InterruptedException + { + wait(ms, 0); + } + + /** + * Waits a specified amount of time (or indefinitely if + * the time specified is 0) for someone to call notify() + * or notifyAll() on this Object, waking up this Thread. + * + * <p>The Thread that calls wait must have a lock on this Object, + * obtained by a <code>synchronized</code> method or statement. + * After calling wait, the thread loses the lock on this + * object until the method completes (abruptly or normally), + * at which time it regains the lock. All locks held on + * other objects remain in force, even though the thread is + * inactive. Therefore, caution must be used to avoid deadlock. + * + * <p>Usually, this call will complete normally if the time + * expires, or abruptly with {@link InterruptedException} + * if another thread called notify, but neither result + * is guaranteed. + * + * <p>The waiting period is nowhere near as precise as + * nanoseconds; considering that even wait(int) is inaccurate, + * how much can you expect? But on supporting + * implementations, this offers somewhat more granularity + * than milliseconds. + * + * @param ms the number of milliseconds to wait (1,000 + * milliseconds = 1 second) + * @param ns the number of nanoseconds to wait over and + * above ms (1,000,000 nanoseconds = 1 millisecond) + * @throws IllegalArgumentException if ms < 0 or ns is not + * in the range 0 to 999,999 + * @throws IllegalMonitorStateException if this Thread + * does not own a lock on this Object + * @throws InterruptedException if some other Thread + * interrupts this Thread + * @see #notify() + * @see #notifyAll() + * @see #wait() + * @see #wait(long) + * @see Thread + */ + public final void wait(long ms, int ns) + throws IllegalMonitorStateException, InterruptedException + { + if (ms < 0 || ns < 0 || ns > 999999) + throw new IllegalArgumentException("argument out of range"); + VMObject.wait(this, ms, ns); + } +} // class Object diff --git a/libjava/classpath/java/lang/OutOfMemoryError.java b/libjava/classpath/java/lang/OutOfMemoryError.java new file mode 100644 index 0000000..66da563 --- /dev/null +++ b/libjava/classpath/java/lang/OutOfMemoryError.java @@ -0,0 +1,73 @@ +/* OutOfMemoryError.java -- thrown when a memory allocation fails + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Thrown when the Java Virtual Machine is unable to allocate an object + * because it is out of memory and no more memory could be made available + * by the garbage collector. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class OutOfMemoryError extends VirtualMachineError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 8228564086184010517L; + + /** + * Create an error without a message. + */ + public OutOfMemoryError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public OutOfMemoryError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Package.java b/libjava/classpath/java/lang/Package.java new file mode 100644 index 0000000..4cded0a --- /dev/null +++ b/libjava/classpath/java/lang/Package.java @@ -0,0 +1,318 @@ +/* Package.java -- information about a package + Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import gnu.classpath.VMStackWalker; + +import java.net.URL; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; + + +/** + * Everything you ever wanted to know about a package. This class makes it + * possible to attach specification and implementation information to a + * package as explained in the + * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html#PackageVersionSpecification">Package Versioning Specification</a> + * section of the + * <a href="http://java.sun.com/products/jdk/1.3/docs/guide/versioning/spec/VersioningSpecification.html">Product Versioning Specification</a>. + * It also allows packages to be sealed with respect to the originating URL. + * + * <p>The most useful method is the <code>isCompatibleWith()</code> method that + * compares a desired version of a specification with the version of the + * specification as implemented by a package. A package is considered + * compatible with another version if the version of the specification is + * equal or higher then the requested version. Version numbers are represented + * as strings of positive numbers separated by dots (e.g. "1.2.0"). + * The first number is called the major number, the second the minor, + * the third the micro, etc. A version is considered higher then another + * version if it has a bigger major number then the another version or when + * the major numbers of the versions are equal if it has a bigger minor number + * then the other version, etc. (If a version has no minor, micro, etc numbers + * then they are considered the be 0.) + * + * @author Mark Wielaard (mark@klomp.org) + * @see ClassLoader#definePackage(String, String, String, String, String, + * String, String, URL) + * @since 1.2 + * @status updated to 1.4 + */ +public class Package +{ + /** The name of the Package */ + private final String name; + + /** The name if the implementation */ + private final String implTitle; + + /** The vendor that wrote this implementation */ + private final String implVendor; + + /** The version of this implementation */ + private final String implVersion; + + /** The name of the specification */ + private final String specTitle; + + /** The name of the specification designer */ + private final String specVendor; + + /** The version of this specification */ + private final String specVersion; + + /** If sealed the origin of the package classes, otherwise null */ + private final URL sealed; + + /** + * A package local constructor for the Package class. All parameters except + * the <code>name</code> of the package may be <code>null</code>. + * There are no public constructors defined for Package; this is a package + * local constructor that is used by java.lang.Classloader.definePackage(). + * + * @param name The name of the Package + * @param specTitle The name of the specification + * @param specVendor The name of the specification designer + * @param specVersion The version of this specification + * @param implTitle The name of the implementation + * @param implVendor The vendor that wrote this implementation + * @param implVersion The version of this implementation + * @param sealed If sealed the origin of the package classes + */ + Package(String name, + String specTitle, String specVendor, String specVersion, + String implTitle, String implVendor, String implVersion, URL sealed) + { + if (name == null) + throw new IllegalArgumentException("null Package name"); + + this.name = name; + this.implTitle = implTitle; + this.implVendor = implVendor; + this.implVersion = implVersion; + this.specTitle = specTitle; + this.specVendor = specVendor; + this.specVersion = specVersion; + this.sealed = sealed; + } + + /** + * Returns the Package name in dot-notation. + * + * @return the non-null package name + */ + public String getName() + { + return name; + } + + /** + * Returns the name of the specification, or null if unknown. + * + * @return the specification title + */ + public String getSpecificationTitle() + { + return specTitle; + } + + /** + * Returns the version of the specification, or null if unknown. + * + * @return the specification version + */ + public String getSpecificationVersion() + { + return specVersion; + } + + /** + * Returns the name of the specification designer, or null if unknown. + * + * @return the specification vendor + */ + public String getSpecificationVendor() + { + return specVendor; + } + + /** + * Returns the name of the implementation, or null if unknown. + * + * @return the implementation title + */ + public String getImplementationTitle() + { + return implTitle; + } + + /** + * Returns the version of this implementation, or null if unknown. + * + * @return the implementation version + */ + public String getImplementationVersion() + { + return implVersion; + } + + /** + * Returns the vendor that wrote this implementation, or null if unknown. + * + * @return the implementation vendor + */ + public String getImplementationVendor() + { + return implVendor; + } + + /** + * Returns true if this Package is sealed. + * + * @return true if the package is sealed + */ + public boolean isSealed() + { + return sealed != null; + } + + /** + * Returns true if this Package is sealed and the origin of the classes is + * the given URL. + * + * @param url the URL to test + * @return true if the package is sealed by this URL + * @throws NullPointerException if url is null + */ + public boolean isSealed(URL url) + { + return url.equals(sealed); + } + + /** + * Checks if the version of the specification is higher or at least as high + * as the desired version. Comparison is done by sequentially comparing + * dotted decimal numbers from the parameter and from + * <code>getSpecificationVersion</code>. + * + * @param version the (minimal) desired version of the specification + * + * @return true if the version is compatible, false otherwise + * + * @Throws NumberFormatException if either version string is invalid + * @throws NullPointerException if either version string is null + */ + public boolean isCompatibleWith(String version) + { + StringTokenizer versionTokens = new StringTokenizer(version, "."); + StringTokenizer specTokens = new StringTokenizer(specVersion, "."); + try + { + while (versionTokens.hasMoreElements()) + { + int vers = Integer.parseInt(versionTokens.nextToken()); + int spec = Integer.parseInt(specTokens.nextToken()); + if (spec < vers) + return false; + else if (spec > vers) + return true; + // They must be equal, next Token please! + } + } + catch (NoSuchElementException e) + { + // This must have been thrown by spec.nextToken() so return false. + return false; + } + // They must have been exactly the same version. + // Or the specVersion has more subversions. That is also good. + return true; + } + + /** + * Returns the named package if it is known by the callers class loader. + * It may return null if the package is unknown, when there is no + * information on that particular package available or when the callers + * classloader is null. + * + * @param name the name of the desired package + * @return the package by that name in the current ClassLoader + */ + public static Package getPackage(String name) + { + // Get the caller's classloader + ClassLoader cl = VMStackWalker.getCallingClassLoader(); + return cl != null ? cl.getPackage(name) : VMClassLoader.getPackage(name); + } + + /** + * Returns all the packages that are known to the callers class loader. + * It may return an empty array if the classloader of the caller is null. + * + * @return an array of all known packages + */ + public static Package[] getPackages() + { + // Get the caller's classloader + ClassLoader cl = VMStackWalker.getCallingClassLoader(); + return cl != null ? cl.getPackages() : VMClassLoader.getPackages(); + } + + /** + * Returns the hashCode of the name of this package. + * + * @return the hash code + */ + public int hashCode() + { + return name.hashCode(); + } + + /** + * Returns a string representation of this package. It is specified to + * be <code>"package " + getName() + (getSpecificationTitle() == null + * ? "" : ", " + getSpecificationTitle()) + (getSpecificationVersion() + * == null ? "" : ", version " + getSpecificationVersion())</code>. + * + * @return the string representation of the package + */ + public String toString() + { + return ("package " + name + (specTitle == null ? "" : ", " + specTitle) + + (specVersion == null ? "" : ", version " + specVersion)); + } +} // class Package diff --git a/libjava/classpath/java/lang/Process.java b/libjava/classpath/java/lang/Process.java new file mode 100644 index 0000000..b6e18ca --- /dev/null +++ b/libjava/classpath/java/lang/Process.java @@ -0,0 +1,129 @@ +/* Process.java - Represent spawned system process + Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * An instance of a subclass of <code>Process</code> is created by the + * <code>Runtime.exec</code> methods. Methods in <code>Process</code> + * provide a means to send input to a process, obtain the output from a + * subprocess, destroy a subprocess, obtain the exit value from a + * subprocess, and wait for a subprocess to complete. + * + * <p>This is dependent on the platform, and some processes (like native + * windowing processes, 16-bit processes in Windows, or shell scripts) may + * be limited in functionality. Because some platforms have limited buffers + * between processes, you may need to provide input and read output to prevent + * the process from blocking, or even deadlocking. + * + * <p>Even if all references to this object disapper, the process continues + * to execute to completion. There are no guarantees that the + * subprocess execute asynchronously or concurrently with the process which + * owns this object. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @see Runtime#exec(String[], String[], File) + * @since 1.0 + * @status updated to 1.4 + */ +public abstract class Process +{ + /** + * Empty constructor does nothing. + */ + public Process() + { + } + + /** + * Obtain the output stream that sends data to the subprocess. This is + * the STDIN of the subprocess. When implementing, you should probably + * use a buffered stream. + * + * @return the output stream that pipes to the process input + */ + public abstract OutputStream getOutputStream(); + + /** + * Obtain the input stream that receives data from the subprocess. This is + * the STDOUT of the subprocess. When implementing, you should probably + * use a buffered stream. + * + * @return the input stream that pipes data from the process output + */ + public abstract InputStream getInputStream(); + + /** + * Obtain the input stream that receives data from the subprocess. This is + * the STDERR of the subprocess. When implementing, you should probably + * use a buffered stream. + * + * @return the input stream that pipes data from the process error output + */ + public abstract InputStream getErrorStream(); + + /** + * The thread calling <code>waitFor</code> will block until the subprocess + * has terminated. If the process has already terminated then the method + * immediately returns with the exit value of the subprocess. + * + * @return the subprocess exit value; 0 conventionally denotes success + * @throws InterruptedException if another thread interrupts the blocked one + */ + public abstract int waitFor() throws InterruptedException; + + /** + * When a process terminates there is associated with that termination + * an exit value for the process to indicate why it terminated. A return + * of <code>0</code> denotes normal process termination by convention. + * + * @return the exit value of the subprocess + * @throws IllegalThreadStateException if the subprocess has not terminated + */ + public abstract int exitValue(); + + /** + * Kills the subprocess and all of its children forcibly. + */ + public abstract void destroy(); +} // class Process diff --git a/libjava/classpath/java/lang/Readable.java b/libjava/classpath/java/lang/Readable.java new file mode 100644 index 0000000..efc1985 --- /dev/null +++ b/libjava/classpath/java/lang/Readable.java @@ -0,0 +1,71 @@ +/* Readable.java -- A character source + Copyright (C) 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.io.IOException; +import java.nio.CharBuffer; + +/** + * A <code>Readable</code> object is simply a source for Unicode character + * data. On request, a <code>Readable</code> will provide its data in + * a supplied <code>CharBuffer</code>. + * + * @author Tom Tromey <tromey@redhat.com> + * @author Andrew John Hughes <gnu_andrew@member.fsf.org> + * @since 1.5 + */ +public interface Readable +{ + + /** + * Adds the character data supplied by this <code>Readable</code> + * to the specified character buffer. This method simply places + * each character into the buffer as supplied, using <code>put()</code>, + * without flipping or rewinding. + * + * @param buf the buffer to place the character data in. + * @return the number of <code>char</code> values placed in the buffer, + * or -1 if no more characters are available. + * @throws IOException if an I/O error occurs. + * @throws NullPointerException if buf is null. + * @throws ReadOnlyBufferException if buf is read only. + */ + int read(CharBuffer buf) + throws IOException; + +} diff --git a/libjava/classpath/java/lang/Runnable.java b/libjava/classpath/java/lang/Runnable.java new file mode 100644 index 0000000..32c52b9 --- /dev/null +++ b/libjava/classpath/java/lang/Runnable.java @@ -0,0 +1,62 @@ +/* Runnable -- interface for a method tied to an Object; often for Threads + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Runnable is an interface you implement to indicate that your class can be + * executed as the main part of a Thread, among other places. When you want + * an entry point to run a piece of code, implement this interface and + * override run. + * + * @author Paul Fisher + * @author Tom Tromey (tromey@cygnus.com) + * @see Thread + * @since 1.0 + * @status updated to 1.4 + */ +public interface Runnable +{ + /** + * This method will be called by whoever wishes to run your class + * implementing Runnable. Note that there are no restrictions on what + * you are allowed to do in the run method, except that you cannot + * throw a checked exception. + */ + void run(); +} diff --git a/libjava/classpath/java/lang/Runtime.java b/libjava/classpath/java/lang/Runtime.java new file mode 100644 index 0000000..64ca5d9 --- /dev/null +++ b/libjava/classpath/java/lang/Runtime.java @@ -0,0 +1,796 @@ +/* Runtime.java -- access to the VM process + Copyright (C) 1998, 2002, 2003, 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import gnu.classpath.SystemProperties; +import gnu.classpath.VMStackWalker; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.StringTokenizer; + +/** + * Runtime represents the Virtual Machine. + * + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @author Jeroen Frijters + */ +// No idea why this class isn't final, since you can't build a subclass! +public class Runtime +{ + /** + * The library path, to search when loading libraries. We can also safely use + * this as a lock for synchronization. + */ + private final String[] libpath; + + /** + * The thread that started the exit sequence. Access to this field must + * be thread-safe; lock on libpath to avoid deadlock with user code. + * <code>runFinalization()</code> may want to look at this to see if ALL + * finalizers should be run, because the virtual machine is about to halt. + */ + private Thread exitSequence; + + /** + * All shutdown hooks. This is initialized lazily, and set to null once all + * shutdown hooks have run. Access to this field must be thread-safe; lock + * on libpath to avoid deadlock with user code. + */ + private Set shutdownHooks; + + /** + * The one and only runtime instance. + */ + private static final Runtime current = new Runtime(); + + /** + * Not instantiable by a user, this should only create one instance. + */ + private Runtime() + { + if (current != null) + throw new InternalError("Attempt to recreate Runtime"); + + // If used by underlying VM this contains the directories where Classpath's own + // native libraries are located. + String bootPath = SystemProperties.getProperty("gnu.classpath.boot.library.path", ""); + + // If properly set by the user this contains the directories where the application's + // native libraries are located. On operating systems where a LD_LIBRARY_PATH environment + // variable is available a VM should preset java.library.path with value of this + // variable. + String path = SystemProperties.getProperty("java.library.path", "."); + String pathSep = SystemProperties.getProperty("path.separator", ":"); + String fileSep = SystemProperties.getProperty("file.separator", "/"); + + StringTokenizer t1 = new StringTokenizer(bootPath, pathSep); + StringTokenizer t2 = new StringTokenizer(path, pathSep); + libpath = new String[t1.countTokens() + t2.countTokens()]; + + int i = 0; + while(t1.hasMoreTokens()) { + String prefix = t1.nextToken(); + if (! prefix.endsWith(fileSep)) + prefix += fileSep; + + libpath[i] = prefix; + i++; + } + + while(t2.hasMoreTokens()) { + String prefix = t2.nextToken(); + if (! prefix.endsWith(fileSep)) + prefix += fileSep; + + libpath[i] = prefix; + i++; + } + } + + /** + * Get the current Runtime object for this JVM. This is necessary to access + * the many instance methods of this class. + * + * @return the current Runtime object + */ + public static Runtime getRuntime() + { + return current; + } + + /** + * Exit the Java runtime. This method will either throw a SecurityException + * or it will never return. The status code is returned to the system; often + * a non-zero status code indicates an abnormal exit. Of course, there is a + * security check, <code>checkExit(status)</code>. + * + * <p>First, all shutdown hooks are run, in unspecified order, and + * concurrently. Next, if finalization on exit has been enabled, all pending + * finalizers are run. Finally, the system calls <code>halt</code>.</p> + * + * <p>If this is run a second time after shutdown has already started, there + * are two actions. If shutdown hooks are still executing, it blocks + * indefinitely. Otherwise, if the status is nonzero it halts immediately; + * if it is zero, it blocks indefinitely. This is typically called by + * <code>System.exit</code>.</p> + * + * @param status the status to exit with + * @throws SecurityException if permission is denied + * @see #addShutdownHook(Thread) + * @see #runFinalizersOnExit(boolean) + * @see #runFinalization() + * @see #halt(int) + */ + public void exit(int status) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkExit(status); + + if (runShutdownHooks()) + halt(status); + + // Someone else already called runShutdownHooks(). + // Make sure we are not/no longer in the shutdownHooks set. + // And wait till the thread that is calling runShutdownHooks() finishes. + synchronized (libpath) + { + if (shutdownHooks != null) + { + shutdownHooks.remove(Thread.currentThread()); + // Interrupt the exit sequence thread, in case it was waiting + // inside a join on our thread. + exitSequence.interrupt(); + // Shutdown hooks are still running, so we clear status to + // make sure we don't halt. + status = 0; + } + } + + // If exit() is called again after the shutdown hooks have run, but + // while finalization for exit is going on and the status is non-zero + // we halt immediately. + if (status != 0) + halt(status); + + while (true) + try + { + exitSequence.join(); + } + catch (InterruptedException e) + { + // Ignore, we've suspended indefinitely to let all shutdown + // hooks complete, and to let any non-zero exits through, because + // this is a duplicate call to exit(0). + } + } + + /** + * On first invocation, run all the shutdown hooks and return true. + * Any subsequent invocations will simply return false. + * Note that it is package accessible so that VMRuntime can call it + * when VM exit is not triggered by a call to Runtime.exit(). + * + * @return was the current thread the first one to call this method? + */ + boolean runShutdownHooks() + { + boolean first = false; + synchronized (libpath) // Synch on libpath, not this, to avoid deadlock. + { + if (exitSequence == null) + { + first = true; + exitSequence = Thread.currentThread(); + if (shutdownHooks != null) + { + Iterator i = shutdownHooks.iterator(); + while (i.hasNext()) // Start all shutdown hooks. + try + { + ((Thread) i.next()).start(); + } + catch (IllegalThreadStateException e) + { + i.remove(); + } + } + } + } + if (first) + { + if (shutdownHooks != null) + { + // Check progress of all shutdown hooks. As a hook completes, + // remove it from the set. If a hook calls exit, it removes + // itself from the set, then waits indefinitely on the + // exitSequence thread. Once the set is empty, set it to null to + // signal all finalizer threads that halt may be called. + while (true) + { + Thread[] hooks; + synchronized (libpath) + { + hooks = new Thread[shutdownHooks.size()]; + shutdownHooks.toArray(hooks); + } + if (hooks.length == 0) + break; + for (int i = 0; i < hooks.length; i++) + { + try + { + synchronized (libpath) + { + if (!shutdownHooks.contains(hooks[i])) + continue; + } + hooks[i].join(); + synchronized (libpath) + { + shutdownHooks.remove(hooks[i]); + } + } + catch (InterruptedException x) + { + // continue waiting on the next thread + } + } + } + synchronized (libpath) + { + shutdownHooks = null; + } + } + // Run finalization on all finalizable objects (even if they are + // still reachable). + VMRuntime.runFinalizationForExit(); + } + return first; + } + + /** + * Register a new shutdown hook. This is invoked when the program exits + * normally (because all non-daemon threads ended, or because + * <code>System.exit</code> was invoked), or when the user terminates + * the virtual machine (such as by typing ^C, or logging off). There is + * a security check to add hooks, + * <code>RuntimePermission("shutdownHooks")</code>. + * + * <p>The hook must be an initialized, but unstarted Thread. The threads + * are run concurrently, and started in an arbitrary order; and user + * threads or daemons may still be running. Once shutdown hooks have + * started, they must all complete, or else you must use <code>halt</code>, + * to actually finish the shutdown sequence. Attempts to modify hooks + * after shutdown has started result in IllegalStateExceptions.</p> + * + * <p>It is imperative that you code shutdown hooks defensively, as you + * do not want to deadlock, and have no idea what other hooks will be + * running concurrently. It is also a good idea to finish quickly, as the + * virtual machine really wants to shut down!</p> + * + * <p>There are no guarantees that such hooks will run, as there are ways + * to forcibly kill a process. But in such a drastic case, shutdown hooks + * would do little for you in the first place.</p> + * + * @param hook an initialized, unstarted Thread + * @throws IllegalArgumentException if the hook is already registered or run + * @throws IllegalStateException if the virtual machine is already in + * the shutdown sequence + * @throws SecurityException if permission is denied + * @since 1.3 + * @see #removeShutdownHook(Thread) + * @see #exit(int) + * @see #halt(int) + */ + public void addShutdownHook(Thread hook) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkPermission(new RuntimePermission("shutdownHooks")); + if (hook.isAlive() || hook.getThreadGroup() == null) + throw new IllegalArgumentException("The hook thread " + hook + " must not have been already run or started"); + synchronized (libpath) + { + if (exitSequence != null) + throw new IllegalStateException("The Virtual Machine is exiting. It is not possible anymore to add any hooks"); + if (shutdownHooks == null) + { + VMRuntime.enableShutdownHooks(); + shutdownHooks = new HashSet(); // Lazy initialization. + } + if (! shutdownHooks.add(hook)) + throw new IllegalArgumentException(hook.toString() + " had already been inserted"); + } + } + + /** + * De-register a shutdown hook. As when you registered it, there is a + * security check to remove hooks, + * <code>RuntimePermission("shutdownHooks")</code>. + * + * @param hook the hook to remove + * @return true if the hook was successfully removed, false if it was not + * registered in the first place + * @throws IllegalStateException if the virtual machine is already in + * the shutdown sequence + * @throws SecurityException if permission is denied + * @since 1.3 + * @see #addShutdownHook(Thread) + * @see #exit(int) + * @see #halt(int) + */ + public boolean removeShutdownHook(Thread hook) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkPermission(new RuntimePermission("shutdownHooks")); + synchronized (libpath) + { + if (exitSequence != null) + throw new IllegalStateException(); + if (shutdownHooks != null) + return shutdownHooks.remove(hook); + } + return false; + } + + /** + * Forcibly terminate the virtual machine. This call never returns. It is + * much more severe than <code>exit</code>, as it bypasses all shutdown + * hooks and initializers. Use caution in calling this! Of course, there is + * a security check, <code>checkExit(status)</code>. + * + * @param status the status to exit with + * @throws SecurityException if permission is denied + * @since 1.3 + * @see #exit(int) + * @see #addShutdownHook(Thread) + */ + public void halt(int status) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkExit(status); + VMRuntime.exit(status); + } + + /** + * Tell the VM to run the finalize() method on every single Object before + * it exits. Note that the JVM may still exit abnormally and not perform + * this, so you still don't have a guarantee. And besides that, this is + * inherently unsafe in multi-threaded code, as it may result in deadlock + * as multiple threads compete to manipulate objects. This value defaults to + * <code>false</code>. There is a security check, <code>checkExit(0)</code>. + * + * @param finalizeOnExit whether to finalize all Objects on exit + * @throws SecurityException if permission is denied + * @see #exit(int) + * @see #gc() + * @since 1.1 + * @deprecated never rely on finalizers to do a clean, thread-safe, + * mop-up from your code + */ + public static void runFinalizersOnExit(boolean finalizeOnExit) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkExit(0); + VMRuntime.runFinalizersOnExit(finalizeOnExit); + } + + /** + * Create a new subprocess with the specified command line. Calls + * <code>exec(cmdline, null, null)</code>. A security check is performed, + * <code>checkExec</code>. + * + * @param cmdline the command to call + * @return the Process object + * @throws SecurityException if permission is denied + * @throws IOException if an I/O error occurs + * @throws NullPointerException if cmdline is null + * @throws IndexOutOfBoundsException if cmdline is "" + */ + public Process exec(String cmdline) throws IOException + { + return exec(cmdline, null, null); + } + + /** + * Create a new subprocess with the specified command line and environment. + * If the environment is null, the process inherits the environment of + * this process. Calls <code>exec(cmdline, env, null)</code>. A security + * check is performed, <code>checkExec</code>. + * + * @param cmdline the command to call + * @param env the environment to use, in the format name=value + * @return the Process object + * @throws SecurityException if permission is denied + * @throws IOException if an I/O error occurs + * @throws NullPointerException if cmdline is null, or env has null entries + * @throws IndexOutOfBoundsException if cmdline is "" + */ + public Process exec(String cmdline, String[] env) throws IOException + { + return exec(cmdline, env, null); + } + + /** + * Create a new subprocess with the specified command line, environment, and + * working directory. If the environment is null, the process inherits the + * environment of this process. If the directory is null, the process uses + * the current working directory. This splits cmdline into an array, using + * the default StringTokenizer, then calls + * <code>exec(cmdArray, env, dir)</code>. A security check is performed, + * <code>checkExec</code>. + * + * @param cmdline the command to call + * @param env the environment to use, in the format name=value + * @param dir the working directory to use + * @return the Process object + * @throws SecurityException if permission is denied + * @throws IOException if an I/O error occurs + * @throws NullPointerException if cmdline is null, or env has null entries + * @throws IndexOutOfBoundsException if cmdline is "" + * @since 1.3 + */ + public Process exec(String cmdline, String[] env, File dir) + throws IOException + { + StringTokenizer t = new StringTokenizer(cmdline); + String[] cmd = new String[t.countTokens()]; + for (int i = 0; i < cmd.length; i++) + cmd[i] = t.nextToken(); + return exec(cmd, env, dir); + } + + /** + * Create a new subprocess with the specified command line, already + * tokenized. Calls <code>exec(cmd, null, null)</code>. A security check + * is performed, <code>checkExec</code>. + * + * @param cmd the command to call + * @return the Process object + * @throws SecurityException if permission is denied + * @throws IOException if an I/O error occurs + * @throws NullPointerException if cmd is null, or has null entries + * @throws IndexOutOfBoundsException if cmd is length 0 + */ + public Process exec(String[] cmd) throws IOException + { + return exec(cmd, null, null); + } + + /** + * Create a new subprocess with the specified command line, already + * tokenized, and specified environment. If the environment is null, the + * process inherits the environment of this process. Calls + * <code>exec(cmd, env, null)</code>. A security check is performed, + * <code>checkExec</code>. + * + * @param cmd the command to call + * @param env the environment to use, in the format name=value + * @return the Process object + * @throws SecurityException if permission is denied + * @throws IOException if an I/O error occurs + * @throws NullPointerException if cmd is null, or cmd or env has null + * entries + * @throws IndexOutOfBoundsException if cmd is length 0 + */ + public Process exec(String[] cmd, String[] env) throws IOException + { + return exec(cmd, env, null); + } + + /** + * Create a new subprocess with the specified command line, already + * tokenized, and the specified environment and working directory. If the + * environment is null, the process inherits the environment of this + * process. If the directory is null, the process uses the current working + * directory. A security check is performed, <code>checkExec</code>. + * + * @param cmd the command to call + * @param env the environment to use, in the format name=value + * @param dir the working directory to use + * @return the Process object + * @throws SecurityException if permission is denied + * @throws IOException if an I/O error occurs + * @throws NullPointerException if cmd is null, or cmd or env has null + * entries + * @throws IndexOutOfBoundsException if cmd is length 0 + * @since 1.3 + */ + public Process exec(String[] cmd, String[] env, File dir) + throws IOException + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkExec(cmd[0]); + return VMRuntime.exec(cmd, env, dir); + } + + /** + * Returns the number of available processors currently available to the + * virtual machine. This number may change over time; so a multi-processor + * program want to poll this to determine maximal resource usage. + * + * @return the number of processors available, at least 1 + */ + public int availableProcessors() + { + return VMRuntime.availableProcessors(); + } + + /** + * Find out how much memory is still free for allocating Objects on the heap. + * + * @return the number of bytes of free memory for more Objects + */ + public long freeMemory() + { + return VMRuntime.freeMemory(); + } + + /** + * Find out how much memory total is available on the heap for allocating + * Objects. + * + * @return the total number of bytes of memory for Objects + */ + public long totalMemory() + { + return VMRuntime.totalMemory(); + } + + /** + * Returns the maximum amount of memory the virtual machine can attempt to + * use. This may be <code>Long.MAX_VALUE</code> if there is no inherent + * limit (or if you really do have a 8 exabyte memory!). + * + * @return the maximum number of bytes the virtual machine will attempt + * to allocate + */ + public long maxMemory() + { + return VMRuntime.maxMemory(); + } + + /** + * Run the garbage collector. This method is more of a suggestion than + * anything. All this method guarantees is that the garbage collector will + * have "done its best" by the time it returns. Notice that garbage + * collection takes place even without calling this method. + */ + public void gc() + { + VMRuntime.gc(); + } + + /** + * Run finalization on all Objects that are waiting to be finalized. Again, + * a suggestion, though a stronger one than {@link #gc()}. This calls the + * <code>finalize</code> method of all objects waiting to be collected. + * + * @see #finalize() + */ + public void runFinalization() + { + VMRuntime.runFinalization(); + } + + /** + * Tell the VM to trace every bytecode instruction that executes (print out + * a trace of it). No guarantees are made as to where it will be printed, + * and the VM is allowed to ignore this request. + * + * @param on whether to turn instruction tracing on + */ + public void traceInstructions(boolean on) + { + VMRuntime.traceInstructions(on); + } + + /** + * Tell the VM to trace every method call that executes (print out a trace + * of it). No guarantees are made as to where it will be printed, and the + * VM is allowed to ignore this request. + * + * @param on whether to turn method tracing on + */ + public void traceMethodCalls(boolean on) + { + VMRuntime.traceMethodCalls(on); + } + + /** + * Load a native library using the system-dependent filename. This is similar + * to loadLibrary, except the only name mangling done is inserting "_g" + * before the final ".so" if the VM was invoked by the name "java_g". There + * may be a security check, of <code>checkLink</code>. + * + * <p> + * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * + * @param filename the file to load + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the library is not found + */ + public void load(String filename) + { + load(filename, VMStackWalker.getCallingClassLoader()); + } + + /** + * Same as <code>load(String)</code> but using the given loader. + * + * @param filename the file to load + * @param loader class loader, or <code>null</code> for the boot loader + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the library is not found + */ + void load(String filename, ClassLoader loader) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkLink(filename); + if (loadLib(filename, loader) == 0) + throw new UnsatisfiedLinkError("Could not load library " + filename); + } + + /** + * Do a security check on the filename and then load the native library. + * + * @param filename the file to load + * @param loader class loader, or <code>null</code> for the boot loader + * @return 0 on failure, nonzero on success + * @throws SecurityException if file read permission is denied + */ + private static int loadLib(String filename, ClassLoader loader) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkRead(filename); + return VMRuntime.nativeLoad(filename, loader); + } + + /** + * Load a native library using a system-independent "short name" for the + * library. It will be transformed to a correct filename in a + * system-dependent manner (for example, in Windows, "mylib" will be turned + * into "mylib.dll"). This is done as follows: if the context that called + * load has a ClassLoader cl, then <code>cl.findLibrary(libpath)</code> is + * used to convert the name. If that result was null, or there was no class + * loader, this searches each directory of the system property + * <code>java.library.path</code> for a file named + * <code>System.mapLibraryName(libname)</code>. There may be a security + * check, of <code>checkLink</code>. + * + * <p>Note: Besides <code>java.library.path</code> a VM may chose to search + * for native libraries in a path that is specified by the + * <code>gnu.classpath.boot.library.path</code> system property. However + * this is for internal usage or development of GNU Classpath only. + * <b>A Java application must not load a non-system library by changing + * this property otherwise it will break compatibility.</b></p> + * + * <p> + * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * + * @param libname the library to load + * + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the library is not found + * + * @see System#mapLibraryName(String) + * @see ClassLoader#findLibrary(String) + */ + public void loadLibrary(String libname) + { + loadLibrary(libname, VMStackWalker.getCallingClassLoader()); + } + + /** + * Same as <code>loadLibrary(String)</code> but using the given loader. + * + * @param libname the library to load + * @param loader class loader, or <code>null</code> for the boot loader + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the library is not found + */ + void loadLibrary(String libname, ClassLoader loader) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe! + if (sm != null) + sm.checkLink(libname); + String filename; + if (loader != null && (filename = loader.findLibrary(libname)) != null) + { + if (loadLib(filename, loader) != 0) + return; + } + else + { + filename = VMRuntime.mapLibraryName(libname); + for (int i = 0; i < libpath.length; i++) + if (loadLib(libpath[i] + filename, loader) != 0) + return; + } + throw new UnsatisfiedLinkError("Native library `" + libname + + "' not found (as file `" + filename + "') in gnu.classpath.boot.library.path and java.library.path"); + } + + /** + * Return a localized version of this InputStream, meaning all characters + * are localized before they come out the other end. + * + * @param in the stream to localize + * @return the localized stream + * @deprecated <code>InputStreamReader</code> is the preferred way to read + * local encodings + * @XXX This implementation does not localize, yet. + */ + public InputStream getLocalizedInputStream(InputStream in) + { + return in; + } + + /** + * Return a localized version of this OutputStream, meaning all characters + * are localized before they are sent to the other end. + * + * @param out the stream to localize + * @return the localized stream + * @deprecated <code>OutputStreamWriter</code> is the preferred way to write + * local encodings + * @XXX This implementation does not localize, yet. + */ + public OutputStream getLocalizedOutputStream(OutputStream out) + { + return out; + } +} // class Runtime diff --git a/libjava/classpath/java/lang/RuntimeException.java b/libjava/classpath/java/lang/RuntimeException.java new file mode 100644 index 0000000..72cf087 --- /dev/null +++ b/libjava/classpath/java/lang/RuntimeException.java @@ -0,0 +1,102 @@ +/* RuntimeException.java -- root of all unchecked exceptions + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * All exceptions which are subclasses of <code>RuntimeException</code> + * can be thrown at any time during the execution of a Java virtual machine. + * Methods which throw these exceptions are not required to declare them + * in their throws clause. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @status updated to 1.4 + */ +public class RuntimeException extends Exception +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -7034897190745766939L; + + /** + * Create an exception without a message. The cause remains uninitialized. + * + * @see #initCause(Throwable) + */ + public RuntimeException() + { + } + + /** + * Create an exception with a message. The cause remains uninitialized. + * + * @param s the message string + * @see #initCause(Throwable) + */ + public RuntimeException(String s) + { + super(s); + } + + /** + * Create an exception with a message and a cause. + * + * @param s the message string + * @param cause the cause of this exception + * @since 1.4 + */ + public RuntimeException(String s, Throwable cause) + { + super(s, cause); + } + + /** + * Create an exception with the given cause, and a message of + * <code>cause == null ? null : cause.toString()</code>. + * + * @param cause the cause of this exception + * @since 1.4 + */ + public RuntimeException(Throwable cause) + { + super(cause); + } +} diff --git a/libjava/classpath/java/lang/RuntimePermission.java b/libjava/classpath/java/lang/RuntimePermission.java new file mode 100644 index 0000000..ca33307 --- /dev/null +++ b/libjava/classpath/java/lang/RuntimePermission.java @@ -0,0 +1,208 @@ +/* RuntimePermission.java -- permission for a secure runtime action + Copyright (C) 1998, 2000, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.security.BasicPermission; + +/** + * A <code>RuntimePermission</code> contains a permission name, but no + * actions list. This means you either have the permission or you don't. + * + * Permission names have the follow the hierarchial property naming + * convention. In addition, an asterisk may appear at the end of a + * name if following a period or by itself. + * + * <table border=1> + * <tr><th>Valid names</th><th>Invalid names</th></tr> + * <tr><td>"accessClassInPackage.*","*"</td> + * <td>"**", "*x", "*.a"</td></tr> + * </table> + * <br> + * + * The following table provides a list of all the possible RuntimePermission + * permission names with a description of what that permission allows.<br> + * <table border=1> + * <tr><th>Permission Name</th><th>Permission Allows</th><th>Risks</th</tr> + * <tr> + * <td><code>createClassLoader</code></td> + * <td>creation of a class loader</td> + * <td>a class loader can load rogue classes which bypass all security + * permissions</td></tr> + * <tr> + * <td><code>getClassLoader</code></td> + * <td>retrieval of the class loader for the calling class</td> + * <td>rogue code could load classes not otherwise available</td></tr> + * <tr> + * <td><code>setContextClassLoader</code></td> + * <td>allows the setting of the context class loader used by a thread</td> + * <td>rogue code could change the context class loader needed by system + * threads</td></tr> + * <tr> + * <td><code>setSecurityManager</code></td> + * <td>allows the application to replace the security manager</td> + * <td>the new manager may be less restrictive, so that rogue code can + * bypass existing security checks</td></tr> + * <tr> + * <td><code>createSecurityManager</code></td> + * <td>allows the application to create a new security manager</td> + * <td>rogue code can use the new security manager to discover information + * about the execution stack</td></tr> + * <tr> + * <td><code>exitVM</code></td> + * <td>allows the application to halt the virtual machine</td> + * <td>rogue code can mount a denial-of-service attack by killing the + * virtual machine</td></tr> + * <tr> + * <td><code>shutdownHooks</code></td> + * <td>allows registration and modification of shutdown hooks</td> + * <td>rogue code can add a hook that interferes with clean + * virtual machine shutdown</td></tr> + * <tr> + * <td><code>setFactory</code></td> + * <td>allows the application to set the socket factory for socket, + * server socket, stream handler, or RMI socket factory.</td> + * <td>rogue code can create a rogue network object which mangles or + * intercepts data</td></tr> + * <tr> + * <td><code>setIO</code></td> + * <td>allows the application to set System.out, System.in, and + * System.err</td> + * <td>rogue code could sniff user input and intercept or mangle + * output</td></tr> + * <tr> + * <td><code>modifyThread</code></td> + * <td>allows the application to modify any thread in the virtual machine + * using any of the methods <code>stop</code>, <code>resume</code>, + * <code>suspend</code>, <code>setPriority</code>, and + * <code>setName</code> of classs <code>Thread</code></td> + * <td>rogue code could adversely modify system or user threads</td></tr> + * <tr> + * <td><code>stopThread</code></td> + * <td>allows the application to <code>stop</code> any thread it has + * access to in the system</td> + * <td>rogue code can stop arbitrary threads</td></tr> + * <tr> + * <td><code>modifyThreadGroup</code></td> + * <td>allows the application to modify thread groups using any of the + * methods <code>destroy</code>, <code>resume</code>, + * <code>setDaemon</code>, <code>setMaxPriority</code>, + * <code>stop</code>, and <code>suspend</code> of the class + * <code>ThreadGroup</code></td> + * <td>rogue code can mount a denial-of-service attack by changing run + * priorities</td></tr> + * <tr> + * <td><code>getProtectionDomain</code></td> + * <td>retrieve a class's ProtectionDomain</td> + * <td>rogue code can gain information about the security policy, to + * prepare a better attack</td></tr> + * <tr> + * <td><code>readFileDescriptor</code></td> + * <td>read a file descriptor</td> + * <td>rogue code can read sensitive information</td></tr> + * <tr> + * <td><code>writeFileDescriptor</code></td> + * <td>write a file descriptor</td> + * <td>rogue code can write files, including viruses, and can modify the + * virtual machine binary; if not just fill up the disk</td></tr> + * <tr> + * <td><code>loadLibrary.</code><em>library name</em></td> + * <td>dynamic linking of the named library</td> + * <td>native code can bypass many security checks of pure Java</td></tr> + * <tr> + * <td><code>accessClassInPackage.</code><em>package name</em></td> + * <td>access to a package via a ClassLoader</td> + * <td>rogue code can access classes not normally available</td></tr> + * <tr> + * <td><code>defineClassInPackage.</code><em>package name</em></td> + * <td>define a class inside a given package</td> + * <td>rogue code can install rogue classes, including in trusted packages + * like java.security or java.lang</td></tr> + * <tr> + * <td><code>accessDeclaredMembers</code></td> + * <td>access declared class members via reflection</td> + * <td>rogue code can discover information, invoke methods, or modify fields + * that are not otherwise available</td></tr> + * <tr> + * <td><code>queuePrintJob</code></td> + * <td>initiate a print job</td> + * <td>rogue code could make a hard copy of sensitive information, or + * simply waste paper</td></tr> + * </table> + * + * @author Brian Jones + * @author Eric Blake (ebb9@email.byu.edu) + * @see BasicPermission + * @see Permission + * @see SecurityManager + * @since 1.2 + * @status updated to 1.4 + */ +public final class RuntimePermission extends BasicPermission +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = 7399184964622342223L; + + /** + * Create a new permission with the specified name. + * + * @param permissionName the name of the granted permission + * @throws NullPointerException if name is null + * @throws IllegalArgumentException thrown if name is empty or invalid + */ + public RuntimePermission(String permissionName) + { + super(permissionName); + } + + /** + * Create a new permission with the specified name. The actions argument + * is ignored, as runtime permissions have no actions. + * + * @param permissionName the name of the granted permission + * @param actions ignored + * @throws NullPointerException if name is null + * @throws IllegalArgumentException thrown if name is empty or invalid + */ + public RuntimePermission(String permissionName, String actions) + { + super(permissionName); + } +} diff --git a/libjava/classpath/java/lang/SecurityException.java b/libjava/classpath/java/lang/SecurityException.java new file mode 100644 index 0000000..a95d797 --- /dev/null +++ b/libjava/classpath/java/lang/SecurityException.java @@ -0,0 +1,74 @@ +/* SecurityException.java -- thrown to indicate a security violation + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * The security manager will throw this exception to indicate a security + * violation. This can occur any time an operation is attempted which is + * deemed unsafe by the current security policies. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @see SecurityManager + * @status updated to 1.4 + */ +public class SecurityException extends RuntimeException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 6878364983674394167L; + + /** + * Create an exception without a message. + */ + public SecurityException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public SecurityException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/SecurityManager.java b/libjava/classpath/java/lang/SecurityManager.java new file mode 100644 index 0000000..ef9e7597 --- /dev/null +++ b/libjava/classpath/java/lang/SecurityManager.java @@ -0,0 +1,1062 @@ +/* SecurityManager.java -- security checks for privileged actions + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import gnu.classpath.VMStackWalker; + +import java.awt.AWTPermission; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FilePermission; +import java.lang.reflect.Member; +import java.net.InetAddress; +import java.net.SocketPermission; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.AllPermission; +import java.security.Permission; +import java.security.PrivilegedAction; +import java.security.Security; +import java.security.SecurityPermission; +import java.util.PropertyPermission; +import java.util.StringTokenizer; + +/** + * SecurityManager is a class you can extend to create your own Java + * security policy. By default, there is no SecurityManager installed in + * 1.1, which means that all things are permitted to all people. The security + * manager, if set, is consulted before doing anything with potentially + * dangerous results, and throws a <code>SecurityException</code> if the + * action is forbidden. + * + * <p>A typical check is as follows, just before the dangerous operation:<br> + * <pre> + * SecurityManager sm = System.getSecurityManager(); + * if (sm != null) + * sm.checkABC(<em>argument</em>, ...); + * </pre> + * Note that this is thread-safe, by caching the security manager in a local + * variable rather than risking a NullPointerException if the mangager is + * changed between the check for null and before the permission check. + * + * <p>The special method <code>checkPermission</code> is a catchall, and + * the default implementation calls + * <code>AccessController.checkPermission</code>. In fact, all the other + * methods default to calling checkPermission. + * + * <p>Sometimes, the security check needs to happen from a different context, + * such as when called from a worker thread. In such cases, use + * <code>getSecurityContext</code> to take a snapshot that can be passed + * to the worker thread:<br> + * <pre> + * Object context = null; + * SecurityManager sm = System.getSecurityManager(); + * if (sm != null) + * context = sm.getSecurityContext(); // defaults to an AccessControlContext + * // now, in worker thread + * if (sm != null) + * sm.checkPermission(permission, context); + * </pre> + * + * <p>Permissions fall into these categories: File, Socket, Net, Security, + * Runtime, Property, AWT, Reflect, and Serializable. Each of these + * permissions have a property naming convention, that follows a hierarchical + * naming convention, to make it easy to grant or deny several permissions + * at once. Some permissions also take a list of permitted actions, such + * as "read" or "write", to fine-tune control even more. The permission + * <code>java.security.AllPermission</code> grants all permissions. + * + * <p>The default methods in this class deny all things to all people. You + * must explicitly grant permission for anything you want to be legal when + * subclassing this class. + * + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @see ClassLoader + * @see SecurityException + * @see #checkTopLevelWindow(Object) + * @see System#getSecurityManager() + * @see System#setSecurityManager(SecurityManager) + * @see AccessController + * @see AccessControlContext + * @see AccessControlException + * @see Permission + * @see BasicPermission + * @see java.io.FilePermission + * @see java.net.SocketPermission + * @see java.util.PropertyPermission + * @see RuntimePermission + * @see java.awt.AWTPermission + * @see Policy + * @see SecurityPermission + * @see ProtectionDomain + * @since 1.0 + * @status still missing 1.4 functionality + */ +public class SecurityManager +{ + /** + * The current security manager. This is located here instead of in + * System, to avoid security problems, as well as bootstrap issues. + * Make sure to access it in a thread-safe manner; it is package visible + * to avoid overhead in java.lang. + */ + static volatile SecurityManager current; + + /** + * Tells whether or not the SecurityManager is currently performing a + * security check. + * @deprecated Use {@link #checkPermission(Permission)} instead. + */ + protected boolean inCheck; + + /** + * Construct a new security manager. There may be a security check, of + * <code>RuntimePermission("createSecurityManager")</code>. + * + * @throws SecurityException if permission is denied + */ + public SecurityManager() + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new RuntimePermission("createSecurityManager")); + } + + /** + * Tells whether or not the SecurityManager is currently performing a + * security check. + * + * @return true if the SecurityManager is in a security check + * @see #inCheck + * @deprecated use {@link #checkPermission(Permission)} instead + */ + public boolean getInCheck() + { + return inCheck; + } + + /** + * Get a list of all the classes currently executing methods on the Java + * stack. getClassContext()[0] is the currently executing method (ie. the + * class that CALLED getClassContext, not SecurityManager). + * + * @return an array of classes on the Java execution stack + */ + protected Class[] getClassContext() + { + Class[] stack1 = VMStackWalker.getClassContext(); + Class[] stack2 = new Class[stack1.length - 1]; + System.arraycopy(stack1, 1, stack2, 0, stack1.length - 1); + return stack2; + } + + /** + * Find the ClassLoader of the first non-system class on the execution + * stack. A non-system class is one whose ClassLoader is not equal to + * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This + * will return null in three cases: + * + * <ul> + * <li>All methods on the stack are from system classes</li> + * <li>All methods on the stack up to the first "privileged" caller, as + * created by {@link AccessController.doPrivileged(PrivilegedAction)}, + * are from system classes</li> + * <li>A check of <code>java.security.AllPermission</code> succeeds.</li> + * </ul> + * + * @return the most recent non-system ClassLoader on the execution stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected ClassLoader currentClassLoader() + { + Class cl = currentLoadedClass(); + return cl != null ? cl.getClassLoader() : null; + } + + /** + * Find the first non-system class on the execution stack. A non-system + * class is one whose ClassLoader is not equal to + * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This + * will return null in three cases: + * + * <ul> + * <li>All methods on the stack are from system classes</li> + * <li>All methods on the stack up to the first "privileged" caller, as + * created by {@link AccessController.doPrivileged(PrivilegedAction)}, + * are from system classes</li> + * <li>A check of <code>java.security.AllPermission</code> succeeds.</li> + * </ul> + * + * @return the most recent non-system Class on the execution stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected Class currentLoadedClass() + { + int i = classLoaderDepth(); + return i >= 0 ? getClassContext()[i] : null; + } + + /** + * Get the depth of a particular class on the execution stack. + * + * @param className the fully-qualified name to search for + * @return the index of the class on the stack, or -1 + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected int classDepth(String className) + { + Class[] c = getClassContext(); + for (int i = 0; i < c.length; i++) + if (className.equals(c[i].getName())) + return i; + return -1; + } + + /** + * Get the depth on the execution stack of the most recent non-system class. + * A non-system class is one whose ClassLoader is not equal to + * {@link ClassLoader#getSystemClassLoader()} or its ancestors. This + * will return -1 in three cases: + * + * <ul> + * <li>All methods on the stack are from system classes</li> + * <li>All methods on the stack up to the first "privileged" caller, as + * created by {@link AccessController.doPrivileged(PrivilegedAction)}, + * are from system classes</li> + * <li>A check of <code>java.security.AllPermission</code> succeeds.</li> + * </ul> + * + * @return the index of the most recent non-system Class on the stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected int classLoaderDepth() + { + try + { + checkPermission(new AllPermission()); + } + catch (SecurityException e) + { + Class[] c = getClassContext(); + for (int i = 0; i < c.length; i++) + if (c[i].getClassLoader() != null) + // XXX Check if c[i] is AccessController, or a system class. + return i; + } + return -1; + } + + /** + * Tell whether the specified class is on the execution stack. + * + * @param className the fully-qualified name of the class to find + * @return whether the specified class is on the execution stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected boolean inClass(String className) + { + return classDepth(className) != -1; + } + + /** + * Tell whether there is a class loaded with an explicit ClassLoader on + * the stack. + * + * @return whether a class with an explicit ClassLoader is on the stack + * @deprecated use {@link #checkPermission(Permission)} instead + */ + protected boolean inClassLoader() + { + return classLoaderDepth() != -1; + } + + /** + * Get an implementation-dependent Object that contains enough information + * about the current environment to be able to perform standard security + * checks later. This is used by trusted methods that need to verify that + * their callers have sufficient access to perform certain operations. + * + * <p>Currently the only methods that use this are checkRead() and + * checkConnect(). The default implementation returns an + * <code>AccessControlContext</code>. + * + * @return a security context + * @see #checkConnect(String, int, Object) + * @see #checkRead(String, Object) + * @see AccessControlContext + * @see AccessController#getContext() + */ + public Object getSecurityContext() + { + return AccessController.getContext(); + } + + /** + * Check if the current thread is allowed to perform an operation that + * requires the specified <code>Permission</code>. This defaults to + * <code>AccessController.checkPermission</code>. + * + * @param perm the <code>Permission</code> required + * @throws SecurityException if permission is denied + * @throws NullPointerException if perm is null + * @since 1.2 + */ + public void checkPermission(Permission perm) + { + AccessController.checkPermission(perm); + } + + /** + * Check if the current thread is allowed to perform an operation that + * requires the specified <code>Permission</code>. This is done in a + * context previously returned by <code>getSecurityContext()</code>. The + * default implementation expects context to be an AccessControlContext, + * and it calls <code>AccessControlContext.checkPermission(perm)</code>. + * + * @param perm the <code>Permission</code> required + * @param context a security context + * @throws SecurityException if permission is denied, or if context is + * not an AccessControlContext + * @throws NullPointerException if perm is null + * @see #getSecurityContext() + * @see AccessControlContext#checkPermission(Permission) + * @since 1.2 + */ + public void checkPermission(Permission perm, Object context) + { + if (! (context instanceof AccessControlContext)) + throw new SecurityException("Missing context"); + ((AccessControlContext) context).checkPermission(perm); + } + + /** + * Check if the current thread is allowed to create a ClassLoader. This + * method is called from ClassLoader.ClassLoader(), and checks + * <code>RuntimePermission("createClassLoader")</code>. If you override + * this, you should call <code>super.checkCreateClassLoader()</code> rather + * than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see ClassLoader#ClassLoader() + */ + public void checkCreateClassLoader() + { + checkPermission(new RuntimePermission("createClassLoader")); + } + + /** + * Check if the current thread is allowed to modify another Thread. This is + * called by Thread.stop(), suspend(), resume(), interrupt(), destroy(), + * setPriority(), setName(), and setDaemon(). The default implementation + * checks <code>RuntimePermission("modifyThread")</code> on system threads + * (ie. threads in ThreadGroup with a null parent), and returns silently on + * other threads. + * + * <p>If you override this, you must do two things. First, call + * <code>super.checkAccess(t)</code>, to make sure you are not relaxing + * requirements. Second, if the calling thread has + * <code>RuntimePermission("modifyThread")</code>, return silently, so that + * core classes (the Classpath library!) can modify any thread. + * + * @param thread the other Thread to check + * @throws SecurityException if permission is denied + * @throws NullPointerException if thread is null + * @see Thread#stop() + * @see Thread#suspend() + * @see Thread#resume() + * @see Thread#setPriority(int) + * @see Thread#setName(String) + * @see Thread#setDaemon(boolean) + */ + public void checkAccess(Thread thread) + { + if (thread.getThreadGroup() != null + && thread.getThreadGroup().getParent() != null) + checkPermission(new RuntimePermission("modifyThread")); + } + + /** + * Check if the current thread is allowed to modify a ThreadGroup. This is + * called by Thread.Thread() (to add a thread to the ThreadGroup), + * ThreadGroup.ThreadGroup() (to add this ThreadGroup to a parent), + * ThreadGroup.stop(), suspend(), resume(), interrupt(), destroy(), + * setDaemon(), and setMaxPriority(). The default implementation + * checks <code>RuntimePermission("modifyThread")</code> on the system group + * (ie. the one with a null parent), and returns silently on other groups. + * + * <p>If you override this, you must do two things. First, call + * <code>super.checkAccess(t)</code>, to make sure you are not relaxing + * requirements. Second, if the calling thread has + * <code>RuntimePermission("modifyThreadGroup")</code>, return silently, + * so that core classes (the Classpath library!) can modify any thread. + * + * @param g the ThreadGroup to check + * @throws SecurityException if permission is denied + * @throws NullPointerException if g is null + * @see Thread#Thread() + * @see ThreadGroup#ThreadGroup() + * @see ThreadGroup#stop() + * @see ThreadGroup#suspend() + * @see ThreadGroup#resume() + * @see ThreadGroup#interrupt() + * @see ThreadGroup#setDaemon(boolean) + * @see ThreadGroup#setMaxPriority(int) + */ + public void checkAccess(ThreadGroup g) + { + if (g.getParent() != null) + checkPermission(new RuntimePermission("modifyThreadGroup")); + } + + /** + * Check if the current thread is allowed to exit the JVM with the given + * status. This method is called from Runtime.exit() and Runtime.halt(). + * The default implementation checks + * <code>RuntimePermission("exitVM")</code>. If you override this, call + * <code>super.checkExit</code> rather than throwing an exception. + * + * @param status the status to exit with + * @throws SecurityException if permission is denied + * @see Runtime#exit(int) + * @see Runtime#halt(int) + */ + public void checkExit(int status) + { + checkPermission(new RuntimePermission("exitVM")); + } + + /** + * Check if the current thread is allowed to execute the given program. This + * method is called from Runtime.exec(). If the name is an absolute path, + * the default implementation checks + * <code>FilePermission(program, "execute")</code>, otherwise it checks + * <code>FilePermission("<<ALL FILES>>", "execute")</code>. If + * you override this, call <code>super.checkExec</code> rather than + * throwing an exception. + * + * @param program the name of the program to exec + * @throws SecurityException if permission is denied + * @throws NullPointerException if program is null + * @see Runtime#exec(String[], String[], File) + */ + public void checkExec(String program) + { + if (! program.equals(new File(program).getAbsolutePath())) + program = "<<ALL FILES>>"; + checkPermission(new FilePermission(program, "execute")); + } + + /** + * Check if the current thread is allowed to link in the given native + * library. This method is called from Runtime.load() (and hence, by + * loadLibrary() as well). The default implementation checks + * <code>RuntimePermission("loadLibrary." + filename)</code>. If you + * override this, call <code>super.checkLink</code> rather than throwing + * an exception. + * + * @param filename the full name of the library to load + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see Runtime#load(String) + */ + public void checkLink(String filename) + { + // Use the toString() hack to do the null check. + checkPermission(new RuntimePermission("loadLibrary." + + filename.toString())); + } + + /** + * Check if the current thread is allowed to read the given file using the + * FileDescriptor. This method is called from + * FileInputStream.FileInputStream(). The default implementation checks + * <code>RuntimePermission("readFileDescriptor")</code>. If you override + * this, call <code>super.checkRead</code> rather than throwing an + * exception. + * + * @param desc the FileDescriptor representing the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if desc is null + * @see FileInputStream#FileInputStream(FileDescriptor) + */ + public void checkRead(FileDescriptor desc) + { + if (desc == null) + throw new NullPointerException(); + checkPermission(new RuntimePermission("readFileDescriptor")); + } + + /** + * Check if the current thread is allowed to read the given file. This + * method is called from FileInputStream.FileInputStream(), + * RandomAccessFile.RandomAccessFile(), File.exists(), canRead(), isFile(), + * isDirectory(), lastModified(), length() and list(). The default + * implementation checks <code>FilePermission(filename, "read")</code>. If + * you override this, call <code>super.checkRead</code> rather than + * throwing an exception. + * + * @param filename the full name of the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see File + * @see FileInputStream#FileInputStream(String) + * @see RandomAccessFile#RandomAccessFile(String) + */ + public void checkRead(String filename) + { + checkPermission(new FilePermission(filename, "read")); + } + + /** + * Check if the current thread is allowed to read the given file. using the + * given security context. The context must be a result of a previous call + * to <code>getSecurityContext()</code>. The default implementation checks + * <code>AccessControlContext.checkPermission(new FilePermission(filename, + * "read"))</code>. If you override this, call <code>super.checkRead</code> + * rather than throwing an exception. + * + * @param filename the full name of the file to access + * @param context the context to determine access for + * @throws SecurityException if permission is denied, or if context is + * not an AccessControlContext + * @throws NullPointerException if filename is null + * @see #getSecurityContext() + * @see AccessControlContext#checkPermission(Permission) + */ + public void checkRead(String filename, Object context) + { + if (! (context instanceof AccessControlContext)) + throw new SecurityException("Missing context"); + AccessControlContext ac = (AccessControlContext) context; + ac.checkPermission(new FilePermission(filename, "read")); + } + + /** + * Check if the current thread is allowed to write the given file using the + * FileDescriptor. This method is called from + * FileOutputStream.FileOutputStream(). The default implementation checks + * <code>RuntimePermission("writeFileDescriptor")</code>. If you override + * this, call <code>super.checkWrite</code> rather than throwing an + * exception. + * + * @param desc the FileDescriptor representing the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if desc is null + * @see FileOutputStream#FileOutputStream(FileDescriptor) + */ + public void checkWrite(FileDescriptor desc) + { + if (desc == null) + throw new NullPointerException(); + checkPermission(new RuntimePermission("writeFileDescriptor")); + } + + /** + * Check if the current thread is allowed to write the given file. This + * method is called from FileOutputStream.FileOutputStream(), + * RandomAccessFile.RandomAccessFile(), File.canWrite(), mkdir(), and + * renameTo(). The default implementation checks + * <code>FilePermission(filename, "write")</code>. If you override this, + * call <code>super.checkWrite</code> rather than throwing an exception. + * + * @param filename the full name of the file to access + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see File + * @see File#canWrite() + * @see File#mkdir() + * @see File#renameTo() + * @see FileOutputStream#FileOutputStream(String) + * @see RandomAccessFile#RandomAccessFile(String) + */ + public void checkWrite(String filename) + { + checkPermission(new FilePermission(filename, "write")); + } + + /** + * Check if the current thread is allowed to delete the given file. This + * method is called from File.delete(). The default implementation checks + * <code>FilePermission(filename, "delete")</code>. If you override this, + * call <code>super.checkDelete</code> rather than throwing an exception. + * + * @param filename the full name of the file to delete + * @throws SecurityException if permission is denied + * @throws NullPointerException if filename is null + * @see File#delete() + */ + public void checkDelete(String filename) + { + checkPermission(new FilePermission(filename, "delete")); + } + + /** + * Check if the current thread is allowed to connect to a given host on a + * given port. This method is called from Socket.Socket(). A port number + * of -1 indicates the caller is attempting to determine an IP address, so + * the default implementation checks + * <code>SocketPermission(host, "resolve")</code>. Otherwise, the default + * implementation checks + * <code>SocketPermission(host + ":" + port, "connect")</code>. If you + * override this, call <code>super.checkConnect</code> rather than throwing + * an exception. + * + * @param host the host to connect to + * @param port the port to connect on + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @see Socket#Socket() + */ + public void checkConnect(String host, int port) + { + if (port == -1) + checkPermission(new SocketPermission(host, "resolve")); + else + // Use the toString() hack to do the null check. + checkPermission(new SocketPermission(host.toString() + ":" + port, + "connect")); + } + + /** + * Check if the current thread is allowed to connect to a given host on a + * given port, using the given security context. The context must be a + * result of a previous call to <code>getSecurityContext</code>. A port + * number of -1 indicates the caller is attempting to determine an IP + * address, so the default implementation checks + * <code>AccessControlContext.checkPermission(new SocketPermission(host, + * "resolve"))</code>. Otherwise, the default implementation checks + * <code>AccessControlContext.checkPermission(new SocketPermission(host + * + ":" + port, "connect"))</code>. If you override this, call + * <code>super.checkConnect</code> rather than throwing an exception. + * + * @param host the host to connect to + * @param port the port to connect on + * @param context the context to determine access for + * + * @throws SecurityException if permission is denied, or if context is + * not an AccessControlContext + * @throws NullPointerException if host is null + * + * @see #getSecurityContext() + * @see AccessControlContext#checkPermission(Permission) + */ + public void checkConnect(String host, int port, Object context) + { + if (! (context instanceof AccessControlContext)) + throw new SecurityException("Missing context"); + AccessControlContext ac = (AccessControlContext) context; + if (port == -1) + ac.checkPermission(new SocketPermission(host, "resolve")); + else + // Use the toString() hack to do the null check. + ac.checkPermission(new SocketPermission(host.toString() + ":" + port, + "connect")); + } + + /** + * Check if the current thread is allowed to listen to a specific port for + * data. This method is called by ServerSocket.ServerSocket(). The default + * implementation checks + * <code>SocketPermission("localhost:" + (port == 0 ? "1024-" : "" + port), + * "listen")</code>. If you override this, call + * <code>super.checkListen</code> rather than throwing an exception. + * + * @param port the port to listen on + * @throws SecurityException if permission is denied + * @see ServerSocket#ServerSocket(int) + */ + public void checkListen(int port) + { + checkPermission(new SocketPermission("localhost:" + + (port == 0 ? "1024-" : "" +port), + "listen")); + } + + /** + * Check if the current thread is allowed to accept a connection from a + * particular host on a particular port. This method is called by + * ServerSocket.implAccept(). The default implementation checks + * <code>SocketPermission(host + ":" + port, "accept")</code>. If you + * override this, call <code>super.checkAccept</code> rather than throwing + * an exception. + * + * @param host the host which wishes to connect + * @param port the port the connection will be on + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @see ServerSocket#accept() + */ + public void checkAccept(String host, int port) + { + // Use the toString() hack to do the null check. + checkPermission(new SocketPermission(host.toString() + ":" + port, + "accept")); + } + + /** + * Check if the current thread is allowed to read and write multicast to + * a particular address. The default implementation checks + * <code>SocketPermission(addr.getHostAddress(), "accept,connect")</code>. + * If you override this, call <code>super.checkMulticast</code> rather than + * throwing an exception. + * + * @param addr the address to multicast to + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @since 1.1 + */ + public void checkMulticast(InetAddress addr) + { + checkPermission(new SocketPermission(addr.getHostAddress(), + "accept,connect")); + } + + /** + *Check if the current thread is allowed to read and write multicast to + * a particular address with a particular ttl (time-to-live) value. The + * default implementation ignores ttl, and checks + * <code>SocketPermission(addr.getHostAddress(), "accept,connect")</code>. + * If you override this, call <code>super.checkMulticast</code> rather than + * throwing an exception. + * + * @param addr the address to multicast to + * @param ttl value in use for multicast send + * @throws SecurityException if permission is denied + * @throws NullPointerException if host is null + * @since 1.1 + * @deprecated use {@link #checkPermission(Permission)} instead + */ + public void checkMulticast(InetAddress addr, byte ttl) + { + checkPermission(new SocketPermission(addr.getHostAddress(), + "accept,connect")); + } + + /** + * Check if the current thread is allowed to read or write all the system + * properties at once. This method is called by System.getProperties() + * and setProperties(). The default implementation checks + * <code>PropertyPermission("*", "read,write")</code>. If you override + * this, call <code>super.checkPropertiesAccess</code> rather than + * throwing an exception. + * + * @throws SecurityException if permission is denied + * @see System#getProperties() + * @see System#setProperties(Properties) + */ + public void checkPropertiesAccess() + { + checkPermission(new PropertyPermission("*", "read,write")); + } + + /** + * Check if the current thread is allowed to read a particular system + * property (writes are checked directly via checkPermission). This method + * is called by System.getProperty() and setProperty(). The default + * implementation checks <code>PropertyPermission(key, "read")</code>. If + * you override this, call <code>super.checkPropertyAccess</code> rather + * than throwing an exception. + * + * @param key the key of the property to check + * + * @throws SecurityException if permission is denied + * @throws NullPointerException if key is null + * @throws IllegalArgumentException if key is "" + * + * @see System#getProperty(String) + */ + public void checkPropertyAccess(String key) + { + checkPermission(new PropertyPermission(key, "read")); + } + + /** + * Check if the current thread is allowed to create a top-level window. If + * it is not, the operation should still go through, but some sort of + * nonremovable warning should be placed on the window to show that it + * is untrusted. This method is called by Window.Window(). The default + * implementation checks + * <code>AWTPermission("showWindowWithoutWarningBanner")</code>, and returns + * true if no exception was thrown. If you override this, use + * <code>return super.checkTopLevelWindow</code> rather than returning + * false. + * + * @param window the window to create + * @return true if there is permission to show the window without warning + * @throws NullPointerException if window is null + * @see Window#Window(Frame) + */ + public boolean checkTopLevelWindow(Object window) + { + if (window == null) + throw new NullPointerException(); + try + { + checkPermission(new AWTPermission("showWindowWithoutWarningBanner")); + return true; + } + catch (SecurityException e) + { + return false; + } + } + + /** + * Check if the current thread is allowed to create a print job. This + * method is called by Toolkit.getPrintJob(). The default implementation + * checks <code>RuntimePermission("queuePrintJob")</code>. If you override + * this, call <code>super.checkPrintJobAccess</code> rather than throwing + * an exception. + * + * @throws SecurityException if permission is denied + * @see Toolkit#getPrintJob(Frame, String, Properties) + * @since 1.1 + */ + public void checkPrintJobAccess() + { + checkPermission(new RuntimePermission("queuePrintJob")); + } + + /** + * Check if the current thread is allowed to use the system clipboard. This + * method is called by Toolkit.getSystemClipboard(). The default + * implementation checks <code>AWTPermission("accessClipboard")</code>. If + * you override this, call <code>super.checkSystemClipboardAccess</code> + * rather than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see Toolkit#getSystemClipboard() + * @since 1.1 + */ + public void checkSystemClipboardAccess() + { + checkPermission(new AWTPermission("accessClipboard")); + } + + /** + * Check if the current thread is allowed to use the AWT event queue. This + * method is called by Toolkit.getSystemEventQueue(). The default + * implementation checks <code>AWTPermission("accessEventQueue")</code>. + * you override this, call <code>super.checkAwtEventQueueAccess</code> + * rather than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see Toolkit#getSystemEventQueue() + * @since 1.1 + */ + public void checkAwtEventQueueAccess() + { + checkPermission(new AWTPermission("accessEventQueue")); + } + + /** + * Check if the current thread is allowed to access the specified package + * at all. This method is called by ClassLoader.loadClass() in user-created + * ClassLoaders. The default implementation gets a list of all restricted + * packages, via <code>Security.getProperty("package.access")</code>. Then, + * if packageName starts with or equals any restricted package, it checks + * <code>RuntimePermission("accessClassInPackage." + packageName)</code>. + * If you override this, you should call + * <code>super.checkPackageAccess</code> before doing anything else. + * + * @param packageName the package name to check access to + * @throws SecurityException if permission is denied + * @throws NullPointerException if packageName is null + * @see ClassLoader#loadClass(String, boolean) + * @see Security#getProperty(String) + */ + public void checkPackageAccess(String packageName) + { + checkPackageList(packageName, "package.access", "accessClassInPackage."); + } + + /** + * Check if the current thread is allowed to define a class into the + * specified package. This method is called by ClassLoader.loadClass() in + * user-created ClassLoaders. The default implementation gets a list of all + * restricted packages, via + * <code>Security.getProperty("package.definition")</code>. Then, if + * packageName starts with or equals any restricted package, it checks + * <code>RuntimePermission("defineClassInPackage." + packageName)</code>. + * If you override this, you should call + * <code>super.checkPackageDefinition</code> before doing anything else. + * + * @param packageName the package name to check access to + * @throws SecurityException if permission is denied + * @throws NullPointerException if packageName is null + * @see ClassLoader#loadClass(String, boolean) + * @see Security#getProperty(String) + */ + public void checkPackageDefinition(String packageName) + { + checkPackageList(packageName, "package.definition", "defineClassInPackage."); + } + + /** + * Check if the current thread is allowed to set the current socket factory. + * This method is called by Socket.setSocketImplFactory(), + * ServerSocket.setSocketFactory(), and URL.setURLStreamHandlerFactory(). + * The default implementation checks + * <code>RuntimePermission("setFactory")</code>. If you override this, call + * <code>super.checkSetFactory</code> rather than throwing an exception. + * + * @throws SecurityException if permission is denied + * @see Socket#setSocketImplFactory(SocketImplFactory) + * @see ServerSocket#setSocketFactory(SocketImplFactory) + * @see URL#setURLStreamHandlerFactory(URLStreamHandlerFactory) + */ + public void checkSetFactory() + { + checkPermission(new RuntimePermission("setFactory")); + } + + /** + * Check if the current thread is allowed to get certain types of Methods, + * Fields and Constructors from a Class object. This method is called by + * Class.getMethod[s](), Class.getField[s](), Class.getConstructor[s], + * Class.getDeclaredMethod[s](), Class.getDeclaredField[s](), and + * Class.getDeclaredConstructor[s](). The default implementation allows + * PUBLIC access, and access to classes defined by the same classloader as + * the code performing the reflection. Otherwise, it checks + * <code>RuntimePermission("accessDeclaredMembers")</code>. If you override + * this, do not call <code>super.checkMemberAccess</code>, as this would + * mess up the stack depth check that determines the ClassLoader requesting + * the access. + * + * @param c the Class to check + * @param memberType either DECLARED or PUBLIC + * @throws SecurityException if permission is denied, including when + * memberType is not DECLARED or PUBLIC + * @throws NullPointerException if c is null + * @see Class + * @see Member#DECLARED + * @see Member#PUBLIC + * @since 1.1 + */ + public void checkMemberAccess(Class c, int memberType) + { + if (c == null) + throw new NullPointerException(); + if (memberType == Member.PUBLIC) + return; + // XXX Allow access to classes created by same classloader before next + // check. + checkPermission(new RuntimePermission("accessDeclaredMembers")); + } + + /** + * Test whether a particular security action may be taken. The default + * implementation checks <code>SecurityPermission(action)</code>. If you + * override this, call <code>super.checkSecurityAccess</code> rather than + * throwing an exception. + * + * @param action the desired action to take + * @throws SecurityException if permission is denied + * @throws NullPointerException if action is null + * @throws IllegalArgumentException if action is "" + * @since 1.1 + */ + public void checkSecurityAccess(String action) + { + checkPermission(new SecurityPermission(action)); + } + + /** + * Get the ThreadGroup that a new Thread should belong to by default. Called + * by Thread.Thread(). The default implementation returns the current + * ThreadGroup of the current Thread. <STRONG>Spec Note:</STRONG> it is not + * clear whether the new Thread is guaranteed to pass the + * checkAccessThreadGroup() test when using this ThreadGroup, but I presume + * so. + * + * @return the ThreadGroup to put the new Thread into + * @since 1.1 + */ + public ThreadGroup getThreadGroup() + { + return Thread.currentThread().getThreadGroup(); + } + + /** + * Helper that checks a comma-separated list of restricted packages, from + * <code>Security.getProperty("package.definition")</code>, for the given + * package access permission. If packageName starts with or equals any + * restricted package, it checks + * <code>RuntimePermission(permission + packageName)</code>. + * + * @param packageName the package name to check access to + * @param restriction "package.access" or "package.definition" + * @param permission the base permission, including the '.' + * @throws SecurityException if permission is denied + * @throws NullPointerException if packageName is null + * @see #checkPackageAccess(String) + * @see #checkPackageDefinition(String) + */ + void checkPackageList(String packageName, final String restriction, + String permission) + { + if (packageName == null) + throw new NullPointerException(); + + String list = (String)AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + return Security.getProperty(restriction); + } + }); + + if (list == null || list.equals("")) + return; + + String packageNamePlusDot = packageName + "."; + + StringTokenizer st = new StringTokenizer(list, ","); + while (st.hasMoreTokens()) + { + if (packageNamePlusDot.startsWith(st.nextToken())) + { + Permission p = new RuntimePermission(permission + packageName); + checkPermission(p); + return; + } + } + } +} diff --git a/libjava/classpath/java/lang/Short.java b/libjava/classpath/java/lang/Short.java new file mode 100644 index 0000000..fbeea91 --- /dev/null +++ b/libjava/classpath/java/lang/Short.java @@ -0,0 +1,353 @@ +/* Short.java -- object wrapper for short + Copyright (C) 1998, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * Instances of class <code>Short</code> represent primitive + * <code>short</code> values. + * + * Additionally, this class provides various helper functions and variables + * related to shorts. + * + * @author Paul Fisher + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.1 + * @status updated to 1.4 + */ +public final class Short extends Number implements Comparable +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 7515723908773894738L; + + /** + * The minimum value a <code>short</code> can represent is -32768 (or + * -2<sup>15</sup>). + */ + public static final short MIN_VALUE = -32768; + + /** + * The minimum value a <code>short</code> can represent is 32767 (or + * 2<sup>15</sup>). + */ + public static final short MAX_VALUE = 32767; + + /** + * The primitive type <code>short</code> is represented by this + * <code>Class</code> object. + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('S'); + + /** + * The immutable value of this Short. + * + * @serial the wrapped short + */ + private final short value; + + /** + * Create a <code>Short</code> object representing the value of the + * <code>short</code> argument. + * + * @param value the value to use + */ + public Short(short value) + { + this.value = value; + } + + /** + * Create a <code>Short</code> object representing the value of the + * argument after conversion to a <code>short</code>. + * + * @param s the string to convert + * @throws NumberFormatException if the String cannot be parsed + */ + public Short(String s) + { + value = parseShort(s, 10); + } + + /** + * Converts the <code>short</code> to a <code>String</code> and assumes + * a radix of 10. + * + * @param s the <code>short</code> to convert to <code>String</code> + * @return the <code>String</code> representation of the argument + */ + public static String toString(short s) + { + return String.valueOf(s); + } + + /** + * Converts the specified <code>String</code> into a <code>short</code>. + * This function assumes a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the <code>short</code> value of <code>s</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>short</code> + */ + public static short parseShort(String s) + { + return parseShort(s, 10); + } + + /** + * Converts the specified <code>String</code> into a <code>short</code> + * using the specified radix (base). The string must not be <code>null</code> + * or empty. It may begin with an optional '-', which will negate the answer, + * provided that there are also valid digits. Each digit is parsed as if by + * <code>Character.digit(d, radix)</code>, and must be in the range + * <code>0</code> to <code>radix - 1</code>. Finally, the result must be + * within <code>MIN_VALUE</code> to <code>MAX_VALUE</code>, inclusive. + * Unlike Double.parseDouble, you may not have a leading '+'. + * + * @param s the <code>String</code> to convert + * @param radix the radix (base) to use in the conversion + * @return the <code>String</code> argument converted to <code>short</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>short</code> + */ + public static short parseShort(String s, int radix) + { + int i = Integer.parseInt(s, radix, false); + if ((short) i != i) + throw new NumberFormatException(); + return (short) i; + } + + /** + * Creates a new <code>Short</code> object using the <code>String</code> + * and specified radix (base). + * + * @param s the <code>String</code> to convert + * @param radix the radix (base) to convert with + * @return the new <code>Short</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>short</code> + * @see #parseShort(String, int) + */ + public static Short valueOf(String s, int radix) + { + return new Short(parseShort(s, radix)); + } + + /** + * Creates a new <code>Short</code> object using the <code>String</code>, + * assuming a radix of 10. + * + * @param s the <code>String</code> to convert + * @return the new <code>Short</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>short</code> + * @see #Short(String) + * @see #parseShort(String) + */ + public static Short valueOf(String s) + { + return new Short(parseShort(s, 10)); + } + + /** + * Convert the specified <code>String</code> into a <code>Short</code>. + * The <code>String</code> may represent decimal, hexadecimal, or + * octal numbers. + * + * <p>The extended BNF grammar is as follows:<br> + * <pre> + * <em>DecodableString</em>: + * ( [ <code>-</code> ] <em>DecimalNumber</em> ) + * | ( [ <code>-</code> ] ( <code>0x</code> | <code>0X</code> + * | <code>#</code> ) <em>HexDigit</em> { <em>HexDigit</em> } ) + * | ( [ <code>-</code> ] <code>0</code> { <em>OctalDigit</em> } ) + * <em>DecimalNumber</em>: + * <em>DecimalDigit except '0'</em> { <em>DecimalDigit</em> } + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 10) has value 0 to 9</em> + * <em>OctalDigit</em>: + * <em>Character.digit(d, 8) has value 0 to 7</em> + * <em>DecimalDigit</em>: + * <em>Character.digit(d, 16) has value 0 to 15</em> + * </pre> + * Finally, the value must be in the range <code>MIN_VALUE</code> to + * <code>MAX_VALUE</code>, or an exception is thrown. + * + * @param s the <code>String</code> to interpret + * @return the value of the String as a <code>Short</code> + * @throws NumberFormatException if <code>s</code> cannot be parsed as a + * <code>short</code> + * @throws NullPointerException if <code>s</code> is null + * @see Integer#decode(String) + */ + public static Short decode(String s) + { + int i = Integer.parseInt(s, 10, true); + if ((short) i != i) + throw new NumberFormatException(); + return new Short((short) i); + } + + /** + * Return the value of this <code>Short</code> as a <code>byte</code>. + * + * @return the byte value + */ + public byte byteValue() + { + return (byte) value; + } + + /** + * Return the value of this <code>Short</code>. + * + * @return the short value + */ + public short shortValue() + { + return value; + } + + /** + * Return the value of this <code>Short</code> as an <code>int</code>. + * + * @return the int value + */ + public int intValue() + { + return value; + } + + /** + * Return the value of this <code>Short</code> as a <code>long</code>. + * + * @return the long value + */ + public long longValue() + { + return value; + } + + /** + * Return the value of this <code>Short</code> as a <code>float</code>. + * + * @return the float value + */ + public float floatValue() + { + return value; + } + + /** + * Return the value of this <code>Short</code> as a <code>double</code>. + * + * @return the double value + */ + public double doubleValue() + { + return value; + } + + /** + * Converts the <code>Short</code> value to a <code>String</code> and + * assumes a radix of 10. + * + * @return the <code>String</code> representation of this <code>Short</code> + */ + public String toString() + { + return String.valueOf(value); + } + + /** + * Return a hashcode representing this Object. <code>Short</code>'s hash + * code is simply its value. + * + * @return this Object's hash code + */ + public int hashCode() + { + return value; + } + + /** + * Returns <code>true</code> if <code>obj</code> is an instance of + * <code>Short</code> and represents the same short value. + * + * @param obj the object to compare + * @return whether these Objects are semantically equal + */ + public boolean equals(Object obj) + { + return obj instanceof Short && value == ((Short) obj).value; + } + + /** + * Compare two Shorts numerically by comparing their <code>short</code> + * values. The result is positive if the first is greater, negative if the + * second is greater, and 0 if the two are equal. + * + * @param s the Short to compare + * @return the comparison + * @since 1.2 + */ + public int compareTo(Short s) + { + return value - s.value; + } + + /** + * Behaves like <code>compareTo(Short)</code> unless the Object + * is not a <code>Short</code>. + * + * @param o the object to compare + * @return the comparison + * @throws ClassCastException if the argument is not a <code>Short</code> + * @see #compareTo(Short) + * @see Comparable + * @since 1.2 + */ + public int compareTo(Object o) + { + return compareTo((Short)o); + } +} diff --git a/libjava/classpath/java/lang/StackOverflowError.java b/libjava/classpath/java/lang/StackOverflowError.java new file mode 100644 index 0000000..5188ddd --- /dev/null +++ b/libjava/classpath/java/lang/StackOverflowError.java @@ -0,0 +1,72 @@ +/* StackOverflowError.java -- thrown when the stack depth is exceeded + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>StackOverflowError</code> is thrown when the execution stack + * overflow occurs. This often occurs when a method enters infinit recursion. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class StackOverflowError extends VirtualMachineError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 8609175038441759607L; + + /** + * Create an error without a message. + */ + public StackOverflowError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public StackOverflowError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/StackTraceElement.java b/libjava/classpath/java/lang/StackTraceElement.java new file mode 100644 index 0000000..6dd4d85 --- /dev/null +++ b/libjava/classpath/java/lang/StackTraceElement.java @@ -0,0 +1,259 @@ +/* StackTraceElement.java -- One function call or call stack element + Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import java.io.Serializable; + +/** + * One function call or stack trace element. Gives information about + * the execution point such as the source file name, the line number, + * the fully qualified class name, the method name and whether this method + * is native, if this information is known. + * + * @author Mark Wielaard (mark@klomp.org) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.4 + * @status updated to 1.4 + */ +public final class StackTraceElement implements Serializable +{ + /** + * Compatible with JDK 1.4+. + */ + private static final long serialVersionUID = 6992337162326171013L; + + /** + * The name of the file, null if unknown. + * + * @serial the source code filename, if known + */ + private final String fileName; + + /** + * The line number in the file, negative if unknown. + * + * @serial the source code line number, if known + */ + private final int lineNumber; + + /** + * The fully qualified class name, null if unknown. + * + * @serial the enclosing class, if known + */ + private final String declaringClass; + + /** + * The method name in the class, null if unknown. + * + * @serial the enclosing method, if known + */ + private final String methodName; + + /** Whether the method is native. */ + private final transient boolean isNative; + + /** + * A package local constructor for the StackTraceElement class, to be + * called by the Virtual Machine as part of Throwable.fillInStackTrace. + * There are no public constructors defined for this class. Creation + * of new elements is implementation specific. + * + * @param fileName the name of the file, null if unknown + * @param lineNumber the line in the file, negative if unknown + * @param className the fully qualified name of the class, null if unknown + * @param methodName the name of the method, null if unknown + * @param isNative true if native, false otherwise + */ + StackTraceElement(String fileName, int lineNumber, String className, + String methodName, boolean isNative) + { + this.fileName = fileName; + this.lineNumber = lineNumber; + this.declaringClass = className; + this.methodName = methodName; + this.isNative = isNative; + } + + /** + * Returns the name of the file, or null if unknown. This is usually + * obtained from the <code>SourceFile</code> attribute of the class file + * format, if present. + * + * @return the file name + */ + public String getFileName() + { + return fileName; + } + + /** + * Returns the line number in the file, or a negative number if unknown. + * This is usually obtained from the <code>LineNumberTable</code> attribute + * of the method in the class file format, if present. + * + * @return the line number + */ + public int getLineNumber() + { + return lineNumber; + } + + /** + * Returns the fully qualified class name, or null if unknown. + * + * @return the class name + */ + public String getClassName() + { + return declaringClass; + } + + /** + * Returns the method name in the class, or null if unknown. If the + * execution point is in a constructor, the name is + * <code><init></code>; if the execution point is in the class + * initializer, the name is <code><clinit></code>. + * + * @return the method name + */ + public String getMethodName() + { + return methodName; + } + + /** + * Returns true if the method is native, or false if it is not or unknown. + * + * @return whether the method is native + */ + public boolean isNativeMethod() + { + return isNative; + } + + /** + * Returns a string representation of this stack trace element. The + * returned String is implementation specific. This implementation + * returns the following String: "[class][.][method]([file][:line])". + * If the fully qualified class name or the method is unknown it is + * omitted including the point seperator. If the source file name is + * unknown it is replaced by "Unknown Source" if the method is not native + * or by "Native Method" if the method is native. If the line number + * is unknown it and the colon are omitted. + * + * @return a string representation of this execution point + */ + public String toString() + { + StringBuffer sb = new StringBuffer(); + if (declaringClass != null) + { + sb.append(declaringClass); + if (methodName != null) + sb.append('.'); + } + if (methodName != null) + sb.append(methodName); + sb.append(" ("); + if (fileName != null) + sb.append(fileName); + else + sb.append(isNative ? "Native Method" : "Unknown Source"); + if (lineNumber >= 0) + sb.append(':').append(lineNumber); + sb.append(')'); + return sb.toString(); + } + + /** + * Returns true if the given object is also a StackTraceElement and all + * attributes, except the native flag, are equal (either the same attribute + * between the two elments are null, or both satisfy Object.equals). + * + * @param o the object to compare + * @return true if the two are equal + */ + public boolean equals(Object o) + { + if (! (o instanceof StackTraceElement)) + return false; + StackTraceElement e = (StackTraceElement) o; + return equals(fileName, e.fileName) + && lineNumber == e.lineNumber + && equals(declaringClass, e.declaringClass) + && equals(methodName, e.methodName); + } + + /** + * Returns the hashCode of this StackTraceElement. This implementation + * computes the hashcode by xor-ing the hashcode of all attributes except + * the native flag. + * + * @return the hashcode + */ + public int hashCode() + { + return hashCode(fileName) ^ lineNumber ^ hashCode(declaringClass) + ^ hashCode(methodName); + } + + /** + * Compare two objects according to Collection semantics. + * + * @param o1 the first object + * @param o2 the second object + * @return o1 == null ? o2 == null : o1.equals(o2) + */ + private static boolean equals(Object o1, Object o2) + { + return o1 == null ? o2 == null : o1.equals(o2); + } + + /** + * Hash an object according to Collection semantics. + * + * @param o the object to hash + * @return o1 == null ? 0 : o1.hashCode() + */ + private static int hashCode(Object o) + { + return o == null ? 0 : o.hashCode(); + } +} diff --git a/libjava/classpath/java/lang/StrictMath.java b/libjava/classpath/java/lang/StrictMath.java new file mode 100644 index 0000000..32bd354 --- /dev/null +++ b/libjava/classpath/java/lang/StrictMath.java @@ -0,0 +1,1844 @@ +/* java.lang.StrictMath -- common mathematical functions, strict Java + Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +/* + * Some of the algorithms in this class are in the public domain, as part + * of fdlibm (freely-distributable math library), available at + * http://www.netlib.org/fdlibm/, and carry the following copyright: + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +package java.lang; + +import gnu.classpath.Configuration; + +import java.util.Random; + +/** + * Helper class containing useful mathematical functions and constants. + * This class mirrors {@link Math}, but is 100% portable, because it uses + * no native methods whatsoever. Also, these algorithms are all accurate + * to less than 1 ulp, and execute in <code>strictfp</code> mode, while + * Math is allowed to vary in its results for some functions. Unfortunately, + * this usually means StrictMath has less efficiency and speed, as Math can + * use native methods. + * + * <p>The source of the various algorithms used is the fdlibm library, at:<br> + * <a href="http://www.netlib.org/fdlibm/">http://www.netlib.org/fdlibm/</a> + * + * Note that angles are specified in radians. Conversion functions are + * provided for your convenience. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + */ +public final strictfp class StrictMath +{ + /** + * StrictMath is non-instantiable. + */ + private StrictMath() + { + } + + /** + * A random number generator, initialized on first use. + * + * @see #random() + */ + private static Random rand; + + /** + * The most accurate approximation to the mathematical constant <em>e</em>: + * <code>2.718281828459045</code>. Used in natural log and exp. + * + * @see #log(double) + * @see #exp(double) + */ + public static final double E + = 2.718281828459045; // Long bits 0x4005bf0z8b145769L. + + /** + * The most accurate approximation to the mathematical constant <em>pi</em>: + * <code>3.141592653589793</code>. This is the ratio of a circle's diameter + * to its circumference. + */ + public static final double PI + = 3.141592653589793; // Long bits 0x400921fb54442d18L. + + /** + * Take the absolute value of the argument. (Absolute value means make + * it positive.) + * + * <p>Note that the the largest negative value (Integer.MIN_VALUE) cannot + * be made positive. In this case, because of the rules of negation in + * a computer, MIN_VALUE is what will be returned. + * This is a <em>negative</em> value. You have been warned. + * + * @param i the number to take the absolute value of + * @return the absolute value + * @see Integer#MIN_VALUE + */ + public static int abs(int i) + { + return (i < 0) ? -i : i; + } + + /** + * Take the absolute value of the argument. (Absolute value means make + * it positive.) + * + * <p>Note that the the largest negative value (Long.MIN_VALUE) cannot + * be made positive. In this case, because of the rules of negation in + * a computer, MIN_VALUE is what will be returned. + * This is a <em>negative</em> value. You have been warned. + * + * @param l the number to take the absolute value of + * @return the absolute value + * @see Long#MIN_VALUE + */ + public static long abs(long l) + { + return (l < 0) ? -l : l; + } + + /** + * Take the absolute value of the argument. (Absolute value means make + * it positive.) + * + * @param f the number to take the absolute value of + * @return the absolute value + */ + public static float abs(float f) + { + return (f <= 0) ? 0 - f : f; + } + + /** + * Take the absolute value of the argument. (Absolute value means make + * it positive.) + * + * @param d the number to take the absolute value of + * @return the absolute value + */ + public static double abs(double d) + { + return (d <= 0) ? 0 - d : d; + } + + /** + * Return whichever argument is smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static int min(int a, int b) + { + return (a < b) ? a : b; + } + + /** + * Return whichever argument is smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static long min(long a, long b) + { + return (a < b) ? a : b; + } + + /** + * Return whichever argument is smaller. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, -0 is always smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static float min(float a, float b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; < will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return -(-a - b); + return (a < b) ? a : b; + } + + /** + * Return whichever argument is smaller. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, -0 is always smaller. + * + * @param a the first number + * @param b a second number + * @return the smaller of the two numbers + */ + public static double min(double a, double b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; < will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return -(-a - b); + return (a < b) ? a : b; + } + + /** + * Return whichever argument is larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static int max(int a, int b) + { + return (a > b) ? a : b; + } + + /** + * Return whichever argument is larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static long max(long a, long b) + { + return (a > b) ? a : b; + } + + /** + * Return whichever argument is larger. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, 0 is always larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static float max(float a, float b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; > will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return a - -b; + return (a > b) ? a : b; + } + + /** + * Return whichever argument is larger. If either argument is NaN, the + * result is NaN, and when comparing 0 and -0, 0 is always larger. + * + * @param a the first number + * @param b a second number + * @return the larger of the two numbers + */ + public static double max(double a, double b) + { + // this check for NaN, from JLS 15.21.1, saves a method call + if (a != a) + return a; + // no need to check if b is NaN; > will work correctly + // recall that -0.0 == 0.0, but [+-]0.0 - [+-]0.0 behaves special + if (a == 0 && b == 0) + return a - -b; + return (a > b) ? a : b; + } + + /** + * The trigonometric function <em>sin</em>. The sine of NaN or infinity is + * NaN, and the sine of 0 retains its sign. + * + * @param a the angle (in radians) + * @return sin(a) + */ + public static double sin(double a) + { + if (a == Double.NEGATIVE_INFINITY || ! (a < Double.POSITIVE_INFINITY)) + return Double.NaN; + + if (abs(a) <= PI / 4) + return sin(a, 0); + + // Argument reduction needed. + double[] y = new double[2]; + int n = remPiOver2(a, y); + switch (n & 3) + { + case 0: + return sin(y[0], y[1]); + case 1: + return cos(y[0], y[1]); + case 2: + return -sin(y[0], y[1]); + default: + return -cos(y[0], y[1]); + } + } + + /** + * The trigonometric function <em>cos</em>. The cosine of NaN or infinity is + * NaN. + * + * @param a the angle (in radians). + * @return cos(a). + */ + public static double cos(double a) + { + if (a == Double.NEGATIVE_INFINITY || ! (a < Double.POSITIVE_INFINITY)) + return Double.NaN; + + if (abs(a) <= PI / 4) + return cos(a, 0); + + // Argument reduction needed. + double[] y = new double[2]; + int n = remPiOver2(a, y); + switch (n & 3) + { + case 0: + return cos(y[0], y[1]); + case 1: + return -sin(y[0], y[1]); + case 2: + return -cos(y[0], y[1]); + default: + return sin(y[0], y[1]); + } + } + + /** + * The trigonometric function <em>tan</em>. The tangent of NaN or infinity + * is NaN, and the tangent of 0 retains its sign. + * + * @param a the angle (in radians) + * @return tan(a) + */ + public static double tan(double a) + { + if (a == Double.NEGATIVE_INFINITY || ! (a < Double.POSITIVE_INFINITY)) + return Double.NaN; + + if (abs(a) <= PI / 4) + return tan(a, 0, false); + + // Argument reduction needed. + double[] y = new double[2]; + int n = remPiOver2(a, y); + return tan(y[0], y[1], (n & 1) == 1); + } + + /** + * The trigonometric function <em>arcsin</em>. The range of angles returned + * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN or + * its absolute value is beyond 1, the result is NaN; and the arcsine of + * 0 retains its sign. + * + * @param x the sin to turn back into an angle + * @return arcsin(x) + */ + public static double asin(double x) + { + boolean negative = x < 0; + if (negative) + x = -x; + if (! (x <= 1)) + return Double.NaN; + if (x == 1) + return negative ? -PI / 2 : PI / 2; + if (x < 0.5) + { + if (x < 1 / TWO_27) + return negative ? -x : x; + double t = x * x; + double p = t * (PS0 + t * (PS1 + t * (PS2 + t * (PS3 + t + * (PS4 + t * PS5))))); + double q = 1 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4))); + return negative ? -x - x * (p / q) : x + x * (p / q); + } + double w = 1 - x; // 1>|x|>=0.5. + double t = w * 0.5; + double p = t * (PS0 + t * (PS1 + t * (PS2 + t * (PS3 + t + * (PS4 + t * PS5))))); + double q = 1 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4))); + double s = sqrt(t); + if (x >= 0.975) + { + w = p / q; + t = PI / 2 - (2 * (s + s * w) - PI_L / 2); + } + else + { + w = (float) s; + double c = (t - w * w) / (s + w); + p = 2 * s * (p / q) - (PI_L / 2 - 2 * c); + q = PI / 4 - 2 * w; + t = PI / 4 - (p - q); + } + return negative ? -t : t; + } + + /** + * The trigonometric function <em>arccos</em>. The range of angles returned + * is 0 to pi radians (0 to 180 degrees). If the argument is NaN or + * its absolute value is beyond 1, the result is NaN. + * + * @param x the cos to turn back into an angle + * @return arccos(x) + */ + public static double acos(double x) + { + boolean negative = x < 0; + if (negative) + x = -x; + if (! (x <= 1)) + return Double.NaN; + if (x == 1) + return negative ? PI : 0; + if (x < 0.5) + { + if (x < 1 / TWO_57) + return PI / 2; + double z = x * x; + double p = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z + * (PS4 + z * PS5))))); + double q = 1 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4))); + double r = x - (PI_L / 2 - x * (p / q)); + return negative ? PI / 2 + r : PI / 2 - r; + } + if (negative) // x<=-0.5. + { + double z = (1 + x) * 0.5; + double p = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z + * (PS4 + z * PS5))))); + double q = 1 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4))); + double s = sqrt(z); + double w = p / q * s - PI_L / 2; + return PI - 2 * (s + w); + } + double z = (1 - x) * 0.5; // x>0.5. + double s = sqrt(z); + double df = (float) s; + double c = (z - df * df) / (s + df); + double p = z * (PS0 + z * (PS1 + z * (PS2 + z * (PS3 + z + * (PS4 + z * PS5))))); + double q = 1 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4))); + double w = p / q * s + c; + return 2 * (df + w); + } + + /** + * The trigonometric function <em>arcsin</em>. The range of angles returned + * is -pi/2 to pi/2 radians (-90 to 90 degrees). If the argument is NaN, the + * result is NaN; and the arctangent of 0 retains its sign. + * + * @param x the tan to turn back into an angle + * @return arcsin(x) + * @see #atan2(double, double) + */ + public static double atan(double x) + { + double lo; + double hi; + boolean negative = x < 0; + if (negative) + x = -x; + if (x >= TWO_66) + return negative ? -PI / 2 : PI / 2; + if (! (x >= 0.4375)) // |x|<7/16, or NaN. + { + if (! (x >= 1 / TWO_29)) // Small, or NaN. + return negative ? -x : x; + lo = hi = 0; + } + else if (x < 1.1875) + { + if (x < 0.6875) // 7/16<=|x|<11/16. + { + x = (2 * x - 1) / (2 + x); + hi = ATAN_0_5H; + lo = ATAN_0_5L; + } + else // 11/16<=|x|<19/16. + { + x = (x - 1) / (x + 1); + hi = PI / 4; + lo = PI_L / 4; + } + } + else if (x < 2.4375) // 19/16<=|x|<39/16. + { + x = (x - 1.5) / (1 + 1.5 * x); + hi = ATAN_1_5H; + lo = ATAN_1_5L; + } + else // 39/16<=|x|<2**66. + { + x = -1 / x; + hi = PI / 2; + lo = PI_L / 2; + } + + // Break sum from i=0 to 10 ATi*z**(i+1) into odd and even poly. + double z = x * x; + double w = z * z; + double s1 = z * (AT0 + w * (AT2 + w * (AT4 + w * (AT6 + w + * (AT8 + w * AT10))))); + double s2 = w * (AT1 + w * (AT3 + w * (AT5 + w * (AT7 + w * AT9)))); + if (hi == 0) + return negative ? x * (s1 + s2) - x : x - x * (s1 + s2); + z = hi - ((x * (s1 + s2) - lo) - x); + return negative ? -z : z; + } + + /** + * A special version of the trigonometric function <em>arctan</em>, for + * converting rectangular coordinates <em>(x, y)</em> to polar + * <em>(r, theta)</em>. This computes the arctangent of x/y in the range + * of -pi to pi radians (-180 to 180 degrees). Special cases:<ul> + * <li>If either argument is NaN, the result is NaN.</li> + * <li>If the first argument is positive zero and the second argument is + * positive, or the first argument is positive and finite and the second + * argument is positive infinity, then the result is positive zero.</li> + * <li>If the first argument is negative zero and the second argument is + * positive, or the first argument is negative and finite and the second + * argument is positive infinity, then the result is negative zero.</li> + * <li>If the first argument is positive zero and the second argument is + * negative, or the first argument is positive and finite and the second + * argument is negative infinity, then the result is the double value + * closest to pi.</li> + * <li>If the first argument is negative zero and the second argument is + * negative, or the first argument is negative and finite and the second + * argument is negative infinity, then the result is the double value + * closest to -pi.</li> + * <li>If the first argument is positive and the second argument is + * positive zero or negative zero, or the first argument is positive + * infinity and the second argument is finite, then the result is the + * double value closest to pi/2.</li> + * <li>If the first argument is negative and the second argument is + * positive zero or negative zero, or the first argument is negative + * infinity and the second argument is finite, then the result is the + * double value closest to -pi/2.</li> + * <li>If both arguments are positive infinity, then the result is the + * double value closest to pi/4.</li> + * <li>If the first argument is positive infinity and the second argument + * is negative infinity, then the result is the double value closest to + * 3*pi/4.</li> + * <li>If the first argument is negative infinity and the second argument + * is positive infinity, then the result is the double value closest to + * -pi/4.</li> + * <li>If both arguments are negative infinity, then the result is the + * double value closest to -3*pi/4.</li> + * + * </ul><p>This returns theta, the angle of the point. To get r, albeit + * slightly inaccurately, use sqrt(x*x+y*y). + * + * @param y the y position + * @param x the x position + * @return <em>theta</em> in the conversion of (x, y) to (r, theta) + * @see #atan(double) + */ + public static double atan2(double y, double x) + { + if (x != x || y != y) + return Double.NaN; + if (x == 1) + return atan(y); + if (x == Double.POSITIVE_INFINITY) + { + if (y == Double.POSITIVE_INFINITY) + return PI / 4; + if (y == Double.NEGATIVE_INFINITY) + return -PI / 4; + return 0 * y; + } + if (x == Double.NEGATIVE_INFINITY) + { + if (y == Double.POSITIVE_INFINITY) + return 3 * PI / 4; + if (y == Double.NEGATIVE_INFINITY) + return -3 * PI / 4; + return (1 / (0 * y) == Double.POSITIVE_INFINITY) ? PI : -PI; + } + if (y == 0) + { + if (1 / (0 * x) == Double.POSITIVE_INFINITY) + return y; + return (1 / y == Double.POSITIVE_INFINITY) ? PI : -PI; + } + if (y == Double.POSITIVE_INFINITY || y == Double.NEGATIVE_INFINITY + || x == 0) + return y < 0 ? -PI / 2 : PI / 2; + + double z = abs(y / x); // Safe to do y/x. + if (z > TWO_60) + z = PI / 2 + 0.5 * PI_L; + else if (x < 0 && z < 1 / TWO_60) + z = 0; + else + z = atan(z); + if (x > 0) + return y > 0 ? z : -z; + return y > 0 ? PI - (z - PI_L) : z - PI_L - PI; + } + + /** + * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the + * argument is NaN, the result is NaN; if the argument is positive infinity, + * the result is positive infinity; and if the argument is negative + * infinity, the result is positive zero. + * + * @param x the number to raise to the power + * @return the number raised to the power of <em>e</em> + * @see #log(double) + * @see #pow(double, double) + */ + public static double exp(double x) + { + if (x != x) + return x; + if (x > EXP_LIMIT_H) + return Double.POSITIVE_INFINITY; + if (x < EXP_LIMIT_L) + return 0; + + // Argument reduction. + double hi; + double lo; + int k; + double t = abs(x); + if (t > 0.5 * LN2) + { + if (t < 1.5 * LN2) + { + hi = t - LN2_H; + lo = LN2_L; + k = 1; + } + else + { + k = (int) (INV_LN2 * t + 0.5); + hi = t - k * LN2_H; + lo = k * LN2_L; + } + if (x < 0) + { + hi = -hi; + lo = -lo; + k = -k; + } + x = hi - lo; + } + else if (t < 1 / TWO_28) + return 1; + else + lo = hi = k = 0; + + // Now x is in primary range. + t = x * x; + double c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + if (k == 0) + return 1 - (x * c / (c - 2) - x); + double y = 1 - (lo - x * c / (2 - c) - hi); + return scale(y, k); + } + + /** + * Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the + * argument is NaN or negative, the result is NaN; if the argument is + * positive infinity, the result is positive infinity; and if the argument + * is either zero, the result is negative infinity. + * + * <p>Note that the way to get log<sub>b</sub>(a) is to do this: + * <code>ln(a) / ln(b)</code>. + * + * @param x the number to take the natural log of + * @return the natural log of <code>a</code> + * @see #exp(double) + */ + public static double log(double x) + { + if (x == 0) + return Double.NEGATIVE_INFINITY; + if (x < 0) + return Double.NaN; + if (! (x < Double.POSITIVE_INFINITY)) + return x; + + // Normalize x. + long bits = Double.doubleToLongBits(x); + int exp = (int) (bits >> 52); + if (exp == 0) // Subnormal x. + { + x *= TWO_54; + bits = Double.doubleToLongBits(x); + exp = (int) (bits >> 52) - 54; + } + exp -= 1023; // Unbias exponent. + bits = (bits & 0x000fffffffffffffL) | 0x3ff0000000000000L; + x = Double.longBitsToDouble(bits); + if (x >= SQRT_2) + { + x *= 0.5; + exp++; + } + x--; + if (abs(x) < 1 / TWO_20) + { + if (x == 0) + return exp * LN2_H + exp * LN2_L; + double r = x * x * (0.5 - 1 / 3.0 * x); + if (exp == 0) + return x - r; + return exp * LN2_H - ((r - exp * LN2_L) - x); + } + double s = x / (2 + x); + double z = s * s; + double w = z * z; + double t1 = w * (LG2 + w * (LG4 + w * LG6)); + double t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7))); + double r = t2 + t1; + if (bits >= 0x3ff6174a00000000L && bits < 0x3ff6b85200000000L) + { + double h = 0.5 * x * x; // Need more accuracy for x near sqrt(2). + if (exp == 0) + return x - (h - s * (h + r)); + return exp * LN2_H - ((h - (s * (h + r) + exp * LN2_L)) - x); + } + if (exp == 0) + return x - s * (x - r); + return exp * LN2_H - ((s * (x - r) - exp * LN2_L) - x); + } + + /** + * Take a square root. If the argument is NaN or negative, the result is + * NaN; if the argument is positive infinity, the result is positive + * infinity; and if the result is either zero, the result is the same. + * + * <p>For other roots, use pow(x, 1/rootNumber). + * + * @param x the numeric argument + * @return the square root of the argument + * @see #pow(double, double) + */ + public static double sqrt(double x) + { + if (x < 0) + return Double.NaN; + if (x == 0 || ! (x < Double.POSITIVE_INFINITY)) + return x; + + // Normalize x. + long bits = Double.doubleToLongBits(x); + int exp = (int) (bits >> 52); + if (exp == 0) // Subnormal x. + { + x *= TWO_54; + bits = Double.doubleToLongBits(x); + exp = (int) (bits >> 52) - 54; + } + exp -= 1023; // Unbias exponent. + bits = (bits & 0x000fffffffffffffL) | 0x0010000000000000L; + if ((exp & 1) == 1) // Odd exp, double x to make it even. + bits <<= 1; + exp >>= 1; + + // Generate sqrt(x) bit by bit. + bits <<= 1; + long q = 0; + long s = 0; + long r = 0x0020000000000000L; // Move r right to left. + while (r != 0) + { + long t = s + r; + if (t <= bits) + { + s = t + r; + bits -= t; + q += r; + } + bits <<= 1; + r >>= 1; + } + + // Use floating add to round correctly. + if (bits != 0) + q += q & 1; + return Double.longBitsToDouble((q >> 1) + ((exp + 1022L) << 52)); + } + + /** + * Raise a number to a power. Special cases:<ul> + * <li>If the second argument is positive or negative zero, then the result + * is 1.0.</li> + * <li>If the second argument is 1.0, then the result is the same as the + * first argument.</li> + * <li>If the second argument is NaN, then the result is NaN.</li> + * <li>If the first argument is NaN and the second argument is nonzero, + * then the result is NaN.</li> + * <li>If the absolute value of the first argument is greater than 1 and + * the second argument is positive infinity, or the absolute value of the + * first argument is less than 1 and the second argument is negative + * infinity, then the result is positive infinity.</li> + * <li>If the absolute value of the first argument is greater than 1 and + * the second argument is negative infinity, or the absolute value of the + * first argument is less than 1 and the second argument is positive + * infinity, then the result is positive zero.</li> + * <li>If the absolute value of the first argument equals 1 and the second + * argument is infinite, then the result is NaN.</li> + * <li>If the first argument is positive zero and the second argument is + * greater than zero, or the first argument is positive infinity and the + * second argument is less than zero, then the result is positive zero.</li> + * <li>If the first argument is positive zero and the second argument is + * less than zero, or the first argument is positive infinity and the + * second argument is greater than zero, then the result is positive + * infinity.</li> + * <li>If the first argument is negative zero and the second argument is + * greater than zero but not a finite odd integer, or the first argument is + * negative infinity and the second argument is less than zero but not a + * finite odd integer, then the result is positive zero.</li> + * <li>If the first argument is negative zero and the second argument is a + * positive finite odd integer, or the first argument is negative infinity + * and the second argument is a negative finite odd integer, then the result + * is negative zero.</li> + * <li>If the first argument is negative zero and the second argument is + * less than zero but not a finite odd integer, or the first argument is + * negative infinity and the second argument is greater than zero but not a + * finite odd integer, then the result is positive infinity.</li> + * <li>If the first argument is negative zero and the second argument is a + * negative finite odd integer, or the first argument is negative infinity + * and the second argument is a positive finite odd integer, then the result + * is negative infinity.</li> + * <li>If the first argument is less than zero and the second argument is a + * finite even integer, then the result is equal to the result of raising + * the absolute value of the first argument to the power of the second + * argument.</li> + * <li>If the first argument is less than zero and the second argument is a + * finite odd integer, then the result is equal to the negative of the + * result of raising the absolute value of the first argument to the power + * of the second argument.</li> + * <li>If the first argument is finite and less than zero and the second + * argument is finite and not an integer, then the result is NaN.</li> + * <li>If both arguments are integers, then the result is exactly equal to + * the mathematical result of raising the first argument to the power of + * the second argument if that result can in fact be represented exactly as + * a double value.</li> + * + * </ul><p>(In the foregoing descriptions, a floating-point value is + * considered to be an integer if and only if it is a fixed point of the + * method {@link #ceil(double)} or, equivalently, a fixed point of the + * method {@link #floor(double)}. A value is a fixed point of a one-argument + * method if and only if the result of applying the method to the value is + * equal to the value.) + * + * @param x the number to raise + * @param y the power to raise it to + * @return x<sup>y</sup> + */ + public static double pow(double x, double y) + { + // Special cases first. + if (y == 0) + return 1; + if (y == 1) + return x; + if (y == -1) + return 1 / x; + if (x != x || y != y) + return Double.NaN; + + // When x < 0, yisint tells if y is not an integer (0), even(1), + // or odd (2). + int yisint = 0; + if (x < 0 && floor(y) == y) + yisint = (y % 2 == 0) ? 2 : 1; + double ax = abs(x); + double ay = abs(y); + + // More special cases, of y. + if (ay == Double.POSITIVE_INFINITY) + { + if (ax == 1) + return Double.NaN; + if (ax > 1) + return y > 0 ? y : 0; + return y < 0 ? -y : 0; + } + if (y == 2) + return x * x; + if (y == 0.5) + return sqrt(x); + + // More special cases, of x. + if (x == 0 || ax == Double.POSITIVE_INFINITY || ax == 1) + { + if (y < 0) + ax = 1 / ax; + if (x < 0) + { + if (x == -1 && yisint == 0) + ax = Double.NaN; + else if (yisint == 1) + ax = -ax; + } + return ax; + } + if (x < 0 && yisint == 0) + return Double.NaN; + + // Now we can start! + double t; + double t1; + double t2; + double u; + double v; + double w; + if (ay > TWO_31) + { + if (ay > TWO_64) // Automatic over/underflow. + return ((ax < 1) ? y < 0 : y > 0) ? Double.POSITIVE_INFINITY : 0; + // Over/underflow if x is not close to one. + if (ax < 0.9999995231628418) + return y < 0 ? Double.POSITIVE_INFINITY : 0; + if (ax >= 1.0000009536743164) + return y > 0 ? Double.POSITIVE_INFINITY : 0; + // Now |1-x| is <= 2**-20, sufficient to compute + // log(x) by x-x^2/2+x^3/3-x^4/4. + t = x - 1; + w = t * t * (0.5 - t * (1 / 3.0 - t * 0.25)); + u = INV_LN2_H * t; + v = t * INV_LN2_L - w * INV_LN2; + t1 = (float) (u + v); + t2 = v - (t1 - u); + } + else + { + long bits = Double.doubleToLongBits(ax); + int exp = (int) (bits >> 52); + if (exp == 0) // Subnormal x. + { + ax *= TWO_54; + bits = Double.doubleToLongBits(ax); + exp = (int) (bits >> 52) - 54; + } + exp -= 1023; // Unbias exponent. + ax = Double.longBitsToDouble((bits & 0x000fffffffffffffL) + | 0x3ff0000000000000L); + boolean k; + if (ax < SQRT_1_5) // |x|<sqrt(3/2). + k = false; + else if (ax < SQRT_3) // |x|<sqrt(3). + k = true; + else + { + k = false; + ax *= 0.5; + exp++; + } + + // Compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5). + u = ax - (k ? 1.5 : 1); + v = 1 / (ax + (k ? 1.5 : 1)); + double s = u * v; + double s_h = (float) s; + double t_h = (float) (ax + (k ? 1.5 : 1)); + double t_l = ax - (t_h - (k ? 1.5 : 1)); + double s_l = v * ((u - s_h * t_h) - s_h * t_l); + // Compute log(ax). + double s2 = s * s; + double r = s_l * (s_h + s) + s2 * s2 + * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); + s2 = s_h * s_h; + t_h = (float) (3.0 + s2 + r); + t_l = r - (t_h - 3.0 - s2); + // u+v = s*(1+...). + u = s_h * t_h; + v = s_l * t_h + t_l * s; + // 2/(3log2)*(s+...). + double p_h = (float) (u + v); + double p_l = v - (p_h - u); + double z_h = CP_H * p_h; + double z_l = CP_L * p_h + p_l * CP + (k ? DP_L : 0); + // log2(ax) = (s+..)*2/(3*log2) = exp + dp_h + z_h + z_l. + t = exp; + t1 = (float) (z_h + z_l + (k ? DP_H : 0) + t); + t2 = z_l - (t1 - t - (k ? DP_H : 0) - z_h); + } + + // Split up y into y1+y2 and compute (y1+y2)*(t1+t2). + boolean negative = x < 0 && yisint == 1; + double y1 = (float) y; + double p_l = (y - y1) * t1 + y * t2; + double p_h = y1 * t1; + double z = p_l + p_h; + if (z >= 1024) // Detect overflow. + { + if (z > 1024 || p_l + OVT > z - p_h) + return negative ? Double.NEGATIVE_INFINITY + : Double.POSITIVE_INFINITY; + } + else if (z <= -1075) // Detect underflow. + { + if (z < -1075 || p_l <= z - p_h) + return negative ? -0.0 : 0; + } + + // Compute 2**(p_h+p_l). + int n = round((float) z); + p_h -= n; + t = (float) (p_l + p_h); + u = t * LN2_H; + v = (p_l - (t - p_h)) * LN2 + t * LN2_L; + z = u + v; + w = v - (z - u); + t = z * z; + t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); + double r = (z * t1) / (t1 - 2) - (w + z * w); + z = scale(1 - (r - z), n); + return negative ? -z : z; + } + + /** + * Get the IEEE 754 floating point remainder on two numbers. This is the + * value of <code>x - y * <em>n</em></code>, where <em>n</em> is the closest + * double to <code>x / y</code> (ties go to the even n); for a zero + * remainder, the sign is that of <code>x</code>. If either argument is NaN, + * the first argument is infinite, or the second argument is zero, the result + * is NaN; if x is finite but y is infinite, the result is x. + * + * @param x the dividend (the top half) + * @param y the divisor (the bottom half) + * @return the IEEE 754-defined floating point remainder of x/y + * @see #rint(double) + */ + public static double IEEEremainder(double x, double y) + { + // Purge off exception values. + if (x == Double.NEGATIVE_INFINITY || ! (x < Double.POSITIVE_INFINITY) + || y == 0 || y != y) + return Double.NaN; + + boolean negative = x < 0; + x = abs(x); + y = abs(y); + if (x == y || x == 0) + return 0 * x; // Get correct sign. + + // Achieve x < 2y, then take first shot at remainder. + if (y < TWO_1023) + x %= y + y; + + // Now adjust x to get correct precision. + if (y < 4 / TWO_1023) + { + if (x + x > y) + { + x -= y; + if (x + x >= y) + x -= y; + } + } + else + { + y *= 0.5; + if (x > y) + { + x -= y; + if (x >= y) + x -= y; + } + } + return negative ? -x : x; + } + + /** + * Take the nearest integer that is that is greater than or equal to the + * argument. If the argument is NaN, infinite, or zero, the result is the + * same; if the argument is between -1 and 0, the result is negative zero. + * Note that <code>Math.ceil(x) == -Math.floor(-x)</code>. + * + * @param a the value to act upon + * @return the nearest integer >= <code>a</code> + */ + public static double ceil(double a) + { + return -floor(-a); + } + + /** + * Take the nearest integer that is that is less than or equal to the + * argument. If the argument is NaN, infinite, or zero, the result is the + * same. Note that <code>Math.ceil(x) == -Math.floor(-x)</code>. + * + * @param a the value to act upon + * @return the nearest integer <= <code>a</code> + */ + public static double floor(double a) + { + double x = abs(a); + if (! (x < TWO_52) || (long) a == a) + return a; // No fraction bits; includes NaN and infinity. + if (x < 1) + return a >= 0 ? 0 * a : -1; // Worry about signed zero. + return a < 0 ? (long) a - 1.0 : (long) a; // Cast to long truncates. + } + + /** + * Take the nearest integer to the argument. If it is exactly between + * two integers, the even integer is taken. If the argument is NaN, + * infinite, or zero, the result is the same. + * + * @param a the value to act upon + * @return the nearest integer to <code>a</code> + */ + public static double rint(double a) + { + double x = abs(a); + if (! (x < TWO_52)) + return a; // No fraction bits; includes NaN and infinity. + if (x <= 0.5) + return 0 * a; // Worry about signed zero. + if (x % 2 <= 0.5) + return (long) a; // Catch round down to even. + return (long) (a + (a < 0 ? -0.5 : 0.5)); // Cast to long truncates. + } + + /** + * Take the nearest integer to the argument. This is equivalent to + * <code>(int) Math.floor(f + 0.5f)</code>. If the argument is NaN, the + * result is 0; otherwise if the argument is outside the range of int, the + * result will be Integer.MIN_VALUE or Integer.MAX_VALUE, as appropriate. + * + * @param f the argument to round + * @return the nearest integer to the argument + * @see Integer#MIN_VALUE + * @see Integer#MAX_VALUE + */ + public static int round(float f) + { + return (int) floor(f + 0.5f); + } + + /** + * Take the nearest long to the argument. This is equivalent to + * <code>(long) Math.floor(d + 0.5)</code>. If the argument is NaN, the + * result is 0; otherwise if the argument is outside the range of long, the + * result will be Long.MIN_VALUE or Long.MAX_VALUE, as appropriate. + * + * @param d the argument to round + * @return the nearest long to the argument + * @see Long#MIN_VALUE + * @see Long#MAX_VALUE + */ + public static long round(double d) + { + return (long) floor(d + 0.5); + } + + /** + * Get a random number. This behaves like Random.nextDouble(), seeded by + * System.currentTimeMillis() when first called. In other words, the number + * is from a pseudorandom sequence, and lies in the range [+0.0, 1.0). + * This random sequence is only used by this method, and is threadsafe, + * although you may want your own random number generator if it is shared + * among threads. + * + * @return a random number + * @see Random#nextDouble() + * @see System#currentTimeMillis() + */ + public static synchronized double random() + { + if (rand == null) + rand = new Random(); + return rand.nextDouble(); + } + + /** + * Convert from degrees to radians. The formula for this is + * radians = degrees * (pi/180); however it is not always exact given the + * limitations of floating point numbers. + * + * @param degrees an angle in degrees + * @return the angle in radians + */ + public static double toRadians(double degrees) + { + return (degrees * PI) / 180; + } + + /** + * Convert from radians to degrees. The formula for this is + * degrees = radians * (180/pi); however it is not always exact given the + * limitations of floating point numbers. + * + * @param rads an angle in radians + * @return the angle in degrees + */ + public static double toDegrees(double rads) + { + return (rads * 180) / PI; + } + + /** + * Constants for scaling and comparing doubles by powers of 2. The compiler + * must automatically inline constructs like (1/TWO_54), so we don't list + * negative powers of two here. + */ + private static final double + TWO_16 = 0x10000, // Long bits 0x40f0000000000000L. + TWO_20 = 0x100000, // Long bits 0x4130000000000000L. + TWO_24 = 0x1000000, // Long bits 0x4170000000000000L. + TWO_27 = 0x8000000, // Long bits 0x41a0000000000000L. + TWO_28 = 0x10000000, // Long bits 0x41b0000000000000L. + TWO_29 = 0x20000000, // Long bits 0x41c0000000000000L. + TWO_31 = 0x80000000L, // Long bits 0x41e0000000000000L. + TWO_49 = 0x2000000000000L, // Long bits 0x4300000000000000L. + TWO_52 = 0x10000000000000L, // Long bits 0x4330000000000000L. + TWO_54 = 0x40000000000000L, // Long bits 0x4350000000000000L. + TWO_57 = 0x200000000000000L, // Long bits 0x4380000000000000L. + TWO_60 = 0x1000000000000000L, // Long bits 0x43b0000000000000L. + TWO_64 = 1.8446744073709552e19, // Long bits 0x43f0000000000000L. + TWO_66 = 7.378697629483821e19, // Long bits 0x4410000000000000L. + TWO_1023 = 8.98846567431158e307; // Long bits 0x7fe0000000000000L. + + /** + * Super precision for 2/pi in 24-bit chunks, for use in + * {@link #remPiOver2()}. + */ + private static final int TWO_OVER_PI[] = { + 0xa2f983, 0x6e4e44, 0x1529fc, 0x2757d1, 0xf534dd, 0xc0db62, + 0x95993c, 0x439041, 0xfe5163, 0xabdebb, 0xc561b7, 0x246e3a, + 0x424dd2, 0xe00649, 0x2eea09, 0xd1921c, 0xfe1deb, 0x1cb129, + 0xa73ee8, 0x8235f5, 0x2ebb44, 0x84e99c, 0x7026b4, 0x5f7e41, + 0x3991d6, 0x398353, 0x39f49c, 0x845f8b, 0xbdf928, 0x3b1ff8, + 0x97ffde, 0x05980f, 0xef2f11, 0x8b5a0a, 0x6d1f6d, 0x367ecf, + 0x27cb09, 0xb74f46, 0x3f669e, 0x5fea2d, 0x7527ba, 0xc7ebe5, + 0xf17b3d, 0x0739f7, 0x8a5292, 0xea6bfb, 0x5fb11f, 0x8d5d08, + 0x560330, 0x46fc7b, 0x6babf0, 0xcfbc20, 0x9af436, 0x1da9e3, + 0x91615e, 0xe61b08, 0x659985, 0x5f14a0, 0x68408d, 0xffd880, + 0x4d7327, 0x310606, 0x1556ca, 0x73a8c9, 0x60e27b, 0xc08c6b, + }; + + /** + * Super precision for pi/2 in 24-bit chunks, for use in + * {@link #remPiOver2()}. + */ + private static final double PI_OVER_TWO[] = { + 1.570796251296997, // Long bits 0x3ff921fb40000000L. + 7.549789415861596e-8, // Long bits 0x3e74442d00000000L. + 5.390302529957765e-15, // Long bits 0x3cf8469880000000L. + 3.282003415807913e-22, // Long bits 0x3b78cc5160000000L. + 1.270655753080676e-29, // Long bits 0x39f01b8380000000L. + 1.2293330898111133e-36, // Long bits 0x387a252040000000L. + 2.7337005381646456e-44, // Long bits 0x36e3822280000000L. + 2.1674168387780482e-51, // Long bits 0x3569f31d00000000L. + }; + + /** + * More constants related to pi, used in {@link #remPiOver2()} and + * elsewhere. + */ + private static final double + PI_L = 1.2246467991473532e-16, // Long bits 0x3ca1a62633145c07L. + PIO2_1 = 1.5707963267341256, // Long bits 0x3ff921fb54400000L. + PIO2_1L = 6.077100506506192e-11, // Long bits 0x3dd0b4611a626331L. + PIO2_2 = 6.077100506303966e-11, // Long bits 0x3dd0b4611a600000L. + PIO2_2L = 2.0222662487959506e-21, // Long bits 0x3ba3198a2e037073L. + PIO2_3 = 2.0222662487111665e-21, // Long bits 0x3ba3198a2e000000L. + PIO2_3L = 8.4784276603689e-32; // Long bits 0x397b839a252049c1L. + + /** + * Natural log and square root constants, for calculation of + * {@link #exp(double)}, {@link #log(double)} and + * {@link #power(double, double)}. CP is 2/(3*ln(2)). + */ + private static final double + SQRT_1_5 = 1.224744871391589, // Long bits 0x3ff3988e1409212eL. + SQRT_2 = 1.4142135623730951, // Long bits 0x3ff6a09e667f3bcdL. + SQRT_3 = 1.7320508075688772, // Long bits 0x3ffbb67ae8584caaL. + EXP_LIMIT_H = 709.782712893384, // Long bits 0x40862e42fefa39efL. + EXP_LIMIT_L = -745.1332191019411, // Long bits 0xc0874910d52d3051L. + CP = 0.9617966939259756, // Long bits 0x3feec709dc3a03fdL. + CP_H = 0.9617967009544373, // Long bits 0x3feec709e0000000L. + CP_L = -7.028461650952758e-9, // Long bits 0xbe3e2fe0145b01f5L. + LN2 = 0.6931471805599453, // Long bits 0x3fe62e42fefa39efL. + LN2_H = 0.6931471803691238, // Long bits 0x3fe62e42fee00000L. + LN2_L = 1.9082149292705877e-10, // Long bits 0x3dea39ef35793c76L. + INV_LN2 = 1.4426950408889634, // Long bits 0x3ff71547652b82feL. + INV_LN2_H = 1.4426950216293335, // Long bits 0x3ff7154760000000L. + INV_LN2_L = 1.9259629911266175e-8; // Long bits 0x3e54ae0bf85ddf44L. + + /** + * Constants for computing {@link #log(double)}. + */ + private static final double + LG1 = 0.6666666666666735, // Long bits 0x3fe5555555555593L. + LG2 = 0.3999999999940942, // Long bits 0x3fd999999997fa04L. + LG3 = 0.2857142874366239, // Long bits 0x3fd2492494229359L. + LG4 = 0.22222198432149784, // Long bits 0x3fcc71c51d8e78afL. + LG5 = 0.1818357216161805, // Long bits 0x3fc7466496cb03deL. + LG6 = 0.15313837699209373, // Long bits 0x3fc39a09d078c69fL. + LG7 = 0.14798198605116586; // Long bits 0x3fc2f112df3e5244L. + + /** + * Constants for computing {@link #pow(double, double)}. L and P are + * coefficients for series; OVT is -(1024-log2(ovfl+.5ulp)); and DP is ???. + * The P coefficients also calculate {@link #exp(double)}. + */ + private static final double + L1 = 0.5999999999999946, // Long bits 0x3fe3333333333303L. + L2 = 0.4285714285785502, // Long bits 0x3fdb6db6db6fabffL. + L3 = 0.33333332981837743, // Long bits 0x3fd55555518f264dL. + L4 = 0.272728123808534, // Long bits 0x3fd17460a91d4101L. + L5 = 0.23066074577556175, // Long bits 0x3fcd864a93c9db65L. + L6 = 0.20697501780033842, // Long bits 0x3fca7e284a454eefL. + P1 = 0.16666666666666602, // Long bits 0x3fc555555555553eL. + P2 = -2.7777777777015593e-3, // Long bits 0xbf66c16c16bebd93L. + P3 = 6.613756321437934e-5, // Long bits 0x3f11566aaf25de2cL. + P4 = -1.6533902205465252e-6, // Long bits 0xbebbbd41c5d26bf1L. + P5 = 4.1381367970572385e-8, // Long bits 0x3e66376972bea4d0L. + DP_H = 0.5849624872207642, // Long bits 0x3fe2b80340000000L. + DP_L = 1.350039202129749e-8, // Long bits 0x3e4cfdeb43cfd006L. + OVT = 8.008566259537294e-17; // Long bits 0x3c971547652b82feL. + + /** + * Coefficients for computing {@link #sin(double)}. + */ + private static final double + S1 = -0.16666666666666632, // Long bits 0xbfc5555555555549L. + S2 = 8.33333333332249e-3, // Long bits 0x3f8111111110f8a6L. + S3 = -1.984126982985795e-4, // Long bits 0xbf2a01a019c161d5L. + S4 = 2.7557313707070068e-6, // Long bits 0x3ec71de357b1fe7dL. + S5 = -2.5050760253406863e-8, // Long bits 0xbe5ae5e68a2b9cebL. + S6 = 1.58969099521155e-10; // Long bits 0x3de5d93a5acfd57cL. + + /** + * Coefficients for computing {@link #cos(double)}. + */ + private static final double + C1 = 0.0416666666666666, // Long bits 0x3fa555555555554cL. + C2 = -1.388888888887411e-3, // Long bits 0xbf56c16c16c15177L. + C3 = 2.480158728947673e-5, // Long bits 0x3efa01a019cb1590L. + C4 = -2.7557314351390663e-7, // Long bits 0xbe927e4f809c52adL. + C5 = 2.087572321298175e-9, // Long bits 0x3e21ee9ebdb4b1c4L. + C6 = -1.1359647557788195e-11; // Long bits 0xbda8fae9be8838d4L. + + /** + * Coefficients for computing {@link #tan(double)}. + */ + private static final double + T0 = 0.3333333333333341, // Long bits 0x3fd5555555555563L. + T1 = 0.13333333333320124, // Long bits 0x3fc111111110fe7aL. + T2 = 0.05396825397622605, // Long bits 0x3faba1ba1bb341feL. + T3 = 0.021869488294859542, // Long bits 0x3f9664f48406d637L. + T4 = 8.8632398235993e-3, // Long bits 0x3f8226e3e96e8493L. + T5 = 3.5920791075913124e-3, // Long bits 0x3f6d6d22c9560328L. + T6 = 1.4562094543252903e-3, // Long bits 0x3f57dbc8fee08315L. + T7 = 5.880412408202641e-4, // Long bits 0x3f4344d8f2f26501L. + T8 = 2.464631348184699e-4, // Long bits 0x3f3026f71a8d1068L. + T9 = 7.817944429395571e-5, // Long bits 0x3f147e88a03792a6L. + T10 = 7.140724913826082e-5, // Long bits 0x3f12b80f32f0a7e9L. + T11 = -1.8558637485527546e-5, // Long bits 0xbef375cbdb605373L. + T12 = 2.590730518636337e-5; // Long bits 0x3efb2a7074bf7ad4L. + + /** + * Coefficients for computing {@link #asin(double)} and + * {@link #acos(double)}. + */ + private static final double + PS0 = 0.16666666666666666, // Long bits 0x3fc5555555555555L. + PS1 = -0.3255658186224009, // Long bits 0xbfd4d61203eb6f7dL. + PS2 = 0.20121253213486293, // Long bits 0x3fc9c1550e884455L. + PS3 = -0.04005553450067941, // Long bits 0xbfa48228b5688f3bL. + PS4 = 7.915349942898145e-4, // Long bits 0x3f49efe07501b288L. + PS5 = 3.479331075960212e-5, // Long bits 0x3f023de10dfdf709L. + QS1 = -2.403394911734414, // Long bits 0xc0033a271c8a2d4bL. + QS2 = 2.0209457602335057, // Long bits 0x40002ae59c598ac8L. + QS3 = -0.6882839716054533, // Long bits 0xbfe6066c1b8d0159L. + QS4 = 0.07703815055590194; // Long bits 0x3fb3b8c5b12e9282L. + + /** + * Coefficients for computing {@link #atan(double)}. + */ + private static final double + ATAN_0_5H = 0.4636476090008061, // Long bits 0x3fddac670561bb4fL. + ATAN_0_5L = 2.2698777452961687e-17, // Long bits 0x3c7a2b7f222f65e2L. + ATAN_1_5H = 0.982793723247329, // Long bits 0x3fef730bd281f69bL. + ATAN_1_5L = 1.3903311031230998e-17, // Long bits 0x3c7007887af0cbbdL. + AT0 = 0.3333333333333293, // Long bits 0x3fd555555555550dL. + AT1 = -0.19999999999876483, // Long bits 0xbfc999999998ebc4L. + AT2 = 0.14285714272503466, // Long bits 0x3fc24924920083ffL. + AT3 = -0.11111110405462356, // Long bits 0xbfbc71c6fe231671L. + AT4 = 0.09090887133436507, // Long bits 0x3fb745cdc54c206eL. + AT5 = -0.0769187620504483, // Long bits 0xbfb3b0f2af749a6dL. + AT6 = 0.06661073137387531, // Long bits 0x3fb10d66a0d03d51L. + AT7 = -0.058335701337905735, // Long bits 0xbfadde2d52defd9aL. + AT8 = 0.049768779946159324, // Long bits 0x3fa97b4b24760debL. + AT9 = -0.036531572744216916, // Long bits 0xbfa2b4442c6a6c2fL. + AT10 = 0.016285820115365782; // Long bits 0x3f90ad3ae322da11L. + + /** + * Helper function for reducing an angle to a multiple of pi/2 within + * [-pi/4, pi/4]. + * + * @param x the angle; not infinity or NaN, and outside pi/4 + * @param y an array of 2 doubles modified to hold the remander x % pi/2 + * @return the quadrant of the result, mod 4: 0: [-pi/4, pi/4], + * 1: [pi/4, 3*pi/4], 2: [3*pi/4, 5*pi/4], 3: [-3*pi/4, -pi/4] + */ + private static int remPiOver2(double x, double[] y) + { + boolean negative = x < 0; + x = abs(x); + double z; + int n; + if (Configuration.DEBUG && (x <= PI / 4 || x != x + || x == Double.POSITIVE_INFINITY)) + throw new InternalError("Assertion failure"); + if (x < 3 * PI / 4) // If |x| is small. + { + z = x - PIO2_1; + if ((float) x != (float) (PI / 2)) // 33+53 bit pi is good enough. + { + y[0] = z - PIO2_1L; + y[1] = z - y[0] - PIO2_1L; + } + else // Near pi/2, use 33+33+53 bit pi. + { + z -= PIO2_2; + y[0] = z - PIO2_2L; + y[1] = z - y[0] - PIO2_2L; + } + n = 1; + } + else if (x <= TWO_20 * PI / 2) // Medium size. + { + n = (int) (2 / PI * x + 0.5); + z = x - n * PIO2_1; + double w = n * PIO2_1L; // First round good to 85 bits. + y[0] = z - w; + if (n >= 32 || (float) x == (float) (w)) + { + if (x / y[0] >= TWO_16) // Second iteration, good to 118 bits. + { + double t = z; + w = n * PIO2_2; + z = t - w; + w = n * PIO2_2L - (t - z - w); + y[0] = z - w; + if (x / y[0] >= TWO_49) // Third iteration, 151 bits accuracy. + { + t = z; + w = n * PIO2_3; + z = t - w; + w = n * PIO2_3L - (t - z - w); + y[0] = z - w; + } + } + } + y[1] = z - y[0] - w; + } + else + { + // All other (large) arguments. + int e0 = (int) (Double.doubleToLongBits(x) >> 52) - 1046; + z = scale(x, -e0); // e0 = ilogb(z) - 23. + double[] tx = new double[3]; + for (int i = 0; i < 2; i++) + { + tx[i] = (int) z; + z = (z - tx[i]) * TWO_24; + } + tx[2] = z; + int nx = 2; + while (tx[nx] == 0) + nx--; + n = remPiOver2(tx, y, e0, nx); + } + if (negative) + { + y[0] = -y[0]; + y[1] = -y[1]; + return -n; + } + return n; + } + + /** + * Helper function for reducing an angle to a multiple of pi/2 within + * [-pi/4, pi/4]. + * + * @param x the positive angle, broken into 24-bit chunks + * @param y an array of 2 doubles modified to hold the remander x % pi/2 + * @param e0 the exponent of x[0] + * @param nx the last index used in x + * @return the quadrant of the result, mod 4: 0: [-pi/4, pi/4], + * 1: [pi/4, 3*pi/4], 2: [3*pi/4, 5*pi/4], 3: [-3*pi/4, -pi/4] + */ + private static int remPiOver2(double[] x, double[] y, int e0, int nx) + { + int i; + int ih; + int n; + double fw; + double z; + int[] iq = new int[20]; + double[] f = new double[20]; + double[] q = new double[20]; + boolean recompute = false; + + // Initialize jk, jz, jv, q0; note that 3>q0. + int jk = 4; + int jz = jk; + int jv = max((e0 - 3) / 24, 0); + int q0 = e0 - 24 * (jv + 1); + + // Set up f[0] to f[nx+jk] where f[nx+jk] = TWO_OVER_PI[jv+jk]. + int j = jv - nx; + int m = nx + jk; + for (i = 0; i <= m; i++, j++) + f[i] = (j < 0) ? 0 : TWO_OVER_PI[j]; + + // Compute q[0],q[1],...q[jk]. + for (i = 0; i <= jk; i++) + { + for (j = 0, fw = 0; j <= nx; j++) + fw += x[j] * f[nx + i - j]; + q[i] = fw; + } + + do + { + // Distill q[] into iq[] reversingly. + for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--) + { + fw = (int) (1 / TWO_24 * z); + iq[i] = (int) (z - TWO_24 * fw); + z = q[j - 1] + fw; + } + + // Compute n. + z = scale(z, q0); + z -= 8 * floor(z * 0.125); // Trim off integer >= 8. + n = (int) z; + z -= n; + ih = 0; + if (q0 > 0) // Need iq[jz-1] to determine n. + { + i = iq[jz - 1] >> (24 - q0); + n += i; + iq[jz - 1] -= i << (24 - q0); + ih = iq[jz - 1] >> (23 - q0); + } + else if (q0 == 0) + ih = iq[jz - 1] >> 23; + else if (z >= 0.5) + ih = 2; + + if (ih > 0) // If q > 0.5. + { + n += 1; + int carry = 0; + for (i = 0; i < jz; i++) // Compute 1-q. + { + j = iq[i]; + if (carry == 0) + { + if (j != 0) + { + carry = 1; + iq[i] = 0x1000000 - j; + } + } + else + iq[i] = 0xffffff - j; + } + switch (q0) + { + case 1: // Rare case: chance is 1 in 12 for non-default. + iq[jz - 1] &= 0x7fffff; + break; + case 2: + iq[jz - 1] &= 0x3fffff; + } + if (ih == 2) + { + z = 1 - z; + if (carry != 0) + z -= scale(1, q0); + } + } + + // Check if recomputation is needed. + if (z == 0) + { + j = 0; + for (i = jz - 1; i >= jk; i--) + j |= iq[i]; + if (j == 0) // Need recomputation. + { + int k; + for (k = 1; iq[jk - k] == 0; k++); // k = no. of terms needed. + + for (i = jz + 1; i <= jz + k; i++) // Add q[jz+1] to q[jz+k]. + { + f[nx + i] = TWO_OVER_PI[jv + i]; + for (j = 0, fw = 0; j <= nx; j++) + fw += x[j] * f[nx + i - j]; + q[i] = fw; + } + jz += k; + recompute = true; + } + } + } + while (recompute); + + // Chop off zero terms. + if (z == 0) + { + jz--; + q0 -= 24; + while (iq[jz] == 0) + { + jz--; + q0 -= 24; + } + } + else // Break z into 24-bit if necessary. + { + z = scale(z, -q0); + if (z >= TWO_24) + { + fw = (int) (1 / TWO_24 * z); + iq[jz] = (int) (z - TWO_24 * fw); + jz++; + q0 += 24; + iq[jz] = (int) fw; + } + else + iq[jz] = (int) z; + } + + // Convert integer "bit" chunk to floating-point value. + fw = scale(1, q0); + for (i = jz; i >= 0; i--) + { + q[i] = fw * iq[i]; + fw *= 1 / TWO_24; + } + + // Compute PI_OVER_TWO[0,...,jk]*q[jz,...,0]. + double[] fq = new double[20]; + for (i = jz; i >= 0; i--) + { + fw = 0; + for (int k = 0; k <= jk && k <= jz - i; k++) + fw += PI_OVER_TWO[k] * q[i + k]; + fq[jz - i] = fw; + } + + // Compress fq[] into y[]. + fw = 0; + for (i = jz; i >= 0; i--) + fw += fq[i]; + y[0] = (ih == 0) ? fw : -fw; + fw = fq[0] - fw; + for (i = 1; i <= jz; i++) + fw += fq[i]; + y[1] = (ih == 0) ? fw : -fw; + return n; + } + + /** + * Helper method for scaling a double by a power of 2. + * + * @param x the double + * @param n the scale; |n| < 2048 + * @return x * 2**n + */ + private static double scale(double x, int n) + { + if (Configuration.DEBUG && abs(n) >= 2048) + throw new InternalError("Assertion failure"); + if (x == 0 || x == Double.NEGATIVE_INFINITY + || ! (x < Double.POSITIVE_INFINITY) || n == 0) + return x; + long bits = Double.doubleToLongBits(x); + int exp = (int) (bits >> 52) & 0x7ff; + if (exp == 0) // Subnormal x. + { + x *= TWO_54; + exp = ((int) (Double.doubleToLongBits(x) >> 52) & 0x7ff) - 54; + } + exp += n; + if (exp > 0x7fe) // Overflow. + return Double.POSITIVE_INFINITY * x; + if (exp > 0) // Normal. + return Double.longBitsToDouble((bits & 0x800fffffffffffffL) + | ((long) exp << 52)); + if (exp <= -54) + return 0 * x; // Underflow. + exp += 54; // Subnormal result. + x = Double.longBitsToDouble((bits & 0x800fffffffffffffL) + | ((long) exp << 52)); + return x * (1 / TWO_54); + } + + /** + * Helper trig function; computes sin in range [-pi/4, pi/4]. + * + * @param x angle within about pi/4 + * @param y tail of x, created by remPiOver2 + * @return sin(x+y) + */ + private static double sin(double x, double y) + { + if (Configuration.DEBUG && abs(x + y) > 0.7854) + throw new InternalError("Assertion failure"); + if (abs(x) < 1 / TWO_27) + return x; // If |x| ~< 2**-27, already know answer. + + double z = x * x; + double v = z * x; + double r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); + if (y == 0) + return x + v * (S1 + z * r); + return x - ((z * (0.5 * y - v * r) - y) - v * S1); + } + + /** + * Helper trig function; computes cos in range [-pi/4, pi/4]. + * + * @param x angle within about pi/4 + * @param y tail of x, created by remPiOver2 + * @return cos(x+y) + */ + private static double cos(double x, double y) + { + if (Configuration.DEBUG && abs(x + y) > 0.7854) + throw new InternalError("Assertion failure"); + x = abs(x); + if (x < 1 / TWO_27) + return 1; // If |x| ~< 2**-27, already know answer. + + double z = x * x; + double r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); + + if (x < 0.3) + return 1 - (0.5 * z - (z * r - x * y)); + + double qx = (x > 0.78125) ? 0.28125 : (x * 0.25); + return 1 - qx - ((0.5 * z - qx) - (z * r - x * y)); + } + + /** + * Helper trig function; computes tan in range [-pi/4, pi/4]. + * + * @param x angle within about pi/4 + * @param y tail of x, created by remPiOver2 + * @param invert true iff -1/tan should be returned instead + * @return tan(x+y) + */ + private static double tan(double x, double y, boolean invert) + { + // PI/2 is irrational, so no double is a perfect multiple of it. + if (Configuration.DEBUG && (abs(x + y) > 0.7854 || (x == 0 && invert))) + throw new InternalError("Assertion failure"); + boolean negative = x < 0; + if (negative) + { + x = -x; + y = -y; + } + if (x < 1 / TWO_28) // If |x| ~< 2**-28, already know answer. + return (negative ? -1 : 1) * (invert ? -1 / x : x); + + double z; + double w; + boolean large = x >= 0.6744; + if (large) + { + z = PI / 4 - x; + w = PI_L / 4 - y; + x = z + w; + y = 0; + } + z = x * x; + w = z * z; + // Break x**5*(T1+x**2*T2+...) into + // x**5(T1+x**4*T3+...+x**20*T11) + // + x**5(x**2*(T2+x**4*T4+...+x**22*T12)). + double r = T1 + w * (T3 + w * (T5 + w * (T7 + w * (T9 + w * T11)))); + double v = z * (T2 + w * (T4 + w * (T6 + w * (T8 + w * (T10 + w * T12))))); + double s = z * x; + r = y + z * (s * (r + v) + y); + r += T0 * s; + w = x + r; + if (large) + { + v = invert ? -1 : 1; + return (negative ? -1 : 1) * (v - 2 * (x - (w * w / (w + v) - r))); + } + if (! invert) + return w; + + // Compute -1.0/(x+r) accurately. + z = (float) w; + v = r - (z - x); + double a = -1 / w; + double t = (float) a; + return t + a * (1 + t * z + t * v); + } +} diff --git a/libjava/classpath/java/lang/String.java b/libjava/classpath/java/lang/String.java new file mode 100644 index 0000000..b4db850 --- /dev/null +++ b/libjava/classpath/java/lang/String.java @@ -0,0 +1,1750 @@ +/* String.java -- immutable character sequences; the object of string literals + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import gnu.java.lang.CharData; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CodingErrorAction; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; +import java.text.Collator; +import java.util.Comparator; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Strings represent an immutable set of characters. All String literals + * are instances of this class, and two string literals with the same contents + * refer to the same String object. + * + * <p>This class also includes a number of methods for manipulating the + * contents of strings (of course, creating a new object if there are any + * changes, as String is immutable). Case mapping relies on Unicode 3.0.0 + * standards, where some character sequences have a different number of + * characters in the uppercase version than the lower case. + * + * <p>Strings are special, in that they are the only object with an overloaded + * operator. When you use '+' with at least one String argument, both + * arguments have String conversion performed on them, and another String (not + * guaranteed to be unique) results. + * + * <p>String is special-cased when doing data serialization - rather than + * listing the fields of this class, a String object is converted to a string + * literal in the object stream. + * + * @author Paul N. Fisher + * @author Eric Blake (ebb9@email.byu.edu) + * @author Per Bothner (bothner@cygnus.com) + * @since 1.0 + * @status updated to 1.4; but could use better data sharing via offset field + */ +public final class String implements Serializable, Comparable, CharSequence +{ + // WARNING: String is a CORE class in the bootstrap cycle. See the comments + // in vm/reference/java/lang/Runtime for implications of this fact. + + /** + * This is probably not necessary because this class is special cased already + * but it will avoid showing up as a discrepancy when comparing SUIDs. + */ + private static final long serialVersionUID = -6849794470754667710L; + + /** + * Stores unicode multi-character uppercase expansion table. + * @see #toUpperCase(char) + * @see CharData#UPPER_EXPAND + */ + private static final char[] upperExpand + = zeroBasedStringValue(CharData.UPPER_EXPAND); + + /** + * Stores unicode multi-character uppercase special casing table. + * @see #upperCaseExpansion(char) + * @see CharData#UPPER_SPECIAL + */ + private static final char[] upperSpecial + = zeroBasedStringValue(CharData.UPPER_SPECIAL); + + /** + * Characters which make up the String. + * Package access is granted for use by StringBuffer. + */ + final char[] value; + + /** + * Holds the number of characters in value. This number is generally + * the same as value.length, but can be smaller because substrings and + * StringBuffers can share arrays. Package visible for use by trusted code. + */ + final int count; + + /** + * Caches the result of hashCode(). If this value is zero, the hashcode + * is considered uncached (even if 0 is the correct hash value). + */ + private int cachedHashCode; + + /** + * Holds the starting position for characters in value[]. Since + * substring()'s are common, the use of offset allows the operation + * to perform in O(1). Package access is granted for use by StringBuffer. + */ + final int offset; + + /** + * An implementation for {@link CASE_INSENSITIVE_ORDER}. + * This must be {@link Serializable}. The class name is dictated by + * compatibility with Sun's JDK. + */ + private static final class CaseInsensitiveComparator + implements Comparator, Serializable + { + /** + * Compatible with JDK 1.2. + */ + private static final long serialVersionUID = 8575799808933029326L; + + /** + * The default private constructor generates unnecessary overhead. + */ + CaseInsensitiveComparator() {} + + /** + * Compares to Strings, using + * <code>String.compareToIgnoreCase(String)</code>. + * + * @param o1 the first string + * @param o2 the second string + * @return < 0, 0, or > 0 depending on the case-insensitive + * comparison of the two strings. + * @throws NullPointerException if either argument is null + * @throws ClassCastException if either argument is not a String + * @see #compareToIgnoreCase(String) + */ + public int compare(Object o1, Object o2) + { + return ((String) o1).compareToIgnoreCase((String) o2); + } + } // class CaseInsensitiveComparator + + /** + * A Comparator that uses <code>String.compareToIgnoreCase(String)</code>. + * This comparator is {@link Serializable}. Note that it ignores Locale, + * for that, you want a Collator. + * + * @see Collator#compare(String, String) + * @since 1.2 + */ + public static final Comparator CASE_INSENSITIVE_ORDER + = new CaseInsensitiveComparator(); + + /** + * Creates an empty String (length 0). Unless you really need a new object, + * consider using <code>""</code> instead. + */ + public String() + { + value = "".value; + offset = 0; + count = 0; + } + + /** + * Copies the contents of a String to a new String. Since Strings are + * immutable, only a shallow copy is performed. + * + * @param str String to copy + * @throws NullPointerException if value is null + */ + public String(String str) + { + value = str.value; + offset = str.offset; + count = str.count; + cachedHashCode = str.cachedHashCode; + } + + /** + * Creates a new String using the character sequence of the char array. + * Subsequent changes to data do not affect the String. + * + * @param data char array to copy + * @throws NullPointerException if data is null + */ + public String(char[] data) + { + this(data, 0, data.length, false); + } + + /** + * Creates a new String using the character sequence of a subarray of + * characters. The string starts at offset, and copies count chars. + * Subsequent changes to data do not affect the String. + * + * @param data char array to copy + * @param offset position (base 0) to start copying out of data + * @param count the number of characters from data to copy + * @throws NullPointerException if data is null + * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 + * || offset + count > data.length) + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public String(char[] data, int offset, int count) + { + this(data, offset, count, false); + } + + /** + * Creates a new String using an 8-bit array of integer values, starting at + * an offset, and copying up to the count. Each character c, using + * corresponding byte b, is created in the new String as if by performing: + * + * <pre> + * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) + * </pre> + * + * @param ascii array of integer values + * @param hibyte top byte of each Unicode character + * @param offset position (base 0) to start copying out of ascii + * @param count the number of characters from ascii to copy + * @throws NullPointerException if ascii is null + * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 + * || offset + count > ascii.length) + * (while unspecified, this is a StringIndexOutOfBoundsException) + * @see #String(byte[]) + * @see #String(byte[], String) + * @see #String(byte[], int, int) + * @see #String(byte[], int, int, String) + * @deprecated use {@link #String(byte[], int, int, String)} to perform + * correct encoding + */ + public String(byte[] ascii, int hibyte, int offset, int count) + { + if (offset < 0 || count < 0 || offset + count > ascii.length) + throw new StringIndexOutOfBoundsException(); + value = new char[count]; + this.offset = 0; + this.count = count; + hibyte <<= 8; + offset += count; + while (--count >= 0) + value[count] = (char) (hibyte | (ascii[--offset] & 0xff)); + } + + /** + * Creates a new String using an 8-bit array of integer values. Each + * character c, using corresponding byte b, is created in the new String + * as if by performing: + * + * <pre> + * c = (char) (((hibyte & 0xff) << 8) | (b & 0xff)) + * </pre> + * + * @param ascii array of integer values + * @param hibyte top byte of each Unicode character + * @throws NullPointerException if ascii is null + * @see #String(byte[]) + * @see #String(byte[], String) + * @see #String(byte[], int, int) + * @see #String(byte[], int, int, String) + * @see #String(byte[], int, int, int) + * @deprecated use {@link #String(byte[], String)} to perform + * correct encoding + */ + public String(byte[] ascii, int hibyte) + { + this(ascii, hibyte, 0, ascii.length); + } + + /** + * Creates a new String using the portion of the byte array starting at the + * offset and ending at offset + count. Uses the specified encoding type + * to decode the byte array, so the resulting string may be longer or + * shorter than the byte array. For more decoding control, use + * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, + * see {@link java.nio.charset.Charset}. The behavior is not specified if + * the decoder encounters invalid characters; this implementation throws + * an Error. + * + * @param data byte array to copy + * @param offset the offset to start at + * @param count the number of bytes in the array to use + * @param encoding the name of the encoding to use + * @throws NullPointerException if data or encoding is null + * @throws IndexOutOfBoundsException if offset or count is incorrect + * (while unspecified, this is a StringIndexOutOfBoundsException) + * @throws UnsupportedEncodingException if encoding is not found + * @throws Error if the decoding fails + * @since 1.1 + */ + public String(byte[] data, int offset, int count, String encoding) + throws UnsupportedEncodingException + { + if (offset < 0 || count < 0 || offset + count > data.length) + throw new StringIndexOutOfBoundsException(); + try + { + CharsetDecoder csd = Charset.forName(encoding).newDecoder(); + csd.onMalformedInput(CodingErrorAction.REPLACE); + csd.onUnmappableCharacter(CodingErrorAction.REPLACE); + CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); + if(cbuf.hasArray()) + { + value = cbuf.array(); + this.offset = cbuf.position(); + this.count = cbuf.remaining(); + } else { + // Doubt this will happen. But just in case. + value = new char[cbuf.remaining()]; + cbuf.get(value); + this.offset = 0; + this.count = value.length; + } + } catch(CharacterCodingException e){ + throw new UnsupportedEncodingException("Encoding: "+encoding+ + " not found."); + } catch(IllegalCharsetNameException e){ + throw new UnsupportedEncodingException("Encoding: "+encoding+ + " not found."); + } catch(UnsupportedCharsetException e){ + throw new UnsupportedEncodingException("Encoding: "+encoding+ + " not found."); + } + } + + /** + * Creates a new String using the byte array. Uses the specified encoding + * type to decode the byte array, so the resulting string may be longer or + * shorter than the byte array. For more decoding control, use + * {@link java.nio.charset.CharsetDecoder}, and for valid character sets, + * see {@link java.nio.charset.Charset}. The behavior is not specified if + * the decoder encounters invalid characters; this implementation throws + * an Error. + * + * @param data byte array to copy + * @param encoding the name of the encoding to use + * @throws NullPointerException if data or encoding is null + * @throws UnsupportedEncodingException if encoding is not found + * @throws Error if the decoding fails + * @see #String(byte[], int, int, String) + * @since 1.1 + */ + public String(byte[] data, String encoding) + throws UnsupportedEncodingException + { + this(data, 0, data.length, encoding); + } + + /** + * Creates a new String using the portion of the byte array starting at the + * offset and ending at offset + count. Uses the encoding of the platform's + * default charset, so the resulting string may be longer or shorter than + * the byte array. For more decoding control, use + * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified + * if the decoder encounters invalid characters; this implementation throws + * an Error. + * + * @param data byte array to copy + * @param offset the offset to start at + * @param count the number of bytes in the array to use + * @throws NullPointerException if data is null + * @throws IndexOutOfBoundsException if offset or count is incorrect + * @throws Error if the decoding fails + * @see #String(byte[], int, int, String) + * @since 1.1 + */ + public String(byte[] data, int offset, int count) + { + if (offset < 0 || count < 0 || offset + count > data.length) + throw new StringIndexOutOfBoundsException(); + int o, c; + char[] v; + String encoding; + try + { + encoding = System.getProperty("file.encoding"); + CharsetDecoder csd = Charset.forName(encoding).newDecoder(); + csd.onMalformedInput(CodingErrorAction.REPLACE); + csd.onUnmappableCharacter(CodingErrorAction.REPLACE); + CharBuffer cbuf = csd.decode(ByteBuffer.wrap(data, offset, count)); + if(cbuf.hasArray()) + { + v = cbuf.array(); + o = cbuf.position(); + c = cbuf.remaining(); + } else { + // Doubt this will happen. But just in case. + v = new char[cbuf.remaining()]; + cbuf.get(v); + o = 0; + c = v.length; + } + } catch(Exception ex){ + // If anything goes wrong (System property not set, + // NIO provider not available, etc) + // Default to the 'safe' encoding ISO8859_1 + v = new char[count]; + o = 0; + c = count; + for (int i=0;i<count;i++) + v[i] = (char)data[offset+i]; + } + this.value = v; + this.offset = o; + this.count = c; + } + + /** + * Creates a new String using the byte array. Uses the encoding of the + * platform's default charset, so the resulting string may be longer or + * shorter than the byte array. For more decoding control, use + * {@link java.nio.charset.CharsetDecoder}. The behavior is not specified + * if the decoder encounters invalid characters; this implementation throws + * an Error. + * + * @param data byte array to copy + * @throws NullPointerException if data is null + * @throws Error if the decoding fails + * @see #String(byte[], int, int) + * @see #String(byte[], int, int, String) + * @since 1.1 + */ + public String(byte[] data) + { + this(data, 0, data.length); + } + + /** + * Creates a new String using the character sequence represented by + * the StringBuffer. Subsequent changes to buf do not affect the String. + * + * @param buffer StringBuffer to copy + * @throws NullPointerException if buffer is null + */ + public String(StringBuffer buffer) + { + synchronized (buffer) + { + offset = 0; + count = buffer.count; + // Share unless buffer is 3/4 empty. + if ((count << 2) < buffer.value.length) + { + value = new char[count]; + VMSystem.arraycopy(buffer.value, 0, value, 0, count); + } + else + { + buffer.shared = true; + value = buffer.value; + } + } + } + + /** + * Creates a new String using the character sequence represented by + * the StringBuilder. Subsequent changes to buf do not affect the String. + * + * @param buffer StringBuilder to copy + * @throws NullPointerException if buffer is null + */ + public String(StringBuilder buffer) + { + this(buffer.value, 0, buffer.count); + } + + /** + * Special constructor which can share an array when safe to do so. + * + * @param data the characters to copy + * @param offset the location to start from + * @param count the number of characters to use + * @param dont_copy true if the array is trusted, and need not be copied + * @throws NullPointerException if chars is null + * @throws StringIndexOutOfBoundsException if bounds check fails + */ + String(char[] data, int offset, int count, boolean dont_copy) + { + if (offset < 0 || count < 0 || offset + count > data.length) + throw new StringIndexOutOfBoundsException(); + if (dont_copy) + { + value = data; + this.offset = offset; + } + else + { + value = new char[count]; + VMSystem.arraycopy(data, offset, value, 0, count); + this.offset = 0; + } + this.count = count; + } + + /** + * Returns the number of characters contained in this String. + * + * @return the length of this String + */ + public int length() + { + return count; + } + + /** + * Returns the character located at the specified index within this String. + * + * @param index position of character to return (base 0) + * @return character located at position index + * @throws IndexOutOfBoundsException if index < 0 || index >= length() + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public char charAt(int index) + { + if (index < 0 || index >= count) + throw new StringIndexOutOfBoundsException(index); + return value[offset + index]; + } + + /** + * Copies characters from this String starting at a specified start index, + * ending at a specified stop index, to a character array starting at + * a specified destination begin index. + * + * @param srcBegin index to begin copying characters from this String + * @param srcEnd index after the last character to be copied from this String + * @param dst character array which this String is copied into + * @param dstBegin index to start writing characters into dst + * @throws NullPointerException if dst is null + * @throws IndexOutOfBoundsException if any indices are out of bounds + * (while unspecified, source problems cause a + * StringIndexOutOfBoundsException, and dst problems cause an + * ArrayIndexOutOfBoundsException) + */ + public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) + { + if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) + throw new StringIndexOutOfBoundsException(); + VMSystem.arraycopy(value, srcBegin + offset, + dst, dstBegin, srcEnd - srcBegin); + } + + /** + * Copies the low byte of each character from this String starting at a + * specified start index, ending at a specified stop index, to a byte array + * starting at a specified destination begin index. + * + * @param srcBegin index to being copying characters from this String + * @param srcEnd index after the last character to be copied from this String + * @param dst byte array which each low byte of this String is copied into + * @param dstBegin index to start writing characters into dst + * @throws NullPointerException if dst is null and copy length is non-zero + * @throws IndexOutOfBoundsException if any indices are out of bounds + * (while unspecified, source problems cause a + * StringIndexOutOfBoundsException, and dst problems cause an + * ArrayIndexOutOfBoundsException) + * @see #getBytes() + * @see #getBytes(String) + * @deprecated use {@link #getBytes()}, which uses a char to byte encoder + */ + public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) + { + if (srcBegin < 0 || srcBegin > srcEnd || srcEnd > count) + throw new StringIndexOutOfBoundsException(); + int i = srcEnd - srcBegin; + srcBegin += offset; + while (--i >= 0) + dst[dstBegin++] = (byte) value[srcBegin++]; + } + + /** + * Converts the Unicode characters in this String to a byte array. Uses the + * specified encoding method, so the result may be longer or shorter than + * the String. For more encoding control, use + * {@link java.nio.charset.CharsetEncoder}, and for valid character sets, + * see {@link java.nio.charset.Charset}. Unsupported characters get + * replaced by an encoding specific byte. + * + * @param enc encoding name + * @return the resulting byte array + * @throws NullPointerException if enc is null + * @throws UnsupportedEncodingException if encoding is not supported + * @since 1.1 + */ + public byte[] getBytes(String enc) throws UnsupportedEncodingException + { + try + { + CharsetEncoder cse = Charset.forName(enc).newEncoder(); + cse.onMalformedInput(CodingErrorAction.REPLACE); + cse.onUnmappableCharacter(CodingErrorAction.REPLACE); + ByteBuffer bbuf = cse.encode(CharBuffer.wrap(value, offset, count)); + if(bbuf.hasArray()) + return bbuf.array(); + + // Doubt this will happen. But just in case. + byte[] bytes = new byte[bbuf.remaining()]; + bbuf.get(bytes); + return bytes; + + } catch(IllegalCharsetNameException e){ + throw new UnsupportedEncodingException("Encoding: "+enc+ + " not found."); + } catch(UnsupportedCharsetException e){ + throw new UnsupportedEncodingException("Encoding: "+enc+ + " not found."); + } catch(CharacterCodingException e){ + // XXX - Ignore coding exceptions? They shouldn't really happen. + return null; + } + } + + /** + * Converts the Unicode characters in this String to a byte array. Uses the + * encoding of the platform's default charset, so the result may be longer + * or shorter than the String. For more encoding control, use + * {@link java.nio.charset.CharsetEncoder}. Unsupported characters get + * replaced by an encoding specific byte. + * + * @return the resulting byte array, or null on a problem + * @since 1.1 + */ + public byte[] getBytes() + { + try + { + return getBytes(System.getProperty("file.encoding")); + } catch(Exception e) { + // XXX - Throw an error here? + // For now, default to the 'safe' encoding. + byte[] bytes = new byte[count]; + for(int i=0;i<count;i++) + bytes[i] = (byte)((value[offset+i] <= 0xFF)? + value[offset+i]:'?'); + return bytes; + } + } + + /** + * Predicate which compares anObject to this. This is true only for Strings + * with the same character sequence. + * + * @param anObject the object to compare + * @return true if anObject is semantically equal to this + * @see #compareTo(String) + * @see #equalsIgnoreCase(String) + */ + public boolean equals(Object anObject) + { + if (! (anObject instanceof String)) + return false; + String str2 = (String) anObject; + if (count != str2.count) + return false; + if (value == str2.value && offset == str2.offset) + return true; + int i = count; + int x = offset; + int y = str2.offset; + while (--i >= 0) + if (value[x++] != str2.value[y++]) + return false; + return true; + } + + /** + * Compares the given StringBuffer to this String. This is true if the + * StringBuffer has the same content as this String at this moment. + * + * @param buffer the StringBuffer to compare to + * @return true if StringBuffer has the same character sequence + * @throws NullPointerException if the given StringBuffer is null + * @since 1.4 + */ + public boolean contentEquals(StringBuffer buffer) + { + synchronized (buffer) + { + if (count != buffer.count) + return false; + if (value == buffer.value) + return true; // Possible if shared. + int i = count; + int x = offset + count; + while (--i >= 0) + if (value[--x] != buffer.value[i]) + return false; + return true; + } + } + + /** + * Compares a String to this String, ignoring case. This does not handle + * multi-character capitalization exceptions; instead the comparison is + * made on a character-by-character basis, and is true if:<br><ul> + * <li><code>c1 == c2</code></li> + * <li><code>Character.toUpperCase(c1) + * == Character.toUpperCase(c2)</code></li> + * <li><code>Character.toLowerCase(c1) + * == Character.toLowerCase(c2)</code></li> + * </ul> + * + * @param anotherString String to compare to this String + * @return true if anotherString is equal, ignoring case + * @see #equals(Object) + * @see Character#toUpperCase(char) + * @see Character#toLowerCase(char) + */ + public boolean equalsIgnoreCase(String anotherString) + { + if (anotherString == null || count != anotherString.count) + return false; + int i = count; + int x = offset; + int y = anotherString.offset; + while (--i >= 0) + { + char c1 = value[x++]; + char c2 = anotherString.value[y++]; + // Note that checking c1 != c2 is redundant, but avoids method calls. + if (c1 != c2 + && Character.toUpperCase(c1) != Character.toUpperCase(c2) + && Character.toLowerCase(c1) != Character.toLowerCase(c2)) + return false; + } + return true; + } + + /** + * Compares this String and another String (case sensitive, + * lexicographically). The result is less than 0 if this string sorts + * before the other, 0 if they are equal, and greater than 0 otherwise. + * After any common starting sequence is skipped, the result is + * <code>this.charAt(k) - anotherString.charAt(k)</code> if both strings + * have characters remaining, or + * <code>this.length() - anotherString.length()</code> if one string is + * a subsequence of the other. + * + * @param anotherString the String to compare against + * @return the comparison + * @throws NullPointerException if anotherString is null + */ + public int compareTo(String anotherString) + { + int i = Math.min(count, anotherString.count); + int x = offset; + int y = anotherString.offset; + while (--i >= 0) + { + int result = value[x++] - anotherString.value[y++]; + if (result != 0) + return result; + } + return count - anotherString.count; + } + + /** + * Behaves like <code>compareTo(java.lang.String)</code> unless the Object + * is not a <code>String</code>. Then it throws a + * <code>ClassCastException</code>. + * + * @param o the object to compare against + * @return the comparison + * @throws NullPointerException if o is null + * @throws ClassCastException if o is not a <code>String</code> + * @since 1.2 + */ + public int compareTo(Object o) + { + return compareTo((String) o); + } + + /** + * Compares this String and another String (case insensitive). This + * comparison is <em>similar</em> to equalsIgnoreCase, in that it ignores + * locale and multi-characater capitalization, and compares characters + * after performing + * <code>Character.toLowerCase(Character.toUpperCase(c))</code> on each + * character of the string. This is unsatisfactory for locale-based + * comparison, in which case you should use {@link java.text.Collator}. + * + * @param str the string to compare against + * @return the comparison + * @see Collator#compare(String, String) + * @since 1.2 + */ + public int compareToIgnoreCase(String str) + { + int i = Math.min(count, str.count); + int x = offset; + int y = str.offset; + while (--i >= 0) + { + int result = Character.toLowerCase(Character.toUpperCase(value[x++])) + - Character.toLowerCase(Character.toUpperCase(str.value[y++])); + if (result != 0) + return result; + } + return count - str.count; + } + + /** + * Predicate which determines if this String matches another String + * starting at a specified offset for each String and continuing + * for a specified length. Indices out of bounds are harmless, and give + * a false result. + * + * @param toffset index to start comparison at for this String + * @param other String to compare region to this String + * @param ooffset index to start comparison at for other + * @param len number of characters to compare + * @return true if regions match (case sensitive) + * @throws NullPointerException if other is null + */ + public boolean regionMatches(int toffset, String other, int ooffset, int len) + { + return regionMatches(false, toffset, other, ooffset, len); + } + + /** + * Predicate which determines if this String matches another String + * starting at a specified offset for each String and continuing + * for a specified length, optionally ignoring case. Indices out of bounds + * are harmless, and give a false result. Case comparisons are based on + * <code>Character.toLowerCase()</code> and + * <code>Character.toUpperCase()</code>, not on multi-character + * capitalization expansions. + * + * @param ignoreCase true if case should be ignored in comparision + * @param toffset index to start comparison at for this String + * @param other String to compare region to this String + * @param ooffset index to start comparison at for other + * @param len number of characters to compare + * @return true if regions match, false otherwise + * @throws NullPointerException if other is null + */ + public boolean regionMatches(boolean ignoreCase, int toffset, + String other, int ooffset, int len) + { + if (toffset < 0 || ooffset < 0 || toffset + len > count + || ooffset + len > other.count) + return false; + toffset += offset; + ooffset += other.offset; + while (--len >= 0) + { + char c1 = value[toffset++]; + char c2 = other.value[ooffset++]; + // Note that checking c1 != c2 is redundant when ignoreCase is true, + // but it avoids method calls. + if (c1 != c2 + && (! ignoreCase + || (Character.toLowerCase(c1) != Character.toLowerCase(c2) + && (Character.toUpperCase(c1) + != Character.toUpperCase(c2))))) + return false; + } + return true; + } + + /** + * Predicate which determines if this String contains the given prefix, + * beginning comparison at toffset. The result is false if toffset is + * negative or greater than this.length(), otherwise it is the same as + * <code>this.substring(toffset).startsWith(prefix)</code>. + * + * @param prefix String to compare + * @param toffset offset for this String where comparison starts + * @return true if this String starts with prefix + * @throws NullPointerException if prefix is null + * @see #regionMatches(boolean, int, String, int, int) + */ + public boolean startsWith(String prefix, int toffset) + { + return regionMatches(false, toffset, prefix, 0, prefix.count); + } + + /** + * Predicate which determines if this String starts with a given prefix. + * If the prefix is an empty String, true is returned. + * + * @param prefix String to compare + * @return true if this String starts with the prefix + * @throws NullPointerException if prefix is null + * @see #startsWith(String, int) + */ + public boolean startsWith(String prefix) + { + return regionMatches(false, 0, prefix, 0, prefix.count); + } + + /** + * Predicate which determines if this String ends with a given suffix. + * If the suffix is an empty String, true is returned. + * + * @param suffix String to compare + * @return true if this String ends with the suffix + * @throws NullPointerException if suffix is null + * @see #regionMatches(boolean, int, String, int, int) + */ + public boolean endsWith(String suffix) + { + return regionMatches(false, count - suffix.count, suffix, 0, suffix.count); + } + + /** + * Computes the hashcode for this String. This is done with int arithmetic, + * where ** represents exponentiation, by this formula:<br> + * <code>s[0]*31**(n-1) + s[1]*31**(n-2) + ... + s[n-1]</code>. + * + * @return hashcode value of this String + */ + public int hashCode() + { + if (cachedHashCode != 0) + return cachedHashCode; + + // Compute the hash code using a local variable to be reentrant. + int hashCode = 0; + int limit = count + offset; + for (int i = offset; i < limit; i++) + hashCode = hashCode * 31 + value[i]; + return cachedHashCode = hashCode; + } + + /** + * Finds the first instance of a character in this String. + * + * @param ch character to find + * @return location (base 0) of the character, or -1 if not found + */ + public int indexOf(int ch) + { + return indexOf(ch, 0); + } + + /** + * Finds the first instance of a character in this String, starting at + * a given index. If starting index is less than 0, the search + * starts at the beginning of this String. If the starting index + * is greater than the length of this String, -1 is returned. + * + * @param ch character to find + * @param fromIndex index to start the search + * @return location (base 0) of the character, or -1 if not found + */ + public int indexOf(int ch, int fromIndex) + { + if ((char) ch != ch) + return -1; + if (fromIndex < 0) + fromIndex = 0; + int i = fromIndex + offset; + for ( ; fromIndex < count; fromIndex++) + if (value[i++] == ch) + return fromIndex; + return -1; + } + + /** + * Finds the last instance of a character in this String. + * + * @param ch character to find + * @return location (base 0) of the character, or -1 if not found + */ + public int lastIndexOf(int ch) + { + return lastIndexOf(ch, count - 1); + } + + /** + * Finds the last instance of a character in this String, starting at + * a given index. If starting index is greater than the maximum valid + * index, then the search begins at the end of this String. If the + * starting index is less than zero, -1 is returned. + * + * @param ch character to find + * @param fromIndex index to start the search + * @return location (base 0) of the character, or -1 if not found + */ + public int lastIndexOf(int ch, int fromIndex) + { + if ((char) ch != ch) + return -1; + if (fromIndex >= count) + fromIndex = count - 1; + int i = fromIndex + offset; + for ( ; fromIndex >= 0; fromIndex--) + if (value[i--] == ch) + return fromIndex; + return -1; + } + + /** + * Finds the first instance of a String in this String. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + */ + public int indexOf(String str) + { + return indexOf(str, 0); + } + + /** + * Finds the first instance of a String in this String, starting at + * a given index. If starting index is less than 0, the search + * starts at the beginning of this String. If the starting index + * is greater than the length of this String, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + */ + public int indexOf(String str, int fromIndex) + { + if (fromIndex < 0) + fromIndex = 0; + int limit = count - str.count; + for ( ; fromIndex <= limit; fromIndex++) + if (regionMatches(fromIndex, str, 0, str.count)) + return fromIndex; + return -1; + } + + /** + * Finds the last instance of a String in this String. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + */ + public int lastIndexOf(String str) + { + return lastIndexOf(str, count - str.count); + } + + /** + * Finds the last instance of a String in this String, starting at + * a given index. If starting index is greater than the maximum valid + * index, then the search begins at the end of this String. If the + * starting index is less than zero, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + */ + public int lastIndexOf(String str, int fromIndex) + { + fromIndex = Math.min(fromIndex, count - str.count); + for ( ; fromIndex >= 0; fromIndex--) + if (regionMatches(fromIndex, str, 0, str.count)) + return fromIndex; + return -1; + } + + /** + * Creates a substring of this String, starting at a specified index + * and ending at the end of this String. + * + * @param begin index to start substring (base 0) + * @return new String which is a substring of this String + * @throws IndexOutOfBoundsException if begin < 0 || begin > length() + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public String substring(int begin) + { + return substring(begin, count); + } + + /** + * Creates a substring of this String, starting at a specified index + * and ending at one character before a specified index. + * + * @param beginIndex index to start substring (inclusive, base 0) + * @param endIndex index to end at (exclusive) + * @return new String which is a substring of this String + * @throws IndexOutOfBoundsException if begin < 0 || end > length() + * || begin > end (while unspecified, this is a + * StringIndexOutOfBoundsException) + */ + public String substring(int beginIndex, int endIndex) + { + if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) + throw new StringIndexOutOfBoundsException(); + if (beginIndex == 0 && endIndex == count) + return this; + int len = endIndex - beginIndex; + // Package constructor avoids an array copy. + return new String(value, beginIndex + offset, len, + (len << 2) >= value.length); + } + + /** + * Creates a substring of this String, starting at a specified index + * and ending at one character before a specified index. This behaves like + * <code>substring(begin, end)</code>. + * + * @param begin index to start substring (inclusive, base 0) + * @param end index to end at (exclusive) + * @return new String which is a substring of this String + * @throws IndexOutOfBoundsException if begin < 0 || end > length() + * || begin > end + * @since 1.4 + */ + public CharSequence subSequence(int begin, int end) + { + return substring(begin, end); + } + + /** + * Concatenates a String to this String. This results in a new string unless + * one of the two originals is "". + * + * @param str String to append to this String + * @return newly concatenated String + * @throws NullPointerException if str is null + */ + public String concat(String str) + { + if (str.count == 0) + return this; + if (count == 0) + return str; + char[] newStr = new char[count + str.count]; + VMSystem.arraycopy(value, offset, newStr, 0, count); + VMSystem.arraycopy(str.value, str.offset, newStr, count, str.count); + // Package constructor avoids an array copy. + return new String(newStr, 0, newStr.length, true); + } + + /** + * Replaces every instance of a character in this String with a new + * character. If no replacements occur, this is returned. + * + * @param oldChar the old character to replace + * @param newChar the new character + * @return new String with all instances of oldChar replaced with newChar + */ + public String replace(char oldChar, char newChar) + { + if (oldChar == newChar) + return this; + int i = count; + int x = offset - 1; + while (--i >= 0) + if (value[++x] == oldChar) + break; + if (i < 0) + return this; + char[] newStr = (char[]) value.clone(); + newStr[x] = newChar; + while (--i >= 0) + if (value[++x] == oldChar) + newStr[x] = newChar; + // Package constructor avoids an array copy. + return new String(newStr, offset, count, true); + } + + /** + * Test if this String matches a regular expression. This is shorthand for + * <code>{@link Pattern}.matches(regex, this)</code>. + * + * @param regex the pattern to match + * @return true if the pattern matches + * @throws NullPointerException if regex is null + * @throws PatternSyntaxException if regex is invalid + * @see Pattern#matches(String, CharSequence) + * @since 1.4 + */ + public boolean matches(String regex) + { + return Pattern.matches(regex, this); + } + + /** + * Replaces the first substring match of the regular expression with a + * given replacement. This is shorthand for <code>{@link Pattern} + * .compile(regex).matcher(this).replaceFirst(replacement)</code>. + * + * @param regex the pattern to match + * @param replacement the replacement string + * @return the modified string + * @throws NullPointerException if regex or replacement is null + * @throws PatternSyntaxException if regex is invalid + * @see #replaceAll(String, String) + * @see Pattern#compile(String) + * @see Pattern#matcher(CharSequence) + * @see Matcher#replaceFirst(String) + * @since 1.4 + */ + public String replaceFirst(String regex, String replacement) + { + return Pattern.compile(regex).matcher(this).replaceFirst(replacement); + } + + /** + * Replaces all matching substrings of the regular expression with a + * given replacement. This is shorthand for <code>{@link Pattern} + * .compile(regex).matcher(this).replaceAll(replacement)</code>. + * + * @param regex the pattern to match + * @param replacement the replacement string + * @return the modified string + * @throws NullPointerException if regex or replacement is null + * @throws PatternSyntaxException if regex is invalid + * @see #replaceFirst(String, String) + * @see Pattern#compile(String) + * @see Pattern#matcher(CharSequence) + * @see Matcher#replaceAll(String) + * @since 1.4 + */ + public String replaceAll(String regex, String replacement) + { + return Pattern.compile(regex).matcher(this).replaceAll(replacement); + } + + /** + * Split this string around the matches of a regular expression. Each + * element of the returned array is the largest block of characters not + * terminated by the regular expression, in the order the matches are found. + * + * <p>The limit affects the length of the array. If it is positive, the + * array will contain at most n elements (n - 1 pattern matches). If + * negative, the array length is unlimited, but there can be trailing empty + * entries. if 0, the array length is unlimited, and trailing empty entries + * are discarded. + * + * <p>For example, splitting "boo:and:foo" yields:<br> + * <table border=0> + * <th><td>Regex</td> <td>Limit</td> <td>Result</td></th> + * <tr><td>":"</td> <td>2</td> <td>{ "boo", "and:foo" }</td></tr> + * <tr><td>":"</td> <td>t</td> <td>{ "boo", "and", "foo" }</td></tr> + * <tr><td>":"</td> <td>-2</td> <td>{ "boo", "and", "foo" }</td></tr> + * <tr><td>"o"</td> <td>5</td> <td>{ "b", "", ":and:f", "", "" }</td></tr> + * <tr><td>"o"</td> <td>-2</td> <td>{ "b", "", ":and:f", "", "" }</td></tr> + * <tr><td>"o"</td> <td>0</td> <td>{ "b", "", ":and:f" }</td></tr> + * </table> + * + * <p>This is shorthand for + * <code>{@link Pattern}.compile(regex).split(this, limit)</code>. + * + * @param regex the pattern to match + * @param limit the limit threshold + * @return the array of split strings + * @throws NullPointerException if regex or replacement is null + * @throws PatternSyntaxException if regex is invalid + * @see Pattern#compile(String) + * @see Pattern#split(CharSequence, int) + * @since 1.4 + */ + public String[] split(String regex, int limit) + { + return Pattern.compile(regex).split(this, limit); + } + + /** + * Split this string around the matches of a regular expression. Each + * element of the returned array is the largest block of characters not + * terminated by the regular expression, in the order the matches are found. + * The array length is unlimited, and trailing empty entries are discarded, + * as though calling <code>split(regex, 0)</code>. + * + * @param regex the pattern to match + * @return the array of split strings + * @throws NullPointerException if regex or replacement is null + * @throws PatternSyntaxException if regex is invalid + * @see #split(String, int) + * @see Pattern#compile(String) + * @see Pattern#split(CharSequence, int) + * @since 1.4 + */ + public String[] split(String regex) + { + return Pattern.compile(regex).split(this, 0); + } + + /** + * Lowercases this String according to a particular locale. This uses + * Unicode's special case mappings, as applied to the given Locale, so the + * resulting string may be a different length. + * + * @param loc locale to use + * @return new lowercased String, or this if no characters were lowercased + * @throws NullPointerException if loc is null + * @see #toUpperCase(Locale) + * @since 1.1 + */ + public String toLowerCase(Locale loc) + { + // First, see if the current string is already lower case. + boolean turkish = "tr".equals(loc.getLanguage()); + int i = count; + int x = offset - 1; + while (--i >= 0) + { + char ch = value[++x]; + if ((turkish && ch == '\u0049') + || ch != Character.toLowerCase(ch)) + break; + } + if (i < 0) + return this; + + // Now we perform the conversion. Fortunately, there are no multi-character + // lowercase expansions in Unicode 3.0.0. + char[] newStr = (char[]) value.clone(); + do + { + char ch = value[x]; + // Hardcoded special case. + newStr[x++] = (turkish && ch == '\u0049') ? '\u0131' + : Character.toLowerCase(ch); + } + while (--i >= 0); + // Package constructor avoids an array copy. + return new String(newStr, offset, count, true); + } + + /** + * Lowercases this String. This uses Unicode's special case mappings, as + * applied to the platform's default Locale, so the resulting string may + * be a different length. + * + * @return new lowercased String, or this if no characters were lowercased + * @see #toLowerCase(Locale) + * @see #toUpperCase() + */ + public String toLowerCase() + { + return toLowerCase(Locale.getDefault()); + } + + /** + * Uppercases this String according to a particular locale. This uses + * Unicode's special case mappings, as applied to the given Locale, so the + * resulting string may be a different length. + * + * @param loc locale to use + * @return new uppercased String, or this if no characters were uppercased + * @throws NullPointerException if loc is null + * @see #toLowerCase(Locale) + * @since 1.1 + */ + public String toUpperCase(Locale loc) + { + // First, see how many characters we have to grow by, as well as if the + // current string is already upper case. + boolean turkish = "tr".equals(loc.getLanguage()); + int expand = 0; + boolean unchanged = true; + int i = count; + int x = i + offset; + while (--i >= 0) + { + char ch = value[--x]; + expand += upperCaseExpansion(ch); + unchanged = (unchanged && expand == 0 + && ! (turkish && ch == '\u0069') + && ch == Character.toUpperCase(ch)); + } + if (unchanged) + return this; + + // Now we perform the conversion. + i = count; + if (expand == 0) + { + char[] newStr = (char[]) value.clone(); + while (--i >= 0) + { + char ch = value[x]; + // Hardcoded special case. + newStr[x++] = (turkish && ch == '\u0069') ? '\u0130' + : Character.toUpperCase(ch); + } + // Package constructor avoids an array copy. + return new String(newStr, offset, count, true); + } + + // Expansion is necessary. + char[] newStr = new char[count + expand]; + int j = 0; + while (--i >= 0) + { + char ch = value[x++]; + // Hardcoded special case. + if (turkish && ch == '\u0069') + { + newStr[j++] = '\u0130'; + continue; + } + expand = upperCaseExpansion(ch); + if (expand > 0) + { + int index = upperCaseIndex(ch); + while (expand-- >= 0) + newStr[j++] = upperExpand[index++]; + } + else + newStr[j++] = Character.toUpperCase(ch); + } + // Package constructor avoids an array copy. + return new String(newStr, 0, newStr.length, true); + } + + /** + * Uppercases this String. This uses Unicode's special case mappings, as + * applied to the platform's default Locale, so the resulting string may + * be a different length. + * + * @return new uppercased String, or this if no characters were uppercased + * @see #toUpperCase(Locale) + * @see #toLowerCase() + */ + public String toUpperCase() + { + return toUpperCase(Locale.getDefault()); + } + + /** + * Trims all characters less than or equal to <code>'\u0020'</code> + * (<code>' '</code>) from the beginning and end of this String. This + * includes many, but not all, ASCII control characters, and all + * {@link Character#isWhitespace(char)}. + * + * @return new trimmed String, or this if nothing trimmed + */ + public String trim() + { + int limit = count + offset; + if (count == 0 || (value[offset] > '\u0020' + && value[limit - 1] > '\u0020')) + return this; + int begin = offset; + do + if (begin == limit) + return ""; + while (value[begin++] <= '\u0020'); + int end = limit; + while (value[--end] <= '\u0020'); + return substring(begin - offset - 1, end - offset + 1); + } + + /** + * Returns this, as it is already a String! + * + * @return this + */ + public String toString() + { + return this; + } + + /** + * Copies the contents of this String into a character array. Subsequent + * changes to the array do not affect the String. + * + * @return character array copying the String + */ + public char[] toCharArray() + { + if (count == value.length) + return (char[]) value.clone(); + + char[] copy = new char[count]; + VMSystem.arraycopy(value, offset, copy, 0, count); + return copy; + } + + /** + * Returns a String representation of an Object. This is "null" if the + * object is null, otherwise it is <code>obj.toString()</code> (which + * can be null). + * + * @param obj the Object + * @return the string conversion of obj + */ + public static String valueOf(Object obj) + { + return obj == null ? "null" : obj.toString(); + } + + /** + * Returns a String representation of a character array. Subsequent + * changes to the array do not affect the String. + * + * @param data the character array + * @return a String containing the same character sequence as data + * @throws NullPointerException if data is null + * @see #valueOf(char[], int, int) + * @see #String(char[]) + */ + public static String valueOf(char[] data) + { + return valueOf (data, 0, data.length); + } + + /** + * Returns a String representing the character sequence of the char array, + * starting at the specified offset, and copying chars up to the specified + * count. Subsequent changes to the array do not affect the String. + * + * @param data character array + * @param offset position (base 0) to start copying out of data + * @param count the number of characters from data to copy + * @return String containing the chars from data[offset..offset+count] + * @throws NullPointerException if data is null + * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 + * || offset + count > data.length) + * (while unspecified, this is a StringIndexOutOfBoundsException) + * @see #String(char[], int, int) + */ + public static String valueOf(char[] data, int offset, int count) + { + return new String(data, offset, count, false); + } + + /** + * Returns a String representing the character sequence of the char array, + * starting at the specified offset, and copying chars up to the specified + * count. Subsequent changes to the array do not affect the String. + * + * @param data character array + * @param offset position (base 0) to start copying out of data + * @param count the number of characters from data to copy + * @return String containing the chars from data[offset..offset+count] + * @throws NullPointerException if data is null + * @throws IndexOutOfBoundsException if (offset < 0 || count < 0 + * || offset + count > data.length) + * (while unspecified, this is a StringIndexOutOfBoundsException) + * @see #String(char[], int, int) + */ + public static String copyValueOf(char[] data, int offset, int count) + { + return new String(data, offset, count, false); + } + + /** + * Returns a String representation of a character array. Subsequent + * changes to the array do not affect the String. + * + * @param data the character array + * @return a String containing the same character sequence as data + * @throws NullPointerException if data is null + * @see #copyValueOf(char[], int, int) + * @see #String(char[]) + */ + public static String copyValueOf(char[] data) + { + return copyValueOf (data, 0, data.length); + } + + /** + * Returns a String representing a boolean. + * + * @param b the boolean + * @return "true" if b is true, else "false" + */ + public static String valueOf(boolean b) + { + return b ? "true" : "false"; + } + + /** + * Returns a String representing a character. + * + * @param c the character + * @return String containing the single character c + */ + public static String valueOf(char c) + { + // Package constructor avoids an array copy. + return new String(new char[] { c }, 0, 1, true); + } + + /** + * Returns a String representing an integer. + * + * @param i the integer + * @return String containing the integer in base 10 + * @see Integer#toString(int) + */ + public static String valueOf(int i) + { + // See Integer to understand why we call the two-arg variant. + return Integer.toString(i, 10); + } + + /** + * Returns a String representing a long. + * + * @param l the long + * @return String containing the long in base 10 + * @see Long#toString(long) + */ + public static String valueOf(long l) + { + return Long.toString(l); + } + + /** + * Returns a String representing a float. + * + * @param f the float + * @return String containing the float + * @see Float#toString(float) + */ + public static String valueOf(float f) + { + return Float.toString(f); + } + + /** + * Returns a String representing a double. + * + * @param d the double + * @return String containing the double + * @see Double#toString(double) + */ + public static String valueOf(double d) + { + return Double.toString(d); + } + + /** + * If two Strings are considered equal, by the equals() method, + * then intern() will return the same String instance. ie. + * if (s1.equals(s2)) then (s1.intern() == s2.intern()). + * All string literals and string-valued constant expressions + * are already interned. + * + * @return the interned String + */ + public String intern() + { + return VMString.intern(this); + } + + /** + * Helper function used to detect which characters have a multi-character + * uppercase expansion. Note that this is only used in locations which + * track one-to-many capitalization (java.lang.Character does not do this). + * As of Unicode 3.0.0, the result is limited in the range 0 to 2, as the + * longest uppercase expansion is three characters (a growth of 2 from the + * lowercase character). + * + * @param ch the char to check + * @return the number of characters to add when converting to uppercase + * @see CharData#DIRECTION + * @see CharData#UPPER_SPECIAL + * @see #toUpperCase(Locale) + */ + private static int upperCaseExpansion(char ch) + { + return Character.direction[Character.readChar(ch) >> 7] & 3; + } + + /** + * Helper function used to locate the offset in upperExpand given a + * character with a multi-character expansion. The binary search is + * optimized under the assumption that this method will only be called on + * characters which exist in upperSpecial. + * + * @param ch the char to check + * @return the index where its expansion begins + * @see CharData#UPPER_SPECIAL + * @see CharData#UPPER_EXPAND + * @see #toUpperCase(Locale) + */ + private static int upperCaseIndex(char ch) + { + // Simple binary search for the correct character. + int low = 0; + int hi = upperSpecial.length - 2; + int mid = ((low + hi) >> 2) << 1; + char c = upperSpecial[mid]; + while (ch != c) + { + if (ch < c) + hi = mid - 2; + else + low = mid + 2; + mid = ((low + hi) >> 2) << 1; + c = upperSpecial[mid]; + } + return upperSpecial[mid + 1]; + } + + /** + * Returns the value array of the given string if it is zero based or a + * copy of it that is zero based (stripping offset and making length equal + * to count). Used for accessing the char[]s of gnu.java.lang.CharData. + * Package private for use in Character. + */ + static char[] zeroBasedStringValue(String s) + { + char[] value; + + if (s.offset == 0 && s.count == s.value.length) + value = s.value; + else + { + int count = s.count; + value = new char[count]; + VMSystem.arraycopy(s.value, s.offset, value, 0, count); + } + + return value; + } +} diff --git a/libjava/classpath/java/lang/StringBuffer.java b/libjava/classpath/java/lang/StringBuffer.java new file mode 100644 index 0000000..94dec48 --- /dev/null +++ b/libjava/classpath/java/lang/StringBuffer.java @@ -0,0 +1,931 @@ +/* StringBuffer.java -- Growable strings + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.io.Serializable; + +/** + * <code>StringBuffer</code> represents a changeable <code>String</code>. + * It provides the operations required to modify the + * <code>StringBuffer</code>, including insert, replace, delete, append, + * and reverse. It is thread-safe; meaning that all modifications to a buffer + * are in synchronized methods. + * + * <p><code>StringBuffer</code>s are variable-length in nature, so even if + * you initialize them to a certain size, they can still grow larger than + * that. <em>Capacity</em> indicates the number of characters the + * <code>StringBuffer</code> can have in it before it has to grow (growing + * the char array is an expensive operation involving <code>new</code>). + * + * <p>Incidentally, compilers often implement the String operator "+" + * by using a <code>StringBuffer</code> operation:<br> + * <code>a + b</code><br> + * is the same as<br> + * <code>new StringBuffer().append(a).append(b).toString()</code>. + * + * <p>Classpath's StringBuffer is capable of sharing memory with Strings for + * efficiency. This will help when a StringBuffer is converted to a String + * and the StringBuffer is not changed after that (quite common when performing + * string concatenation). + * + * @author Paul Fisher + * @author John Keiser + * @author Tom Tromey + * @author Eric Blake (ebb9@email.byu.edu) + * @see String + * @since 1.0 + * @status updated to 1.4 + */ +public final class StringBuffer implements Serializable, CharSequence +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 3388685877147921107L; + + /** + * Index of next available character (and thus the size of the current + * string contents). Note that this has permissions set this way so that + * String can get the value. + * + * @serial the number of characters in the buffer + */ + int count; + + /** + * The buffer. Note that this has permissions set this way so that String + * can get the value. + * + * @serial the buffer + */ + char[] value; + + /** + * True if the buffer is shared with another object (StringBuffer or + * String); this means the buffer must be copied before writing to it again. + * Note that this has permissions set this way so that String can get the + * value. + * + * @serial whether the buffer is shared + */ + boolean shared; + + /** + * The default capacity of a buffer. + */ + private static final int DEFAULT_CAPACITY = 16; + + /** + * Create a new StringBuffer with default capacity 16. + */ + public StringBuffer() + { + this(DEFAULT_CAPACITY); + } + + /** + * Create an empty <code>StringBuffer</code> with the specified initial + * capacity. + * + * @param capacity the initial capacity + * @throws NegativeArraySizeException if capacity is negative + */ + public StringBuffer(int capacity) + { + value = new char[capacity]; + } + + /** + * Create a new <code>StringBuffer</code> with the characters in the + * specified <code>String</code>. Initial capacity will be the size of the + * String plus 16. + * + * @param str the <code>String</code> to convert + * @throws NullPointerException if str is null + */ + public StringBuffer(String str) + { + // Unfortunately, because the size is 16 larger, we cannot share. + count = str.count; + value = new char[count + DEFAULT_CAPACITY]; + str.getChars(0, count, value, 0); + } + + /** + * Get the length of the <code>String</code> this <code>StringBuffer</code> + * would create. Not to be confused with the <em>capacity</em> of the + * <code>StringBuffer</code>. + * + * @return the length of this <code>StringBuffer</code> + * @see #capacity() + * @see #setLength(int) + */ + public synchronized int length() + { + return count; + } + + /** + * Get the total number of characters this <code>StringBuffer</code> can + * support before it must be grown. Not to be confused with <em>length</em>. + * + * @return the capacity of this <code>StringBuffer</code> + * @see #length() + * @see #ensureCapacity(int) + */ + public synchronized int capacity() + { + return value.length; + } + + /** + * Increase the capacity of this <code>StringBuffer</code>. This will + * ensure that an expensive growing operation will not occur until + * <code>minimumCapacity</code> is reached. The buffer is grown to the + * larger of <code>minimumCapacity</code> and + * <code>capacity() * 2 + 2</code>, if it is not already large enough. + * + * @param minimumCapacity the new capacity + * @see #capacity() + */ + public synchronized void ensureCapacity(int minimumCapacity) + { + ensureCapacity_unsynchronized(minimumCapacity); + } + + /** + * Set the length of this StringBuffer. If the new length is greater than + * the current length, all the new characters are set to '\0'. If the new + * length is less than the current length, the first <code>newLength</code> + * characters of the old array will be preserved, and the remaining + * characters are truncated. + * + * @param newLength the new length + * @throws IndexOutOfBoundsException if the new length is negative + * (while unspecified, this is a StringIndexOutOfBoundsException) + * @see #length() + */ + public synchronized void setLength(int newLength) + { + if (newLength < 0) + throw new StringIndexOutOfBoundsException(newLength); + + int valueLength = value.length; + + /* Always call ensureCapacity_unsynchronized in order to preserve + copy-on-write semantics. */ + ensureCapacity_unsynchronized(newLength); + + if (newLength < valueLength) + { + /* If the StringBuffer's value just grew, then we know that + value is newly allocated and the region between count and + newLength is filled with '\0'. */ + count = newLength; + } + else + { + /* The StringBuffer's value doesn't need to grow. However, + we should clear out any cruft that may exist. */ + while (count < newLength) + value[count++] = '\0'; + } + } + + /** + * Get the character at the specified index. + * + * @param index the index of the character to get, starting at 0 + * @return the character at the specified index + * @throws IndexOutOfBoundsException if index is negative or >= length() + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public synchronized char charAt(int index) + { + if (index < 0 || index >= count) + throw new StringIndexOutOfBoundsException(index); + return value[index]; + } + + /** + * Get the specified array of characters. <code>srcOffset - srcEnd</code> + * characters will be copied into the array you pass in. + * + * @param srcOffset the index to start copying from (inclusive) + * @param srcEnd the index to stop copying from (exclusive) + * @param dst the array to copy into + * @param dstOffset the index to start copying into + * @throws NullPointerException if dst is null + * @throws IndexOutOfBoundsException if any source or target indices are + * out of range (while unspecified, source problems cause a + * StringIndexOutOfBoundsException, and dest problems cause an + * ArrayIndexOutOfBoundsException) + * @see System#arraycopy(Object, int, Object, int, int) + */ + public synchronized void getChars(int srcOffset, int srcEnd, + char[] dst, int dstOffset) + { + if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset) + throw new StringIndexOutOfBoundsException(); + VMSystem.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset); + } + + /** + * Set the character at the specified index. + * + * @param index the index of the character to set starting at 0 + * @param ch the value to set that character to + * @throws IndexOutOfBoundsException if index is negative or >= length() + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public synchronized void setCharAt(int index, char ch) + { + if (index < 0 || index >= count) + throw new StringIndexOutOfBoundsException(index); + // Call ensureCapacity to enforce copy-on-write. + ensureCapacity_unsynchronized(count); + value[index] = ch; + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param obj the <code>Object</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(Object) + * @see #append(String) + */ + public StringBuffer append(Object obj) + { + return append(obj == null ? "null" : obj.toString()); + } + + /** + * Append the <code>String</code> to this <code>StringBuffer</code>. If + * str is null, the String "null" is appended. + * + * @param str the <code>String</code> to append + * @return this <code>StringBuffer</code> + */ + public synchronized StringBuffer append(String str) + { + if (str == null) + str = "null"; + int len = str.count; + ensureCapacity_unsynchronized(count + len); + str.getChars(0, len, value, count); + count += len; + return this; + } + + /** + * Append the <code>StringBuffer</code> value of the argument to this + * <code>StringBuffer</code>. This behaves the same as + * <code>append((Object) stringBuffer)</code>, except it is more efficient. + * + * @param stringBuffer the <code>StringBuffer</code> to convert and append + * @return this <code>StringBuffer</code> + * @see #append(Object) + * @since 1.4 + */ + public synchronized StringBuffer append(StringBuffer stringBuffer) + { + if (stringBuffer == null) + return append("null"); + synchronized (stringBuffer) + { + int len = stringBuffer.count; + ensureCapacity_unsynchronized(count + len); + VMSystem.arraycopy(stringBuffer.value, 0, value, count, len); + count += len; + } + return this; + } + + /** + * Append the <code>char</code> array to this <code>StringBuffer</code>. + * This is similar (but more efficient) than + * <code>append(new String(data))</code>, except in the case of null. + * + * @param data the <code>char[]</code> to append + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @see #append(char[], int, int) + */ + public StringBuffer append(char[] data) + { + return append(data, 0, data.length); + } + + /** + * Append part of the <code>char</code> array to this + * <code>StringBuffer</code>. This is similar (but more efficient) than + * <code>append(new String(data, offset, count))</code>, except in the case + * of null. + * + * @param data the <code>char[]</code> to append + * @param offset the start location in <code>str</code> + * @param count the number of characters to get from <code>str</code> + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @throws IndexOutOfBoundsException if offset or count is out of range + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public synchronized StringBuffer append(char[] data, int offset, int count) + { + if (offset < 0 || count < 0 || offset > data.length - count) + throw new StringIndexOutOfBoundsException(); + ensureCapacity_unsynchronized(this.count + count); + VMSystem.arraycopy(data, offset, value, this.count, count); + this.count += count; + return this; + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param bool the <code>boolean</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(boolean) + */ + public StringBuffer append(boolean bool) + { + return append(bool ? "true" : "false"); + } + + /** + * Append the <code>char</code> to this <code>StringBuffer</code>. + * + * @param ch the <code>char</code> to append + * @return this <code>StringBuffer</code> + */ + public synchronized StringBuffer append(char ch) + { + ensureCapacity_unsynchronized(count + 1); + value[count++] = ch; + return this; + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param inum the <code>int</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(int) + */ + // This is native in libgcj, for efficiency. + public StringBuffer append(int inum) + { + return append(String.valueOf(inum)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param lnum the <code>long</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(long) + */ + public StringBuffer append(long lnum) + { + return append(Long.toString(lnum, 10)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param fnum the <code>float</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(float) + */ + public StringBuffer append(float fnum) + { + return append(Float.toString(fnum)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param dnum the <code>double</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(double) + */ + public StringBuffer append(double dnum) + { + return append(Double.toString(dnum)); + } + + /** + * Delete characters from this <code>StringBuffer</code>. + * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is + * harmless for end to be larger than length(). + * + * @param start the first character to delete + * @param end the index after the last character to delete + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if start or end are out of bounds + * @since 1.2 + */ + public synchronized StringBuffer delete(int start, int end) + { + if (start < 0 || start > count || start > end) + throw new StringIndexOutOfBoundsException(start); + if (end > count) + end = count; + // This will unshare if required. + ensureCapacity_unsynchronized(count); + if (count - end != 0) + VMSystem.arraycopy(value, end, value, start, count - end); + count -= end - start; + return this; + } + + /** + * Delete a character from this <code>StringBuffer</code>. + * + * @param index the index of the character to delete + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if index is out of bounds + * @since 1.2 + */ + public StringBuffer deleteCharAt(int index) + { + return delete(index, index + 1); + } + + /** + * Replace characters between index <code>start</code> (inclusive) and + * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> + * is larger than the size of this StringBuffer, all characters after + * <code>start</code> are replaced. + * + * @param start the beginning index of characters to delete (inclusive) + * @param end the ending index of characters to delete (exclusive) + * @param str the new <code>String</code> to insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if start or end are out of bounds + * @throws NullPointerException if str is null + * @since 1.2 + */ + public synchronized StringBuffer replace(int start, int end, String str) + { + if (start < 0 || start > count || start > end) + throw new StringIndexOutOfBoundsException(start); + + int len = str.count; + // Calculate the difference in 'count' after the replace. + int delta = len - (end > count ? count : end) + start; + ensureCapacity_unsynchronized(count + delta); + + if (delta != 0 && end < count) + VMSystem.arraycopy(value, end, value, end + delta, count - end); + + str.getChars(0, len, value, start); + count += delta; + return this; + } + + /** + * Creates a substring of this StringBuffer, starting at a specified index + * and ending at the end of this StringBuffer. + * + * @param beginIndex index to start substring (base 0) + * @return new String which is a substring of this StringBuffer + * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds + * @see #substring(int, int) + * @since 1.2 + */ + public String substring(int beginIndex) + { + return substring(beginIndex, count); + } + + /** + * Creates a substring of this StringBuffer, starting at a specified index + * and ending at one character before a specified index. This is implemented + * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy + * the CharSequence interface. + * + * @param beginIndex index to start at (inclusive, base 0) + * @param endIndex index to end at (exclusive) + * @return new String which is a substring of this StringBuffer + * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of + * bounds + * @see #substring(int, int) + * @since 1.4 + */ + public CharSequence subSequence(int beginIndex, int endIndex) + { + return substring(beginIndex, endIndex); + } + + /** + * Creates a substring of this StringBuffer, starting at a specified index + * and ending at one character before a specified index. + * + * @param beginIndex index to start at (inclusive, base 0) + * @param endIndex index to end at (exclusive) + * @return new String which is a substring of this StringBuffer + * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out + * of bounds + * @since 1.2 + */ + public synchronized String substring(int beginIndex, int endIndex) + { + int len = endIndex - beginIndex; + if (beginIndex < 0 || endIndex > count || endIndex < beginIndex) + throw new StringIndexOutOfBoundsException(); + if (len == 0) + return ""; + // Don't copy unless substring is smaller than 1/4 of the buffer. + boolean share_buffer = ((len << 2) >= value.length); + if (share_buffer) + this.shared = true; + // Package constructor avoids an array copy. + return new String(value, beginIndex, len, share_buffer); + } + + /** + * Insert a subarray of the <code>char[]</code> argument into this + * <code>StringBuffer</code>. + * + * @param offset the place to insert in this buffer + * @param str the <code>char[]</code> to insert + * @param str_offset the index in <code>str</code> to start inserting from + * @param len the number of characters to insert + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @throws StringIndexOutOfBoundsException if any index is out of bounds + * @since 1.2 + */ + public synchronized StringBuffer insert(int offset, + char[] str, int str_offset, int len) + { + if (offset < 0 || offset > count || len < 0 + || str_offset < 0 || str_offset > str.length - len) + throw new StringIndexOutOfBoundsException(); + ensureCapacity_unsynchronized(count + len); + VMSystem.arraycopy(value, offset, value, offset + len, count - offset); + VMSystem.arraycopy(str, str_offset, value, offset, len); + count += len; + return this; + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param obj the <code>Object</code> to convert and insert + * @return this <code>StringBuffer</code> + * @exception StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(Object) + */ + public StringBuffer insert(int offset, Object obj) + { + return insert(offset, obj == null ? "null" : obj.toString()); + } + + /** + * Insert the <code>String</code> argument into this + * <code>StringBuffer</code>. If str is null, the String "null" is used + * instead. + * + * @param offset the place to insert in this buffer + * @param str the <code>String</code> to insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + */ + public synchronized StringBuffer insert(int offset, String str) + { + if (offset < 0 || offset > count) + throw new StringIndexOutOfBoundsException(offset); + if (str == null) + str = "null"; + int len = str.count; + ensureCapacity_unsynchronized(count + len); + VMSystem.arraycopy(value, offset, value, offset + len, count - offset); + str.getChars(0, len, value, offset); + count += len; + return this; + } + + /** + * Insert the <code>char[]</code> argument into this + * <code>StringBuffer</code>. + * + * @param offset the place to insert in this buffer + * @param data the <code>char[]</code> to insert + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>data</code> is <code>null</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see #insert(int, char[], int, int) + */ + public StringBuffer insert(int offset, char[] data) + { + return insert(offset, data, 0, data.length); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param bool the <code>boolean</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(boolean) + */ + public StringBuffer insert(int offset, boolean bool) + { + return insert(offset, bool ? "true" : "false"); + } + + /** + * Insert the <code>char</code> argument into this <code>StringBuffer</code>. + * + * @param offset the place to insert in this buffer + * @param ch the <code>char</code> to insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + */ + public synchronized StringBuffer insert(int offset, char ch) + { + if (offset < 0 || offset > count) + throw new StringIndexOutOfBoundsException(offset); + ensureCapacity_unsynchronized(count + 1); + VMSystem.arraycopy(value, offset, value, offset + 1, count - offset); + value[offset] = ch; + count++; + return this; + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param inum the <code>int</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(int) + */ + public StringBuffer insert(int offset, int inum) + { + return insert(offset, String.valueOf(inum)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param lnum the <code>long</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(long) + */ + public StringBuffer insert(int offset, long lnum) + { + return insert(offset, Long.toString(lnum, 10)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param fnum the <code>float</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(float) + */ + public StringBuffer insert(int offset, float fnum) + { + return insert(offset, Float.toString(fnum)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param dnum the <code>double</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(double) + */ + public StringBuffer insert(int offset, double dnum) + { + return insert(offset, Double.toString(dnum)); + } + + /** + * Finds the first instance of a substring in this StringBuffer. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @see #indexOf(String, int) + * @since 1.4 + */ + public int indexOf(String str) + { + return indexOf(str, 0); + } + + /** + * Finds the first instance of a String in this StringBuffer, starting at + * a given index. If starting index is less than 0, the search starts at + * the beginning of this String. If the starting index is greater than the + * length of this String, or the substring is not found, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @since 1.4 + */ + public synchronized int indexOf(String str, int fromIndex) + { + if (fromIndex < 0) + fromIndex = 0; + int limit = count - str.count; + for ( ; fromIndex <= limit; fromIndex++) + if (regionMatches(fromIndex, str)) + return fromIndex; + return -1; + } + + /** + * Finds the last instance of a substring in this StringBuffer. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @see #lastIndexOf(String, int) + * @since 1.4 + */ + public int lastIndexOf(String str) + { + return lastIndexOf(str, count - str.count); + } + + /** + * Finds the last instance of a String in this StringBuffer, starting at a + * given index. If starting index is greater than the maximum valid index, + * then the search begins at the end of this String. If the starting index + * is less than zero, or the substring is not found, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @since 1.4 + */ + public synchronized int lastIndexOf(String str, int fromIndex) + { + fromIndex = Math.min(fromIndex, count - str.count); + for ( ; fromIndex >= 0; fromIndex--) + if (regionMatches(fromIndex, str)) + return fromIndex; + return -1; + } + + /** + * Reverse the characters in this StringBuffer. The same sequence of + * characters exists, but in the reverse index ordering. + * + * @return this <code>StringBuffer</code> + */ + public synchronized StringBuffer reverse() + { + // Call ensureCapacity to enforce copy-on-write. + ensureCapacity_unsynchronized(count); + for (int i = count >> 1, j = count - i; --i >= 0; ++j) + { + char c = value[i]; + value[i] = value[j]; + value[j] = c; + } + return this; + } + + /** + * Convert this <code>StringBuffer</code> to a <code>String</code>. The + * String is composed of the characters currently in this StringBuffer. Note + * that the result is a copy, and that future modifications to this buffer + * do not affect the String. + * + * @return the characters in this StringBuffer + */ + public String toString() + { + // The string will set this.shared = true. + return new String(this); + } + + /** + * An unsynchronized version of ensureCapacity, used internally to avoid + * the cost of a second lock on the same object. This also has the side + * effect of duplicating the array, if it was shared (to form copy-on-write + * semantics). + * + * @param minimumCapacity the minimum capacity + * @see #ensureCapacity(int) + */ + private void ensureCapacity_unsynchronized(int minimumCapacity) + { + if (shared || minimumCapacity > value.length) + { + // We don't want to make a larger vector when `shared' is + // set. If we do, then setLength becomes very inefficient + // when repeatedly reusing a StringBuffer in a loop. + int max = (minimumCapacity > value.length + ? value.length * 2 + 2 + : value.length); + minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); + char[] nb = new char[minimumCapacity]; + VMSystem.arraycopy(value, 0, nb, 0, count); + value = nb; + shared = false; + } + } + + /** + * Predicate which determines if a substring of this matches another String + * starting at a specified offset for each String and continuing for a + * specified length. This is more efficient than creating a String to call + * indexOf on. + * + * @param toffset index to start comparison at for this String + * @param other non-null String to compare to region of this + * @return true if regions match, false otherwise + * @see #indexOf(String, int) + * @see #lastIndexOf(String, int) + * @see String#regionMatches(boolean, int, String, int, int) + */ + private boolean regionMatches(int toffset, String other) + { + int len = other.count; + int index = other.offset; + while (--len >= 0) + if (value[toffset++] != other.value[index++]) + return false; + return true; + } +} diff --git a/libjava/classpath/java/lang/StringBuilder.java b/libjava/classpath/java/lang/StringBuilder.java new file mode 100644 index 0000000..b54c8ef --- /dev/null +++ b/libjava/classpath/java/lang/StringBuilder.java @@ -0,0 +1,944 @@ +/* StringBuilder.java -- Unsynchronized growable strings + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.io.Serializable; + +/** + * <code>StringBuilder</code> represents a changeable <code>String</code>. + * It provides the operations required to modify the + * <code>StringBuilder</code>, including insert, replace, delete, append, + * and reverse. It like <code>StringBuffer</code>, but is not + * synchronized. It is ideal for use when it is known that the + * object will only be used from a single thread. + * + * <p><code>StringBuilder</code>s are variable-length in nature, so even if + * you initialize them to a certain size, they can still grow larger than + * that. <em>Capacity</em> indicates the number of characters the + * <code>StringBuilder</code> can have in it before it has to grow (growing + * the char array is an expensive operation involving <code>new</code>). + * + * <p>Incidentally, compilers often implement the String operator "+" + * by using a <code>StringBuilder</code> operation:<br> + * <code>a + b</code><br> + * is the same as<br> + * <code>new StringBuilder().append(a).append(b).toString()</code>. + * + * <p>Classpath's StringBuilder is capable of sharing memory with Strings for + * efficiency. This will help when a StringBuilder is converted to a String + * and the StringBuilder is not changed after that (quite common when + * performing string concatenation). + * + * @author Paul Fisher + * @author John Keiser + * @author Tom Tromey + * @author Eric Blake (ebb9@email.byu.edu) + * @see String + * @see StringBuffer + * + * @since 1.5 + */ +// FIX15: Implement Appendable when co-variant methods are available +public final class StringBuilder + implements Serializable, CharSequence +{ + // Implementation note: if you change this class, you usually will + // want to change StringBuffer as well. + + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 4383685877147921099L; + + /** + * Index of next available character (and thus the size of the current + * string contents). Note that this has permissions set this way so that + * String can get the value. + * + * @serial the number of characters in the buffer + */ + int count; + + /** + * The buffer. Note that this has permissions set this way so that String + * can get the value. + * + * @serial the buffer + */ + char[] value; + + /** + * The default capacity of a buffer. + */ + private static final int DEFAULT_CAPACITY = 16; + + /** + * Create a new StringBuilder with default capacity 16. + */ + public StringBuilder() + { + this(DEFAULT_CAPACITY); + } + + /** + * Create an empty <code>StringBuilder</code> with the specified initial + * capacity. + * + * @param capacity the initial capacity + * @throws NegativeArraySizeException if capacity is negative + */ + public StringBuilder(int capacity) + { + value = new char[capacity]; + } + + /** + * Create a new <code>StringBuilder</code> with the characters in the + * specified <code>String</code>. Initial capacity will be the size of the + * String plus 16. + * + * @param str the <code>String</code> to convert + * @throws NullPointerException if str is null + */ + public StringBuilder(String str) + { + // Unfortunately, because the size is 16 larger, we cannot share. + count = str.count; + value = new char[count + DEFAULT_CAPACITY]; + str.getChars(0, count, value, 0); + } + + /** + * Create a new <code>StringBuilder</code> with the characters in the + * specified <code>CharSequence</code>. Initial capacity will be the + * length of the sequence plus 16; if the sequence reports a length + * less than or equal to 0, then the initial capacity will be 16. + * + * @param seq the initializing <code>CharSequence</code> + * @throws NullPointerException if str is null + */ + public StringBuilder(CharSequence seq) + { + int len = seq.length(); + count = len <= 0 ? 0 : len; + value = new char[count + DEFAULT_CAPACITY]; + for (int i = 0; i < len; ++i) + value[i] = seq.charAt(i); + } + + /** + * Get the length of the <code>String</code> this <code>StringBuilder</code> + * would create. Not to be confused with the <em>capacity</em> of the + * <code>StringBuilder</code>. + * + * @return the length of this <code>StringBuilder</code> + * @see #capacity() + * @see #setLength(int) + */ + public int length() + { + return count; + } + + /** + * Get the total number of characters this <code>StringBuilder</code> can + * support before it must be grown. Not to be confused with <em>length</em>. + * + * @return the capacity of this <code>StringBuilder</code> + * @see #length() + * @see #ensureCapacity(int) + */ + public int capacity() + { + return value.length; + } + + /** + * Increase the capacity of this <code>StringBuilder</code>. This will + * ensure that an expensive growing operation will not occur until + * <code>minimumCapacity</code> is reached. The buffer is grown to the + * larger of <code>minimumCapacity</code> and + * <code>capacity() * 2 + 2</code>, if it is not already large enough. + * + * @param minimumCapacity the new capacity + * @see #capacity() + */ + public void ensureCapacity(int minimumCapacity) + { + if (minimumCapacity > value.length) + { + int max = value.length * 2 + 2; + minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); + char[] nb = new char[minimumCapacity]; + System.arraycopy(value, 0, nb, 0, count); + value = nb; + } + } + + /** + * Set the length of this StringBuilder. If the new length is greater than + * the current length, all the new characters are set to '\0'. If the new + * length is less than the current length, the first <code>newLength</code> + * characters of the old array will be preserved, and the remaining + * characters are truncated. + * + * @param newLength the new length + * @throws IndexOutOfBoundsException if the new length is negative + * (while unspecified, this is a StringIndexOutOfBoundsException) + * @see #length() + */ + public void setLength(int newLength) + { + if (newLength < 0) + throw new StringIndexOutOfBoundsException(newLength); + + int valueLength = value.length; + + /* Always call ensureCapacity in order to preserve copy-on-write + semantics. */ + ensureCapacity(newLength); + + if (newLength < valueLength) + { + /* If the StringBuilder's value just grew, then we know that + value is newly allocated and the region between count and + newLength is filled with '\0'. */ + count = newLength; + } + else + { + /* The StringBuilder's value doesn't need to grow. However, + we should clear out any cruft that may exist. */ + while (count < newLength) + value[count++] = '\0'; + } + } + + /** + * Get the character at the specified index. + * + * @param index the index of the character to get, starting at 0 + * @return the character at the specified index + * @throws IndexOutOfBoundsException if index is negative or >= length() + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public char charAt(int index) + { + if (index < 0 || index >= count) + throw new StringIndexOutOfBoundsException(index); + return value[index]; + } + + /** + * Get the specified array of characters. <code>srcOffset - srcEnd</code> + * characters will be copied into the array you pass in. + * + * @param srcOffset the index to start copying from (inclusive) + * @param srcEnd the index to stop copying from (exclusive) + * @param dst the array to copy into + * @param dstOffset the index to start copying into + * @throws NullPointerException if dst is null + * @throws IndexOutOfBoundsException if any source or target indices are + * out of range (while unspecified, source problems cause a + * StringIndexOutOfBoundsException, and dest problems cause an + * ArrayIndexOutOfBoundsException) + * @see System#arraycopy(Object, int, Object, int, int) + */ + public void getChars(int srcOffset, int srcEnd, + char[] dst, int dstOffset) + { + if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset) + throw new StringIndexOutOfBoundsException(); + System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset); + } + + /** + * Set the character at the specified index. + * + * @param index the index of the character to set starting at 0 + * @param ch the value to set that character to + * @throws IndexOutOfBoundsException if index is negative or >= length() + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public void setCharAt(int index, char ch) + { + if (index < 0 || index >= count) + throw new StringIndexOutOfBoundsException(index); + // Call ensureCapacity to enforce copy-on-write. + ensureCapacity(count); + value[index] = ch; + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param obj the <code>Object</code> to convert and append + * @return this <code>StringBuilder</code> + * @see String#valueOf(Object) + * @see #append(String) + */ + public StringBuilder append(Object obj) + { + return append(obj == null ? "null" : obj.toString()); + } + + /** + * Append the <code>String</code> to this <code>StringBuilder</code>. If + * str is null, the String "null" is appended. + * + * @param str the <code>String</code> to append + * @return this <code>StringBuilder</code> + */ + public StringBuilder append(String str) + { + if (str == null) + str = "null"; + int len = str.count; + ensureCapacity(count + len); + str.getChars(0, len, value, count); + count += len; + return this; + } + + /** + * Append the <code>StringBuilder</code> value of the argument to this + * <code>StringBuilder</code>. This behaves the same as + * <code>append((Object) stringBuffer)</code>, except it is more efficient. + * + * @param stringBuffer the <code>StringBuilder</code> to convert and append + * @return this <code>StringBuilder</code> + * @see #append(Object) + */ + public StringBuilder append(StringBuffer stringBuffer) + { + if (stringBuffer == null) + return append("null"); + synchronized (stringBuffer) + { + int len = stringBuffer.count; + ensureCapacity(count + len); + System.arraycopy(stringBuffer.value, 0, value, count, len); + count += len; + } + return this; + } + + /** + * Append the <code>char</code> array to this <code>StringBuilder</code>. + * This is similar (but more efficient) than + * <code>append(new String(data))</code>, except in the case of null. + * + * @param data the <code>char[]</code> to append + * @return this <code>StringBuilder</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @see #append(char[], int, int) + */ + public StringBuilder append(char[] data) + { + return append(data, 0, data.length); + } + + /** + * Append part of the <code>char</code> array to this + * <code>StringBuilder</code>. This is similar (but more efficient) than + * <code>append(new String(data, offset, count))</code>, except in the case + * of null. + * + * @param data the <code>char[]</code> to append + * @param offset the start location in <code>str</code> + * @param count the number of characters to get from <code>str</code> + * @return this <code>StringBuilder</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @throws IndexOutOfBoundsException if offset or count is out of range + * (while unspecified, this is a StringIndexOutOfBoundsException) + */ + public StringBuilder append(char[] data, int offset, int count) + { + if (offset < 0 || count < 0 || offset > data.length - count) + throw new StringIndexOutOfBoundsException(); + ensureCapacity(this.count + count); + System.arraycopy(data, offset, value, this.count, count); + this.count += count; + return this; + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param bool the <code>boolean</code> to convert and append + * @return this <code>StringBuilder</code> + * @see String#valueOf(boolean) + */ + public StringBuilder append(boolean bool) + { + return append(bool ? "true" : "false"); + } + + /** + * Append the <code>char</code> to this <code>StringBuilder</code>. + * + * @param ch the <code>char</code> to append + * @return this <code>StringBuilder</code> + */ + public StringBuilder append(char ch) + { + ensureCapacity(count + 1); + value[count++] = ch; + return this; + } + + /** + * Append the characters in the <code>CharSequence</code> to this + * buffer. + * + * @param seq the <code>CharSequence</code> providing the characters + * @return this <code>StringBuilder</code> + */ + public StringBuilder append(CharSequence seq) + { + return append(seq, 0, seq.length()); + } + + /** + * Append some characters from the <code>CharSequence</code> to this + * buffer. If the argument is null, the four characters "null" are + * appended. + * + * @param seq the <code>CharSequence</code> providing the characters + * @param start the starting index + * @param end one past the final index + * @return this <code>StringBuilder</code> + */ + public StringBuilder append(CharSequence seq, int start, + int end) + { + if (seq == null) + return append("null"); + if (end - start > 0) + { + ensureCapacity(count + end - start); + for (; start < end; ++start) + value[count++] = seq.charAt(start); + } + return this; + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param inum the <code>int</code> to convert and append + * @return this <code>StringBuilder</code> + * @see String#valueOf(int) + */ + // This is native in libgcj, for efficiency. + public StringBuilder append(int inum) + { + return append(String.valueOf(inum)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param lnum the <code>long</code> to convert and append + * @return this <code>StringBuilder</code> + * @see String#valueOf(long) + */ + public StringBuilder append(long lnum) + { + return append(Long.toString(lnum, 10)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param fnum the <code>float</code> to convert and append + * @return this <code>StringBuilder</code> + * @see String#valueOf(float) + */ + public StringBuilder append(float fnum) + { + return append(Float.toString(fnum)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param dnum the <code>double</code> to convert and append + * @return this <code>StringBuilder</code> + * @see String#valueOf(double) + */ + public StringBuilder append(double dnum) + { + return append(Double.toString(dnum)); + } + + /** + * Delete characters from this <code>StringBuilder</code>. + * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is + * harmless for end to be larger than length(). + * + * @param start the first character to delete + * @param end the index after the last character to delete + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if start or end are out of bounds + */ + public StringBuilder delete(int start, int end) + { + if (start < 0 || start > count || start > end) + throw new StringIndexOutOfBoundsException(start); + if (end > count) + end = count; + // This will unshare if required. + ensureCapacity(count); + if (count - end != 0) + System.arraycopy(value, end, value, start, count - end); + count -= end - start; + return this; + } + + /** + * Delete a character from this <code>StringBuilder</code>. + * + * @param index the index of the character to delete + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if index is out of bounds + */ + public StringBuilder deleteCharAt(int index) + { + return delete(index, index + 1); + } + + /** + * Replace characters between index <code>start</code> (inclusive) and + * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> + * is larger than the size of this StringBuilder, all characters after + * <code>start</code> are replaced. + * + * @param start the beginning index of characters to delete (inclusive) + * @param end the ending index of characters to delete (exclusive) + * @param str the new <code>String</code> to insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if start or end are out of bounds + * @throws NullPointerException if str is null + */ + public StringBuilder replace(int start, int end, String str) + { + if (start < 0 || start > count || start > end) + throw new StringIndexOutOfBoundsException(start); + + int len = str.count; + // Calculate the difference in 'count' after the replace. + int delta = len - (end > count ? count : end) + start; + ensureCapacity(count + delta); + + if (delta != 0 && end < count) + System.arraycopy(value, end, value, end + delta, count - end); + + str.getChars(0, len, value, start); + count += delta; + return this; + } + + /** + * Creates a substring of this StringBuilder, starting at a specified index + * and ending at the end of this StringBuilder. + * + * @param beginIndex index to start substring (base 0) + * @return new String which is a substring of this StringBuilder + * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds + * @see #substring(int, int) + */ + public String substring(int beginIndex) + { + return substring(beginIndex, count); + } + + /** + * Creates a substring of this StringBuilder, starting at a specified index + * and ending at one character before a specified index. This is implemented + * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy + * the CharSequence interface. + * + * @param beginIndex index to start at (inclusive, base 0) + * @param endIndex index to end at (exclusive) + * @return new String which is a substring of this StringBuilder + * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of + * bounds + * @see #substring(int, int) + */ + public CharSequence subSequence(int beginIndex, int endIndex) + { + return substring(beginIndex, endIndex); + } + + /** + * Creates a substring of this StringBuilder, starting at a specified index + * and ending at one character before a specified index. + * + * @param beginIndex index to start at (inclusive, base 0) + * @param endIndex index to end at (exclusive) + * @return new String which is a substring of this StringBuilder + * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out + * of bounds + */ + public String substring(int beginIndex, int endIndex) + { + int len = endIndex - beginIndex; + if (beginIndex < 0 || endIndex > count || endIndex < beginIndex) + throw new StringIndexOutOfBoundsException(); + if (len == 0) + return ""; + return new String(value, beginIndex, len); + } + + /** + * Insert a subarray of the <code>char[]</code> argument into this + * <code>StringBuilder</code>. + * + * @param offset the place to insert in this buffer + * @param str the <code>char[]</code> to insert + * @param str_offset the index in <code>str</code> to start inserting from + * @param len the number of characters to insert + * @return this <code>StringBuilder</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @throws StringIndexOutOfBoundsException if any index is out of bounds + */ + public StringBuilder insert(int offset, + char[] str, int str_offset, int len) + { + if (offset < 0 || offset > count || len < 0 + || str_offset < 0 || str_offset > str.length - len) + throw new StringIndexOutOfBoundsException(); + ensureCapacity(count + len); + System.arraycopy(value, offset, value, offset + len, count - offset); + System.arraycopy(str, str_offset, value, offset, len); + count += len; + return this; + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param obj the <code>Object</code> to convert and insert + * @return this <code>StringBuilder</code> + * @exception StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(Object) + */ + public StringBuilder insert(int offset, Object obj) + { + return insert(offset, obj == null ? "null" : obj.toString()); + } + + /** + * Insert the <code>String</code> argument into this + * <code>StringBuilder</code>. If str is null, the String "null" is used + * instead. + * + * @param offset the place to insert in this buffer + * @param str the <code>String</code> to insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + */ + public StringBuilder insert(int offset, String str) + { + if (offset < 0 || offset > count) + throw new StringIndexOutOfBoundsException(offset); + if (str == null) + str = "null"; + int len = str.count; + ensureCapacity(count + len); + System.arraycopy(value, offset, value, offset + len, count - offset); + str.getChars(0, len, value, offset); + count += len; + return this; + } + + /** + * Insert the <code>char[]</code> argument into this + * <code>StringBuilder</code>. + * + * @param offset the place to insert in this buffer + * @param data the <code>char[]</code> to insert + * @return this <code>StringBuilder</code> + * @throws NullPointerException if <code>data</code> is <code>null</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see #insert(int, char[], int, int) + */ + public StringBuilder insert(int offset, char[] data) + { + return insert(offset, data, 0, data.length); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param bool the <code>boolean</code> to convert and insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(boolean) + */ + public StringBuilder insert(int offset, boolean bool) + { + return insert(offset, bool ? "true" : "false"); + } + + /** + * Insert the <code>char</code> argument into this <code>StringBuilder</code>. + * + * @param offset the place to insert in this buffer + * @param ch the <code>char</code> to insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + */ + public StringBuilder insert(int offset, char ch) + { + if (offset < 0 || offset > count) + throw new StringIndexOutOfBoundsException(offset); + ensureCapacity(count + 1); + System.arraycopy(value, offset, value, offset + 1, count - offset); + value[offset] = ch; + count++; + return this; + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param inum the <code>int</code> to convert and insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(int) + */ + public StringBuilder insert(int offset, int inum) + { + return insert(offset, String.valueOf(inum)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param lnum the <code>long</code> to convert and insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(long) + */ + public StringBuilder insert(int offset, long lnum) + { + return insert(offset, Long.toString(lnum, 10)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param fnum the <code>float</code> to convert and insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(float) + */ + public StringBuilder insert(int offset, float fnum) + { + return insert(offset, Float.toString(fnum)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuilder</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param dnum the <code>double</code> to convert and insert + * @return this <code>StringBuilder</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(double) + */ + public StringBuilder insert(int offset, double dnum) + { + return insert(offset, Double.toString(dnum)); + } + + /** + * Finds the first instance of a substring in this StringBuilder. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @see #indexOf(String, int) + */ + public int indexOf(String str) + { + return indexOf(str, 0); + } + + /** + * Finds the first instance of a String in this StringBuilder, starting at + * a given index. If starting index is less than 0, the search starts at + * the beginning of this String. If the starting index is greater than the + * length of this String, or the substring is not found, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + */ + public int indexOf(String str, int fromIndex) + { + if (fromIndex < 0) + fromIndex = 0; + int limit = count - str.count; + for ( ; fromIndex <= limit; fromIndex++) + if (regionMatches(fromIndex, str)) + return fromIndex; + return -1; + } + + /** + * Finds the last instance of a substring in this StringBuilder. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @see #lastIndexOf(String, int) + */ + public int lastIndexOf(String str) + { + return lastIndexOf(str, count - str.count); + } + + /** + * Finds the last instance of a String in this StringBuilder, starting at a + * given index. If starting index is greater than the maximum valid index, + * then the search begins at the end of this String. If the starting index + * is less than zero, or the substring is not found, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + */ + public int lastIndexOf(String str, int fromIndex) + { + fromIndex = Math.min(fromIndex, count - str.count); + for ( ; fromIndex >= 0; fromIndex--) + if (regionMatches(fromIndex, str)) + return fromIndex; + return -1; + } + + /** + * Reverse the characters in this StringBuilder. The same sequence of + * characters exists, but in the reverse index ordering. + * + * @return this <code>StringBuilder</code> + */ + public StringBuilder reverse() + { + // Call ensureCapacity to enforce copy-on-write. + ensureCapacity(count); + for (int i = count >> 1, j = count - i; --i >= 0; ++j) + { + char c = value[i]; + value[i] = value[j]; + value[j] = c; + } + return this; + } + + /** + * Convert this <code>StringBuilder</code> to a <code>String</code>. The + * String is composed of the characters currently in this StringBuilder. Note + * that the result is a copy, and that future modifications to this buffer + * do not affect the String. + * + * @return the characters in this StringBuilder + */ + public String toString() + { + return new String(this); + } + + /** + * Predicate which determines if a substring of this matches another String + * starting at a specified offset for each String and continuing for a + * specified length. This is more efficient than creating a String to call + * indexOf on. + * + * @param toffset index to start comparison at for this String + * @param other non-null String to compare to region of this + * @return true if regions match, false otherwise + * @see #indexOf(String, int) + * @see #lastIndexOf(String, int) + * @see String#regionMatches(boolean, int, String, int, int) + */ + private boolean regionMatches(int toffset, String other) + { + int len = other.count; + int index = other.offset; + while (--len >= 0) + if (value[toffset++] != other.value[index++]) + return false; + return true; + } +} diff --git a/libjava/classpath/java/lang/StringIndexOutOfBoundsException.java b/libjava/classpath/java/lang/StringIndexOutOfBoundsException.java new file mode 100644 index 0000000..ebc4a04 --- /dev/null +++ b/libjava/classpath/java/lang/StringIndexOutOfBoundsException.java @@ -0,0 +1,85 @@ +/* StringIndexOutOfBoundsException.java -- thrown to indicate attempt to + exceed string bounds + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * This exception can be thrown to indicate an attempt to access an index + * which is out of bounds of a String. Any negative integer, and a positive + * integer greater than or equal to the size of the string, is an index + * which would be out of bounds. + * + * @author Brian Jones + * @author Warren Levy (warrenl@cygnus.com) + * @status updated to 1.4 + */ +public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -6762910422159637258L; + + /** + * Create an exception without a message. + */ + public StringIndexOutOfBoundsException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public StringIndexOutOfBoundsException(String s) + { + super(s); + } + + /** + * Create an exception noting the illegal index. + * + * @param index the invalid index + */ + public StringIndexOutOfBoundsException(int index) + { + super("String index out of range: " + index); + } +} diff --git a/libjava/classpath/java/lang/System.java b/libjava/classpath/java/lang/System.java new file mode 100644 index 0000000..e466d3b --- /dev/null +++ b/libjava/classpath/java/lang/System.java @@ -0,0 +1,528 @@ +/* System.java -- useful methods to interface with the system + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +import gnu.classpath.SystemProperties; +import gnu.classpath.VMStackWalker; + +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Properties; +import java.util.PropertyPermission; + +/** + * System represents system-wide resources; things that represent the + * general environment. As such, all methods are static. + * + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status still missing 1.4 functionality + */ +public final class System +{ + // WARNING: System is a CORE class in the bootstrap cycle. See the comments + // in vm/reference/java/lang/Runtime for implications of this fact. + + /** + * The standard InputStream. This is assigned at startup and starts its + * life perfectly valid. Although it is marked final, you can change it + * using {@link #setIn(InputStream)} through some hefty VM magic. + * + * <p>This corresponds to the C stdin and C++ cin variables, which + * typically input from the keyboard, but may be used to pipe input from + * other processes or files. That should all be transparent to you, + * however. + */ + public static final InputStream in = VMSystem.makeStandardInputStream(); + + /** + * The standard output PrintStream. This is assigned at startup and + * starts its life perfectly valid. Although it is marked final, you can + * change it using {@link #setOut(PrintStream)} through some hefty VM magic. + * + * <p>This corresponds to the C stdout and C++ cout variables, which + * typically output normal messages to the screen, but may be used to pipe + * output to other processes or files. That should all be transparent to + * you, however. + */ + public static final PrintStream out = VMSystem.makeStandardOutputStream(); + + /** + * The standard output PrintStream. This is assigned at startup and + * starts its life perfectly valid. Although it is marked final, you can + * change it using {@link #setErr(PrintStream)} through some hefty VM magic. + * + * <p>This corresponds to the C stderr and C++ cerr variables, which + * typically output error messages to the screen, but may be used to pipe + * output to other processes or files. That should all be transparent to + * you, however. + */ + public static final PrintStream err = VMSystem.makeStandardErrorStream(); + + /** + * This class is uninstantiable. + */ + private System() + { + } + + /** + * Set {@link #in} to a new InputStream. This uses some VM magic to change + * a "final" variable, so naturally there is a security check, + * <code>RuntimePermission("setIO")</code>. + * + * @param in the new InputStream + * @throws SecurityException if permission is denied + * @since 1.1 + */ + public static void setIn(InputStream in) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new RuntimePermission("setIO")); + VMSystem.setIn(in); + } + + /** + * Set {@link #out} to a new PrintStream. This uses some VM magic to change + * a "final" variable, so naturally there is a security check, + * <code>RuntimePermission("setIO")</code>. + * + * @param out the new PrintStream + * @throws SecurityException if permission is denied + * @since 1.1 + */ + public static void setOut(PrintStream out) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new RuntimePermission("setIO")); + + VMSystem.setOut(out); + } + + /** + * Set {@link #err} to a new PrintStream. This uses some VM magic to change + * a "final" variable, so naturally there is a security check, + * <code>RuntimePermission("setIO")</code>. + * + * @param err the new PrintStream + * @throws SecurityException if permission is denied + * @since 1.1 + */ + public static void setErr(PrintStream err) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new RuntimePermission("setIO")); + VMSystem.setErr(err); + } + + /** + * Set the current SecurityManager. If a security manager already exists, + * then <code>RuntimePermission("setSecurityManager")</code> is checked + * first. Since this permission is denied by the default security manager, + * setting the security manager is often an irreversible action. + * + * <STRONG>Spec Note:</STRONG> Don't ask me, I didn't write it. It looks + * pretty vulnerable; whoever gets to the gate first gets to set the policy. + * There is probably some way to set the original security manager as a + * command line argument to the VM, but I don't know it. + * + * @param sm the new SecurityManager + * @throws SecurityException if permission is denied + */ + public static synchronized void setSecurityManager(SecurityManager sm) + { + // Implementation note: the field lives in SecurityManager because of + // bootstrap initialization issues. This method is synchronized so that + // no other thread changes it to null before this thread makes the change. + if (SecurityManager.current != null) + SecurityManager.current.checkPermission + (new RuntimePermission("setSecurityManager")); + SecurityManager.current = sm; + } + + /** + * Get the current SecurityManager. If the SecurityManager has not been + * set yet, then this method returns null. + * + * @return the current SecurityManager, or null + */ + public static SecurityManager getSecurityManager() + { + return SecurityManager.current; + } + + /** + * Get the current time, measured in the number of milliseconds from the + * beginning of Jan. 1, 1970. This is gathered from the system clock, with + * any attendant incorrectness (it may be timezone dependent). + * + * @return the current time + * @see java.util.Date + */ + public static long currentTimeMillis() + { + return VMSystem.currentTimeMillis(); + } + + /** + * Copy one array onto another from <code>src[srcStart]</code> ... + * <code>src[srcStart+len-1]</code> to <code>dest[destStart]</code> ... + * <code>dest[destStart+len-1]</code>. First, the arguments are validated: + * neither array may be null, they must be of compatible types, and the + * start and length must fit within both arrays. Then the copying starts, + * and proceeds through increasing slots. If src and dest are the same + * array, this will appear to copy the data to a temporary location first. + * An ArrayStoreException in the middle of copying will leave earlier + * elements copied, but later elements unchanged. + * + * @param src the array to copy elements from + * @param srcStart the starting position in src + * @param dest the array to copy elements to + * @param destStart the starting position in dest + * @param len the number of elements to copy + * @throws NullPointerException if src or dest is null + * @throws ArrayStoreException if src or dest is not an array, if they are + * not compatible array types, or if an incompatible runtime type + * is stored in dest + * @throws IndexOutOfBoundsException if len is negative, or if the start or + * end copy position in either array is out of bounds + */ + public static void arraycopy(Object src, int srcStart, + Object dest, int destStart, int len) + { + VMSystem.arraycopy(src, srcStart, dest, destStart, len); + } + + /** + * Get a hash code computed by the VM for the Object. This hash code will + * be the same as Object's hashCode() method. It is usually some + * convolution of the pointer to the Object internal to the VM. It + * follows standard hash code rules, in that it will remain the same for a + * given Object for the lifetime of that Object. + * + * @param o the Object to get the hash code for + * @return the VM-dependent hash code for this Object + * @since 1.1 + */ + public static int identityHashCode(Object o) + { + return VMSystem.identityHashCode(o); + } + + /** + * Get all the system properties at once. A security check may be performed, + * <code>checkPropertiesAccess</code>. Note that a security manager may + * allow getting a single property, but not the entire group. + * + * <p>The required properties include: + * <dl> + * <dt>java.version</dt> <dd>Java version number</dd> + * <dt>java.vendor</dt> <dd>Java vendor specific string</dd> + * <dt>java.vendor.url</dt> <dd>Java vendor URL</dd> + * <dt>java.home</dt> <dd>Java installation directory</dd> + * <dt>java.vm.specification.version</dt> <dd>VM Spec version</dd> + * <dt>java.vm.specification.vendor</dt> <dd>VM Spec vendor</dd> + * <dt>java.vm.specification.name</dt> <dd>VM Spec name</dd> + * <dt>java.vm.version</dt> <dd>VM implementation version</dd> + * <dt>java.vm.vendor</dt> <dd>VM implementation vendor</dd> + * <dt>java.vm.name</dt> <dd>VM implementation name</dd> + * <dt>java.specification.version</dt> <dd>Java Runtime Environment version</dd> + * <dt>java.specification.vendor</dt> <dd>Java Runtime Environment vendor</dd> + * <dt>java.specification.name</dt> <dd>Java Runtime Environment name</dd> + * <dt>java.class.version</dt> <dd>Java class version number</dd> + * <dt>java.class.path</dt> <dd>Java classpath</dd> + * <dt>java.library.path</dt> <dd>Path for finding Java libraries</dd> + * <dt>java.io.tmpdir</dt> <dd>Default temp file path</dd> + * <dt>java.compiler</dt> <dd>Name of JIT to use</dd> + * <dt>java.ext.dirs</dt> <dd>Java extension path</dd> + * <dt>os.name</dt> <dd>Operating System Name</dd> + * <dt>os.arch</dt> <dd>Operating System Architecture</dd> + * <dt>os.version</dt> <dd>Operating System Version</dd> + * <dt>file.separator</dt> <dd>File separator ("/" on Unix)</dd> + * <dt>path.separator</dt> <dd>Path separator (":" on Unix)</dd> + * <dt>line.separator</dt> <dd>Line separator ("\n" on Unix)</dd> + * <dt>user.name</dt> <dd>User account name</dd> + * <dt>user.home</dt> <dd>User home directory</dd> + * <dt>user.dir</dt> <dd>User's current working directory</dd> + * </dl> + * + * In addition, gnu defines several other properties, where ? stands for + * each character in '0' through '9': + * <dl> + * <dt>gnu.classpath.home</dt> <dd>Path to the classpath libraries.</dd> + * <dt>gnu.classpath.version</dt> <dd>Version of the classpath libraries.</dd> + * <dt>gnu.classpath.vm.shortname</dt> <dd>Succinct version of the VM name; + * used for finding property files in file system</dd> + * <dt>gnu.classpath.home.url</dt> <dd> Base URL; used for finding + * property files in file system</dd> + * <dt>gnu.cpu.endian</dt> <dd>big or little</dd> + * <dt>gnu.java.io.encoding_scheme_alias.iso-8859-?</dt> <dd>8859_?</dd> + * <dt>gnu.java.io.encoding_scheme_alias.iso8859_?</dt> <dd>8859_?</dd> + * <dt>gnu.java.io.encoding_scheme_alias.iso-latin-_?</dt> <dd>8859_?</dd> + * <dt>gnu.java.io.encoding_scheme_alias.latin?</dt> <dd>8859_?</dd> + * <dt>gnu.java.io.encoding_scheme_alias.utf-8</dt> <dd>UTF8</dd> + * </dl> + * + * @return the system properties, will never be null + * @throws SecurityException if permission is denied + */ + public static Properties getProperties() + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPropertiesAccess(); + return SystemProperties.getProperties(); + } + + /** + * Set all the system properties at once. A security check may be performed, + * <code>checkPropertiesAccess</code>. Note that a security manager may + * allow setting a single property, but not the entire group. An argument + * of null resets the properties to the startup default. + * + * @param properties the new set of system properties + * @throws SecurityException if permission is denied + */ + public static void setProperties(Properties properties) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPropertiesAccess(); + SystemProperties.setProperties(properties); + } + + /** + * Get a single system property by name. A security check may be performed, + * <code>checkPropertyAccess(key)</code>. + * + * @param key the name of the system property to get + * @return the property, or null if not found + * @throws SecurityException if permission is denied + * @throws NullPointerException if key is null + * @throws IllegalArgumentException if key is "" + */ + public static String getProperty(String key) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPropertyAccess(key); + else if (key.length() == 0) + throw new IllegalArgumentException("key can't be empty"); + return SystemProperties.getProperty(key); + } + + /** + * Get a single system property by name. A security check may be performed, + * <code>checkPropertyAccess(key)</code>. + * + * @param key the name of the system property to get + * @param def the default + * @return the property, or def if not found + * @throws SecurityException if permission is denied + * @throws NullPointerException if key is null + * @throws IllegalArgumentException if key is "" + */ + public static String getProperty(String key, String def) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPropertyAccess(key); + return SystemProperties.getProperty(key, def); + } + + /** + * Set a single system property by name. A security check may be performed, + * <code>checkPropertyAccess(key, "write")</code>. + * + * @param key the name of the system property to set + * @param value the new value + * @return the previous value, or null + * @throws SecurityException if permission is denied + * @throws NullPointerException if key is null + * @throws IllegalArgumentException if key is "" + * @since 1.2 + */ + public static String setProperty(String key, String value) + { + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new PropertyPermission(key, "write")); + return SystemProperties.setProperty(key, value); + } + + /** + * Gets the value of an environment variable. + * + * @param name the name of the environment variable + * @return the string value of the variable or null when the + * environment variable is not defined. + * @throws NullPointerException + * @throws SecurityException if permission is denied + * @since 1.5 + * @specnote This method was deprecated in some JDK releases, but + * was restored in 1.5. + */ + public static String getenv(String name) + { + if (name == null) + throw new NullPointerException(); + SecurityManager sm = SecurityManager.current; // Be thread-safe. + if (sm != null) + sm.checkPermission(new RuntimePermission("getenv." + name)); + return VMSystem.getenv(name); + } + + /** + * Terminate the Virtual Machine. This just calls + * <code>Runtime.getRuntime().exit(status)</code>, and never returns. + * Obviously, a security check is in order, <code>checkExit</code>. + * + * @param status the exit status; by convention non-zero is abnormal + * @throws SecurityException if permission is denied + * @see Runtime#exit(int) + */ + public static void exit(int status) + { + Runtime.getRuntime().exit(status); + } + + /** + * Calls the garbage collector. This is only a hint, and it is up to the + * implementation what this hint suggests, but it usually causes a + * best-effort attempt to reclaim unused memory from discarded objects. + * This calls <code>Runtime.getRuntime().gc()</code>. + * + * @see Runtime#gc() + */ + public static void gc() + { + Runtime.getRuntime().gc(); + } + + /** + * Runs object finalization on pending objects. This is only a hint, and + * it is up to the implementation what this hint suggests, but it usually + * causes a best-effort attempt to run finalizers on all objects ready + * to be reclaimed. This calls + * <code>Runtime.getRuntime().runFinalization()</code>. + * + * @see Runtime#runFinalization() + */ + public static void runFinalization() + { + Runtime.getRuntime().runFinalization(); + } + + /** + * Tell the Runtime whether to run finalization before exiting the + * JVM. This is inherently unsafe in multi-threaded applications, + * since it can force initialization on objects which are still in use + * by live threads, leading to deadlock; therefore this is disabled by + * default. There may be a security check, <code>checkExit(0)</code>. This + * calls <code>Runtime.runFinalizersOnExit()</code>. + * + * @param finalizeOnExit whether to run finalizers on exit + * @throws SecurityException if permission is denied + * @see Runtime#runFinalizersOnExit() + * @since 1.1 + * @deprecated never rely on finalizers to do a clean, thread-safe, + * mop-up from your code + */ + public static void runFinalizersOnExit(boolean finalizeOnExit) + { + Runtime.runFinalizersOnExit(finalizeOnExit); + } + + /** + * Load a code file using its explicit system-dependent filename. A security + * check may be performed, <code>checkLink</code>. This just calls + * <code>Runtime.getRuntime().load(filename)</code>. + * + * <p> + * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * + * @param filename the code file to load + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the file cannot be loaded + * @see Runtime#load(String) + */ + public static void load(String filename) + { + Runtime.getRuntime().load(filename, VMStackWalker.getCallingClassLoader()); + } + + /** + * Load a library using its explicit system-dependent filename. A security + * check may be performed, <code>checkLink</code>. This just calls + * <code>Runtime.getRuntime().load(filename)</code>. + * + * <p> + * The library is loaded using the class loader associated with the + * class associated with the invoking method. + * + * @param libname the library file to load + * @throws SecurityException if permission is denied + * @throws UnsatisfiedLinkError if the file cannot be loaded + * @see Runtime#load(String) + */ + public static void loadLibrary(String libname) + { + Runtime.getRuntime().loadLibrary(libname, + VMStackWalker.getCallingClassLoader()); + } + + /** + * Convert a library name to its platform-specific variant. + * + * @param libname the library name, as used in <code>loadLibrary</code> + * @return the platform-specific mangling of the name + * @since 1.2 + */ + public static String mapLibraryName(String libname) + { + return VMRuntime.mapLibraryName(libname); + } + +} // class System diff --git a/libjava/classpath/java/lang/Thread.java b/libjava/classpath/java/lang/Thread.java new file mode 100644 index 0000000..37ca630 --- /dev/null +++ b/libjava/classpath/java/lang/Thread.java @@ -0,0 +1,999 @@ +/* Thread -- an independent thread of executable code + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.util.Map; +import java.util.WeakHashMap; + +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + * Status: Believed complete to version 1.4, with caveats. We do not + * implement the deprecated (and dangerous) stop, suspend, and resume + * methods. Security implementation is not complete. + */ + +/** + * Thread represents a single thread of execution in the VM. When an + * application VM starts up, it creates a non-daemon Thread which calls the + * main() method of a particular class. There may be other Threads running, + * such as the garbage collection thread. + * + * <p>Threads have names to identify them. These names are not necessarily + * unique. Every Thread has a priority, as well, which tells the VM which + * Threads should get more running time. New threads inherit the priority + * and daemon status of the parent thread, by default. + * + * <p>There are two methods of creating a Thread: you may subclass Thread and + * implement the <code>run()</code> method, at which point you may start the + * Thread by calling its <code>start()</code> method, or you may implement + * <code>Runnable</code> in the class you want to use and then call new + * <code>Thread(your_obj).start()</code>. + * + * <p>The virtual machine runs until all non-daemon threads have died (either + * by returning from the run() method as invoked by start(), or by throwing + * an uncaught exception); or until <code>System.exit</code> is called with + * adequate permissions. + * + * <p>It is unclear at what point a Thread should be added to a ThreadGroup, + * and at what point it should be removed. Should it be inserted when it + * starts, or when it is created? Should it be removed when it is suspended + * or interrupted? The only thing that is clear is that the Thread should be + * removed when it is stopped. + * + * @author Tom Tromey + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @see Runnable + * @see Runtime#exit(int) + * @see #run() + * @see #start() + * @see ThreadLocal + * @since 1.0 + * @status updated to 1.4 + */ +public class Thread implements Runnable +{ + /** The minimum priority for a Thread. */ + public static final int MIN_PRIORITY = 1; + + /** The priority a Thread gets by default. */ + public static final int NORM_PRIORITY = 5; + + /** The maximum priority for a Thread. */ + public static final int MAX_PRIORITY = 10; + + /** The underlying VM thread, only set when the thread is actually running. + */ + volatile VMThread vmThread; + + /** + * The group this thread belongs to. This is set to null by + * ThreadGroup.removeThread when the thread dies. + */ + volatile ThreadGroup group; + + /** The object to run(), null if this is the target. */ + final Runnable runnable; + + /** The thread name, non-null. */ + volatile String name; + + /** Whether the thread is a daemon. */ + volatile boolean daemon; + + /** The thread priority, 1 to 10. */ + volatile int priority; + + /** Native thread stack size. 0 = use default */ + private long stacksize; + + /** Was the thread stopped before it was started? */ + Throwable stillborn; + + /** The context classloader for this Thread. */ + private ClassLoader contextClassLoader; + + /** The next thread number to use. */ + private static int numAnonymousThreadsCreated; + + /** Thread local storage. Package accessible for use by + * InheritableThreadLocal. + */ + WeakHashMap locals; + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null,</code> + * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * <p> + * Threads created this way must have overridden their + * <code>run()</code> method to actually do anything. An example + * illustrating this method being used follows: + * <p><blockquote><pre> + * import java.lang.*; + * + * class plain01 implements Runnable { + * String name; + * plain01() { + * name = null; + * } + * plain01(String s) { + * name = s; + * } + * public void run() { + * if (name == null) + * System.out.println("A new thread created"); + * else + * System.out.println("A new thread with name " + name + + * " created"); + * } + * } + * class threadtest01 { + * public static void main(String args[] ) { + * int failed = 0 ; + * + * <b>Thread t1 = new Thread();</b> + * if (t1 != null) + * System.out.println("new Thread() succeed"); + * else { + * System.out.println("new Thread() failed"); + * failed++; + * } + * } + * } + * </pre></blockquote> + * + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread() + { + this(null, (Runnable) null); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * + * @param target the object whose <code>run</code> method is called. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread(Runnable target) + { + this(null, target); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null, name)</code>. + * + * @param name the name of the new thread. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread(String name) + { + this(null, null, name, 0); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) + */ + public Thread(ThreadGroup group, Runnable target) + { + this(group, target, "Thread-" + ++numAnonymousThreadsCreated, 0); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, null, name)</code> + * + * @param group the group to put the Thread into + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) + */ + public Thread(ThreadGroup group, String name) + { + this(group, null, name, 0); + } + + /** + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target, name)</code>. + * + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @see #Thread(ThreadGroup, Runnable, String) + */ + public Thread(Runnable target, String name) + { + this(null, target, name, 0); + } + + /** + * Allocate a new Thread object, with the specified ThreadGroup and name, and + * using the specified Runnable object's <code>run()</code> method to + * execute. If the Runnable object is null, <code>this</code> (which is + * a Runnable) is used instead. + * + * <p>If the ThreadGroup is null, the security manager is checked. If a + * manager exists and returns a non-null object for + * <code>getThreadGroup</code>, that group is used; otherwise the group + * of the creating thread is used. Note that the security manager calls + * <code>checkAccess</code> if the ThreadGroup is not null. + * + * <p>The new Thread will inherit its creator's priority and daemon status. + * These can be changed with <code>setPriority</code> and + * <code>setDaemon</code>. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see Runnable#run() + * @see #run() + * @see #setDaemon(boolean) + * @see #setPriority(int) + * @see SecurityManager#checkAccess(ThreadGroup) + * @see ThreadGroup#checkAccess() + */ + public Thread(ThreadGroup group, Runnable target, String name) + { + this(group, target, name, 0); + } + + /** + * Allocate a new Thread object, as if by + * <code>Thread(group, null, name)</code>, and give it the specified stack + * size, in bytes. The stack size is <b>highly platform independent</b>, + * and the virtual machine is free to round up or down, or ignore it + * completely. A higher value might let you go longer before a + * <code>StackOverflowError</code>, while a lower value might let you go + * longer before an <code>OutOfMemoryError</code>. Or, it may do absolutely + * nothing! So be careful, and expect to need to tune this value if your + * virtual machine even supports it. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @param name the name for the Thread + * @param size the stack size, in bytes; 0 to be ignored + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @since 1.4 + */ + public Thread(ThreadGroup group, Runnable target, String name, long size) + { + // Bypass System.getSecurityManager, for bootstrap efficiency. + SecurityManager sm = SecurityManager.current; + Thread current = currentThread(); + if (group == null) + { + if (sm != null) + group = sm.getThreadGroup(); + if (group == null) + group = current.group; + } + else if (sm != null) + sm.checkAccess(group); + + this.group = group; + // Use toString hack to detect null. + this.name = name.toString(); + this.runnable = target; + this.stacksize = size; + + priority = current.priority; + daemon = current.daemon; + contextClassLoader = current.contextClassLoader; + + group.addThread(this); + InheritableThreadLocal.newChildThread(this); + } + + /** + * Used by the VM to create thread objects for threads started outside + * of Java. Note: caller is responsible for adding the thread to + * a group and InheritableThreadLocal. + * + * @param vmThread the native thread + * @param name the thread name or null to use the default naming scheme + * @param priority current priority + * @param daemon is the thread a background thread? + */ + Thread(VMThread vmThread, String name, int priority, boolean daemon) + { + this.vmThread = vmThread; + this.runnable = null; + if (name == null) + name = "Thread-" + ++numAnonymousThreadsCreated; + this.name = name; + this.priority = priority; + this.daemon = daemon; + this.contextClassLoader = ClassLoader.getSystemClassLoader(); + } + + /** + * Get the number of active threads in the current Thread's ThreadGroup. + * This implementation calls + * <code>currentThread().getThreadGroup().activeCount()</code>. + * + * @return the number of active threads in the current ThreadGroup + * @see ThreadGroup#activeCount() + */ + public static int activeCount() + { + return currentThread().group.activeCount(); + } + + /** + * Check whether the current Thread is allowed to modify this Thread. This + * passes the check on to <code>SecurityManager.checkAccess(this)</code>. + * + * @throws SecurityException if the current Thread cannot modify this Thread + * @see SecurityManager#checkAccess(Thread) + */ + public final void checkAccess() + { + // Bypass System.getSecurityManager, for bootstrap efficiency. + SecurityManager sm = SecurityManager.current; + if (sm != null) + sm.checkAccess(this); + } + + /** + * Count the number of stack frames in this Thread. The Thread in question + * must be suspended when this occurs. + * + * @return the number of stack frames in this Thread + * @throws IllegalThreadStateException if this Thread is not suspended + * @deprecated pointless, since suspend is deprecated + */ + public int countStackFrames() + { + VMThread t = vmThread; + if (t == null || group == null) + throw new IllegalThreadStateException(); + + return t.countStackFrames(); + } + + /** + * Get the currently executing Thread. In the situation that the + * currently running thread was created by native code and doesn't + * have an associated Thread object yet, a new Thread object is + * constructed and associated with the native thread. + * + * @return the currently executing Thread + */ + public static Thread currentThread() + { + return VMThread.currentThread(); + } + + /** + * Originally intended to destroy this thread, this method was never + * implemented by Sun, and is hence a no-op. + */ + public void destroy() + { + throw new NoSuchMethodError(); + } + + /** + * Print a stack trace of the current thread to stderr using the same + * format as Throwable's printStackTrace() method. + * + * @see Throwable#printStackTrace() + */ + public static void dumpStack() + { + new Throwable().printStackTrace(); + } + + /** + * Copy every active thread in the current Thread's ThreadGroup into the + * array. Extra threads are silently ignored. This implementation calls + * <code>getThreadGroup().enumerate(array)</code>, which may have a + * security check, <code>checkAccess(group)</code>. + * + * @param array the array to place the Threads into + * @return the number of Threads placed into the array + * @throws NullPointerException if array is null + * @throws SecurityException if you cannot access the ThreadGroup + * @see ThreadGroup#enumerate(Thread[]) + * @see #activeCount() + * @see SecurityManager#checkAccess(ThreadGroup) + */ + public static int enumerate(Thread[] array) + { + return currentThread().group.enumerate(array); + } + + /** + * Get this Thread's name. + * + * @return this Thread's name + */ + public final String getName() + { + VMThread t = vmThread; + return t == null ? name : t.getName(); + } + + /** + * Get this Thread's priority. + * + * @return the Thread's priority + */ + public final synchronized int getPriority() + { + VMThread t = vmThread; + return t == null ? priority : t.getPriority(); + } + + /** + * Get the ThreadGroup this Thread belongs to. If the thread has died, this + * returns null. + * + * @return this Thread's ThreadGroup + */ + public final ThreadGroup getThreadGroup() + { + return group; + } + + /** + * Checks whether the current thread holds the monitor on a given object. + * This allows you to do <code>assert Thread.holdsLock(obj)</code>. + * + * @param obj the object to test lock ownership on. + * @return true if the current thread is currently synchronized on obj + * @throws NullPointerException if obj is null + * @since 1.4 + */ + public static boolean holdsLock(Object obj) + { + return VMThread.holdsLock(obj); + } + + /** + * Interrupt this Thread. First, there is a security check, + * <code>checkAccess</code>. Then, depending on the current state of the + * thread, various actions take place: + * + * <p>If the thread is waiting because of {@link #wait()}, + * {@link #sleep(long)}, or {@link #join()}, its <i>interrupt status</i> + * will be cleared, and an InterruptedException will be thrown. Notice that + * this case is only possible if an external thread called interrupt(). + * + * <p>If the thread is blocked in an interruptible I/O operation, in + * {@link java.nio.channels.InterruptibleChannel}, the <i>interrupt + * status</i> will be set, and ClosedByInterruptException will be thrown. + * + * <p>If the thread is blocked on a {@link java.nio.channels.Selector}, the + * <i>interrupt status</i> will be set, and the selection will return, with + * a possible non-zero value, as though by the wakeup() method. + * + * <p>Otherwise, the interrupt status will be set. + * + * @throws SecurityException if you cannot modify this Thread + */ + public synchronized void interrupt() + { + checkAccess(); + VMThread t = vmThread; + if (t != null) + t.interrupt(); + } + + /** + * Determine whether the current Thread has been interrupted, and clear + * the <i>interrupted status</i> in the process. + * + * @return whether the current Thread has been interrupted + * @see #isInterrupted() + */ + public static boolean interrupted() + { + return VMThread.interrupted(); + } + + /** + * Determine whether the given Thread has been interrupted, but leave + * the <i>interrupted status</i> alone in the process. + * + * @return whether the Thread has been interrupted + * @see #interrupted() + */ + public boolean isInterrupted() + { + VMThread t = vmThread; + return t != null && t.isInterrupted(); + } + + /** + * Determine whether this Thread is alive. A thread which is alive has + * started and not yet died. + * + * @return whether this Thread is alive + */ + public final boolean isAlive() + { + return vmThread != null && group != null; + } + + /** + * Tell whether this is a daemon Thread or not. + * + * @return whether this is a daemon Thread or not + * @see #setDaemon(boolean) + */ + public final boolean isDaemon() + { + VMThread t = vmThread; + return t == null ? daemon : t.isDaemon(); + } + + /** + * Wait forever for the Thread in question to die. + * + * @throws InterruptedException if the Thread is interrupted; it's + * <i>interrupted status</i> will be cleared + */ + public final void join() throws InterruptedException + { + join(0, 0); + } + + /** + * Wait the specified amount of time for the Thread in question to die. + * + * @param ms the number of milliseconds to wait, or 0 for forever + * @throws InterruptedException if the Thread is interrupted; it's + * <i>interrupted status</i> will be cleared + */ + public final void join(long ms) throws InterruptedException + { + join(ms, 0); + } + + /** + * Wait the specified amount of time for the Thread in question to die. + * + * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do + * not offer that fine a grain of timing resolution. Besides, there is + * no guarantee that this thread can start up immediately when time expires, + * because some other thread may be active. So don't expect real-time + * performance. + * + * @param ms the number of milliseconds to wait, or 0 for forever + * @param ns the number of extra nanoseconds to sleep (0-999999) + * @throws InterruptedException if the Thread is interrupted; it's + * <i>interrupted status</i> will be cleared + * @throws IllegalArgumentException if ns is invalid + */ + public final void join(long ms, int ns) throws InterruptedException + { + if(ms < 0 || ns < 0 || ns > 999999) + throw new IllegalArgumentException(); + + VMThread t = vmThread; + if(t != null) + t.join(ms, ns); + } + + /** + * Resume this Thread. If the thread is not suspended, this method does + * nothing. To mirror suspend(), there may be a security check: + * <code>checkAccess</code>. + * + * @throws SecurityException if you cannot resume the Thread + * @see #checkAccess() + * @see #suspend() + * @deprecated pointless, since suspend is deprecated + */ + public final synchronized void resume() + { + checkAccess(); + VMThread t = vmThread; + if (t != null) + t.resume(); + } + + /** + * The method of Thread that will be run if there is no Runnable object + * associated with the Thread. Thread's implementation does nothing at all. + * + * @see #start() + * @see #Thread(ThreadGroup, Runnable, String) + */ + public void run() + { + if (runnable != null) + runnable.run(); + } + + /** + * Set the daemon status of this Thread. If this is a daemon Thread, then + * the VM may exit even if it is still running. This may only be called + * before the Thread starts running. There may be a security check, + * <code>checkAccess</code>. + * + * @param daemon whether this should be a daemon thread or not + * @throws SecurityException if you cannot modify this Thread + * @throws IllegalThreadStateException if the Thread is active + * @see #isDaemon() + * @see #checkAccess() + */ + public final synchronized void setDaemon(boolean daemon) + { + if (vmThread != null) + throw new IllegalThreadStateException(); + checkAccess(); + this.daemon = daemon; + } + + /** + * Returns the context classloader of this Thread. The context + * classloader can be used by code that want to load classes depending + * on the current thread. Normally classes are loaded depending on + * the classloader of the current class. There may be a security check + * for <code>RuntimePermission("getClassLoader")</code> if the caller's + * class loader is not null or an ancestor of this thread's context class + * loader. + * + * @return the context class loader + * @throws SecurityException when permission is denied + * @see setContextClassLoader(ClassLoader) + * @since 1.2 + */ + public synchronized ClassLoader getContextClassLoader() + { + // Bypass System.getSecurityManager, for bootstrap efficiency. + SecurityManager sm = SecurityManager.current; + if (sm != null) + // XXX Don't check this if the caller's class loader is an ancestor. + sm.checkPermission(new RuntimePermission("getClassLoader")); + return contextClassLoader; + } + + /** + * Sets the context classloader for this Thread. When not explicitly set, + * the context classloader for a thread is the same as the context + * classloader of the thread that created this thread. The first thread has + * as context classloader the system classloader. There may be a security + * check for <code>RuntimePermission("setContextClassLoader")</code>. + * + * @param classloader the new context class loader + * @throws SecurityException when permission is denied + * @see getContextClassLoader() + * @since 1.2 + */ + public synchronized void setContextClassLoader(ClassLoader classloader) + { + SecurityManager sm = SecurityManager.current; + if (sm != null) + sm.checkPermission(new RuntimePermission("setContextClassLoader")); + this.contextClassLoader = classloader; + } + + /** + * Set this Thread's name. There may be a security check, + * <code>checkAccess</code>. + * + * @param name the new name for this Thread + * @throws NullPointerException if name is null + * @throws SecurityException if you cannot modify this Thread + */ + public final synchronized void setName(String name) + { + checkAccess(); + // The Class Libraries book says ``threadName cannot be null''. I + // take this to mean NullPointerException. + if (name == null) + throw new NullPointerException(); + VMThread t = vmThread; + if (t != null) + t.setName(name); + else + this.name = name; + } + + /** + * Yield to another thread. The Thread will not lose any locks it holds + * during this time. There are no guarantees which thread will be + * next to run, and it could even be this one, but most VMs will choose + * the highest priority thread that has been waiting longest. + */ + public static void yield() + { + VMThread.yield(); + } + + /** + * Suspend the current Thread's execution for the specified amount of + * time. The Thread will not lose any locks it has during this time. There + * are no guarantees which thread will be next to run, but most VMs will + * choose the highest priority thread that has been waiting longest. + * + * @param ms the number of milliseconds to sleep. + * @throws InterruptedException if the Thread is (or was) interrupted; + * it's <i>interrupted status</i> will be cleared + * @throws IllegalArgumentException if ms is negative + * @see #interrupt() + */ + public static void sleep(long ms) throws InterruptedException + { + sleep(ms, 0); + } + + /** + * Suspend the current Thread's execution for the specified amount of + * time. The Thread will not lose any locks it has during this time. There + * are no guarantees which thread will be next to run, but most VMs will + * choose the highest priority thread that has been waiting longest. + * <p> + * Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs + * do not offer that fine a grain of timing resolution. When ms is + * zero and ns is non-zero the Thread will sleep for at least one + * milli second. There is no guarantee that this thread can start up + * immediately when time expires, because some other thread may be + * active. So don't expect real-time performance. + * + * @param ms the number of milliseconds to sleep + * @param ns the number of extra nanoseconds to sleep (0-999999) + * @throws InterruptedException if the Thread is (or was) interrupted; + * it's <i>interrupted status</i> will be cleared + * @throws IllegalArgumentException if ms or ns is negative + * or ns is larger than 999999. + * @see #interrupt() + */ + public static void sleep(long ms, int ns) throws InterruptedException + { + + // Check parameters + if (ms < 0 || ns < 0 || ns > 999999) + throw new IllegalArgumentException(); + + // Really sleep + VMThread.sleep(ms, ns); + } + + /** + * Start this Thread, calling the run() method of the Runnable this Thread + * was created with, or else the run() method of the Thread itself. This + * is the only way to start a new thread; calling run by yourself will just + * stay in the same thread. The virtual machine will remove the thread from + * its thread group when the run() method completes. + * + * @throws IllegalThreadStateException if the thread has already started + * @see #run() + */ + public synchronized void start() + { + if (vmThread != null || group == null) + throw new IllegalThreadStateException(); + + VMThread.create(this, stacksize); + } + + /** + * Cause this Thread to stop abnormally because of the throw of a ThreadDeath + * error. If you stop a Thread that has not yet started, it will stop + * immediately when it is actually started. + * + * <p>This is inherently unsafe, as it can interrupt synchronized blocks and + * leave data in bad states. Hence, there is a security check: + * <code>checkAccess(this)</code>, plus another one if the current thread + * is not this: <code>RuntimePermission("stopThread")</code>. If you must + * catch a ThreadDeath, be sure to rethrow it after you have cleaned up. + * ThreadDeath is the only exception which does not print a stack trace when + * the thread dies. + * + * @throws SecurityException if you cannot stop the Thread + * @see #interrupt() + * @see #checkAccess() + * @see #start() + * @see ThreadDeath + * @see ThreadGroup#uncaughtException(Thread, Throwable) + * @see SecurityManager#checkAccess(Thread) + * @see SecurityManager#checkPermission(Permission) + * @deprecated unsafe operation, try not to use + */ + public final void stop() + { + stop(new ThreadDeath()); + } + + /** + * Cause this Thread to stop abnormally and throw the specified exception. + * If you stop a Thread that has not yet started, the stop is ignored + * (contrary to what the JDK documentation says). + * <b>WARNING</b>This bypasses Java security, and can throw a checked + * exception which the call stack is unprepared to handle. Do not abuse + * this power. + * + * <p>This is inherently unsafe, as it can interrupt synchronized blocks and + * leave data in bad states. Hence, there is a security check: + * <code>checkAccess(this)</code>, plus another one if the current thread + * is not this: <code>RuntimePermission("stopThread")</code>. If you must + * catch a ThreadDeath, be sure to rethrow it after you have cleaned up. + * ThreadDeath is the only exception which does not print a stack trace when + * the thread dies. + * + * @param t the Throwable to throw when the Thread dies + * @throws SecurityException if you cannot stop the Thread + * @throws NullPointerException in the calling thread, if t is null + * @see #interrupt() + * @see #checkAccess() + * @see #start() + * @see ThreadDeath + * @see ThreadGroup#uncaughtException(Thread, Throwable) + * @see SecurityManager#checkAccess(Thread) + * @see SecurityManager#checkPermission(Permission) + * @deprecated unsafe operation, try not to use + */ + public final synchronized void stop(Throwable t) + { + if (t == null) + throw new NullPointerException(); + // Bypass System.getSecurityManager, for bootstrap efficiency. + SecurityManager sm = SecurityManager.current; + if (sm != null) + { + sm.checkAccess(this); + if (this != currentThread()) + sm.checkPermission(new RuntimePermission("stopThread")); + } + VMThread vt = vmThread; + if (vt != null) + vt.stop(t); + else + stillborn = t; + } + + /** + * Suspend this Thread. It will not come back, ever, unless it is resumed. + * + * <p>This is inherently unsafe, as the suspended thread still holds locks, + * and can potentially deadlock your program. Hence, there is a security + * check: <code>checkAccess</code>. + * + * @throws SecurityException if you cannot suspend the Thread + * @see #checkAccess() + * @see #resume() + * @deprecated unsafe operation, try not to use + */ + public final synchronized void suspend() + { + checkAccess(); + VMThread t = vmThread; + if (t != null) + t.suspend(); + } + + /** + * Set this Thread's priority. There may be a security check, + * <code>checkAccess</code>, then the priority is set to the smaller of + * priority and the ThreadGroup maximum priority. + * + * @param priority the new priority for this Thread + * @throws IllegalArgumentException if priority exceeds MIN_PRIORITY or + * MAX_PRIORITY + * @throws SecurityException if you cannot modify this Thread + * @see #getPriority() + * @see #checkAccess() + * @see ThreadGroup#getMaxPriority() + * @see #MIN_PRIORITY + * @see #MAX_PRIORITY + */ + public final synchronized void setPriority(int priority) + { + checkAccess(); + if (priority < MIN_PRIORITY || priority > MAX_PRIORITY) + throw new IllegalArgumentException("Invalid thread priority value " + + priority + "."); + priority = Math.min(priority, group.getMaxPriority()); + VMThread t = vmThread; + if (t != null) + t.setPriority(priority); + else + this.priority = priority; + } + + /** + * Returns a string representation of this thread, including the + * thread's name, priority, and thread group. + * + * @return a human-readable String representing this Thread + */ + public String toString() + { + return ("Thread[" + name + "," + priority + "," + + (group == null ? "" : group.getName()) + "]"); + } + + /** + * Clean up code, called by VMThread when thread dies. + */ + synchronized void die() + { + group.removeThread(this); + vmThread = null; + locals = null; + } + + /** + * Returns the map used by ThreadLocal to store the thread local values. + */ + static Map getThreadLocals() + { + Thread thread = currentThread(); + Map locals = thread.locals; + if (locals == null) + { + locals = thread.locals = new WeakHashMap(); + } + return locals; + } +} diff --git a/libjava/classpath/java/lang/ThreadDeath.java b/libjava/classpath/java/lang/ThreadDeath.java new file mode 100644 index 0000000..c7d88fb --- /dev/null +++ b/libjava/classpath/java/lang/ThreadDeath.java @@ -0,0 +1,68 @@ +/* ThreadDeath.java - special exception registering Thread death + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * ThreadDeath is thrown in a thread when someone calls <code>stop()</code> + * on that thread. <b>Important:</b> Make sure you rethrow this exception + * if you catch it. If you don't, the thread will not die. + * + * <p>This is an Error rather than an exception, so that normal code will + * not catch it. It is intended for asynchronous cleanup when using the + * deprecated Thread.stop() method. + * + * @author John Keiser + * @author Tom Tromey (tromey@cygnus.com) + * @see Thread#stop() + * @status updated to 1.4 + */ +public class ThreadDeath extends Error +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -4417128565033088268L; + + /** + * Create an error without a message. + */ + public ThreadDeath() + { + } +} diff --git a/libjava/classpath/java/lang/ThreadGroup.java b/libjava/classpath/java/lang/ThreadGroup.java new file mode 100644 index 0000000..6e4c27a --- /dev/null +++ b/libjava/classpath/java/lang/ThreadGroup.java @@ -0,0 +1,749 @@ +/* ThreadGroup -- a group of Threads + Copyright (C) 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.util.Vector; + +/** + * ThreadGroup allows you to group Threads together. There is a hierarchy + * of ThreadGroups, and only the initial ThreadGroup has no parent. A Thread + * may access information about its own ThreadGroup, but not its parents or + * others outside the tree. + * + * @author John Keiser + * @author Tom Tromey + * @author Bryce McKinlay + * @author Eric Blake (ebb9@email.byu.edu) + * @see Thread + * @since 1.0 + * @status updated to 1.4 + */ +public class ThreadGroup +{ + /** The Initial, top-level ThreadGroup. */ + static ThreadGroup root = new ThreadGroup(); + + /** + * This flag is set if an uncaught exception occurs. The runtime should + * check this and exit with an error status if it is set. + */ + static boolean had_uncaught_exception; + + /** The parent thread group. */ + private final ThreadGroup parent; + + /** The group name, non-null. */ + final String name; + + /** The threads in the group. */ + private final Vector threads = new Vector(); + + /** Child thread groups, or null when this group is destroyed. */ + private Vector groups = new Vector(); + + /** If all threads in the group are daemons. */ + private boolean daemon_flag = false; + + /** The maximum group priority. */ + private int maxpri; + + /** + * Hidden constructor to build the root node. + */ + private ThreadGroup() + { + name = "main"; + parent = null; + maxpri = Thread.MAX_PRIORITY; + } + + /** + * Create a new ThreadGroup using the given name and the current thread's + * ThreadGroup as a parent. There may be a security check, + * <code>checkAccess</code>. + * + * @param name the name to use for the ThreadGroup + * @throws SecurityException if the current thread cannot create a group + * @see #checkAccess() + */ + public ThreadGroup(String name) + { + this(Thread.currentThread().group, name); + } + + /** + * Create a new ThreadGroup using the given name and parent group. The new + * group inherits the maximum priority and daemon status of its parent + * group. There may be a security check, <code>checkAccess</code>. + * + * @param name the name to use for the ThreadGroup + * @param parent the ThreadGroup to use as a parent + * @throws NullPointerException if parent is null + * @throws SecurityException if the current thread cannot create a group + * @throws IllegalThreadStateException if the parent is destroyed + * @see #checkAccess() + */ + public ThreadGroup(ThreadGroup parent, String name) + { + parent.checkAccess(); + this.parent = parent; + this.name = name; + maxpri = parent.maxpri; + daemon_flag = parent.daemon_flag; + synchronized (parent) + { + if (parent.groups == null) + throw new IllegalThreadStateException(); + parent.groups.add(this); + } + } + + /** + * Get the name of this ThreadGroup. + * + * @return the name of this ThreadGroup + */ + public final String getName() + { + return name; + } + + /** + * Get the parent of this ThreadGroup. If the parent is not null, there + * may be a security check, <code>checkAccess</code>. + * + * @return the parent of this ThreadGroup + * @throws SecurityException if permission is denied + */ + public final ThreadGroup getParent() + { + if (parent != null) + parent.checkAccess(); + return parent; + } + + /** + * Get the maximum priority of Threads in this ThreadGroup. Threads created + * after this call in this group may not exceed this priority. + * + * @return the maximum priority of Threads in this ThreadGroup + */ + public final int getMaxPriority() + { + return maxpri; + } + + /** + * Tell whether this ThreadGroup is a daemon group. A daemon group will + * be automatically destroyed when its last thread is stopped and + * its last thread group is destroyed. + * + * @return whether this ThreadGroup is a daemon group + */ + public final boolean isDaemon() + { + return daemon_flag; + } + + /** + * Tell whether this ThreadGroup has been destroyed or not. + * + * @return whether this ThreadGroup has been destroyed or not + * @since 1.1 + */ + public synchronized boolean isDestroyed() + { + return groups == null; + } + + /** + * Set whether this ThreadGroup is a daemon group. A daemon group will be + * destroyed when its last thread is stopped and its last thread group is + * destroyed. There may be a security check, <code>checkAccess</code>. + * + * @param daemon whether this ThreadGroup should be a daemon group + * @throws SecurityException if you cannot modify this ThreadGroup + * @see #checkAccess() + */ + public final void setDaemon(boolean daemon) + { + checkAccess(); + daemon_flag = daemon; + } + + /** + * Set the maximum priority for Threads in this ThreadGroup. setMaxPriority + * can only be used to reduce the current maximum. If maxpri is greater + * than the current Maximum of the parent group, the current value is not + * changed. Otherwise, all groups which belong to this have their priority + * adjusted as well. Calling this does not affect threads already in this + * ThreadGroup. There may be a security check, <code>checkAccess</code>. + * + * @param maxpri the new maximum priority for this ThreadGroup + * @throws SecurityException if you cannot modify this ThreadGroup + * @see #getMaxPriority() + * @see #checkAccess() + */ + public final synchronized void setMaxPriority(int maxpri) + { + checkAccess(); + if (maxpri < Thread.MIN_PRIORITY || maxpri > Thread.MAX_PRIORITY) + return; + if (parent != null && maxpri > parent.maxpri) + maxpri = parent.maxpri; + this.maxpri = maxpri; + if (groups == null) + return; + int i = groups.size(); + while (--i >= 0) + ((ThreadGroup) groups.get(i)).setMaxPriority(maxpri); + } + + /** + * Check whether this ThreadGroup is an ancestor of the specified + * ThreadGroup, or if they are the same. + * + * @param group the group to test on + * @return whether this ThreadGroup is a parent of the specified group + */ + public final boolean parentOf(ThreadGroup group) + { + while (group != null) + { + if (group == this) + return true; + group = group.parent; + } + return false; + } + + /** + * Find out if the current Thread can modify this ThreadGroup. This passes + * the check on to <code>SecurityManager.checkAccess(this)</code>. + * + * @throws SecurityException if the current Thread cannot modify this + * ThreadGroup + * @see SecurityManager#checkAccess(ThreadGroup) + */ + public final void checkAccess() + { + // Bypass System.getSecurityManager, for bootstrap efficiency. + SecurityManager sm = SecurityManager.current; + if (sm != null) + sm.checkAccess(this); + } + + /** + * Return an estimate of the total number of active threads in this + * ThreadGroup and all its descendants. This cannot return an exact number, + * since the status of threads may change after they were counted; but it + * should be pretty close. Based on a JDC bug, + * <a href="http://developer.java.sun.com/developer/bugParade/bugs/4089701.html"> + * 4089701</a>, we take active to mean isAlive(). + * + * @return count of active threads in this ThreadGroup and its descendants + */ + public int activeCount() + { + int total = 0; + if (groups == null) + return total; + int i = threads.size(); + while (--i >= 0) + if (((Thread) threads.get(i)).isAlive()) + total++; + i = groups.size(); + while (--i >= 0) + total += ((ThreadGroup) groups.get(i)).activeCount(); + return total; + } + + /** + * Copy all of the active Threads from this ThreadGroup and its descendants + * into the specified array. If the array is not big enough to hold all + * the Threads, extra Threads will simply not be copied. There may be a + * security check, <code>checkAccess</code>. + * + * @param array the array to put the threads into + * @return the number of threads put into the array + * @throws SecurityException if permission was denied + * @throws NullPointerException if array is null + * @throws ArrayStoreException if a thread does not fit in the array + * @see #activeCount() + * @see #checkAccess() + * @see #enumerate(Thread[], boolean) + */ + public int enumerate(Thread[] array) + { + return enumerate(array, 0, true); + } + + /** + * Copy all of the active Threads from this ThreadGroup and, if desired, + * from its descendants, into the specified array. If the array is not big + * enough to hold all the Threads, extra Threads will simply not be copied. + * There may be a security check, <code>checkAccess</code>. + * + * @param array the array to put the threads into + * @param recurse whether to recurse into descendent ThreadGroups + * @return the number of threads put into the array + * @throws SecurityException if permission was denied + * @throws NullPointerException if array is null + * @throws ArrayStoreException if a thread does not fit in the array + * @see #activeCount() + * @see #checkAccess() + */ + public int enumerate(Thread[] array, boolean recurse) + { + return enumerate(array, 0, recurse); + } + + /** + * Get the number of active groups in this ThreadGroup. This group itself + * is not included in the count. A sub-group is active if it has not been + * destroyed. This cannot return an exact number, since the status of + * threads may change after they were counted; but it should be pretty close. + * + * @return the number of active groups in this ThreadGroup + */ + public int activeGroupCount() + { + if (groups == null) + return 0; + int total = groups.size(); + int i = total; + while (--i >= 0) + total += ((ThreadGroup) groups.get(i)).activeGroupCount(); + return total; + } + + /** + * Copy all active ThreadGroups that are descendants of this ThreadGroup + * into the specified array. If the array is not large enough to hold all + * active ThreadGroups, extra ThreadGroups simply will not be copied. There + * may be a security check, <code>checkAccess</code>. + * + * @param array the array to put the ThreadGroups into + * @return the number of ThreadGroups copied into the array + * @throws SecurityException if permission was denied + * @throws NullPointerException if array is null + * @throws ArrayStoreException if a group does not fit in the array + * @see #activeCount() + * @see #checkAccess() + * @see #enumerate(ThreadGroup[], boolean) + */ + public int enumerate(ThreadGroup[] array) + { + return enumerate(array, 0, true); + } + + /** + * Copy all active ThreadGroups that are children of this ThreadGroup into + * the specified array, and if desired, also all descendents. If the array + * is not large enough to hold all active ThreadGroups, extra ThreadGroups + * simply will not be copied. There may be a security check, + * <code>checkAccess</code>. + * + * @param array the array to put the ThreadGroups into + * @param recurse whether to recurse into descendent ThreadGroups + * @return the number of ThreadGroups copied into the array + * @throws SecurityException if permission was denied + * @throws NullPointerException if array is null + * @throws ArrayStoreException if a group does not fit in the array + * @see #activeCount() + * @see #checkAccess() + */ + public int enumerate(ThreadGroup[] array, boolean recurse) + { + return enumerate(array, 0, recurse); + } + + /** + * Stop all Threads in this ThreadGroup and its descendants. + * + * <p>This is inherently unsafe, as it can interrupt synchronized blocks and + * leave data in bad states. Hence, there is a security check: + * <code>checkAccess()</code>, followed by further checks on each thread + * being stopped. + * + * @throws SecurityException if permission is denied + * @see #checkAccess() + * @see Thread#stop(Throwable) + * @deprecated unsafe operation, try not to use + */ + public final synchronized void stop() + { + checkAccess(); + if (groups == null) + return; + int i = threads.size(); + while (--i >= 0) + ((Thread) threads.get(i)).stop(); + i = groups.size(); + while (--i >= 0) + ((ThreadGroup) groups.get(i)).stop(); + } + + /** + * Interrupt all Threads in this ThreadGroup and its sub-groups. There may + * be a security check, <code>checkAccess</code>. + * + * @throws SecurityException if permission is denied + * @see #checkAccess() + * @see Thread#interrupt() + * @since 1.2 + */ + public final synchronized void interrupt() + { + checkAccess(); + if (groups == null) + return; + int i = threads.size(); + while (--i >= 0) + ((Thread) threads.get(i)).interrupt(); + i = groups.size(); + while (--i >= 0) + ((ThreadGroup) groups.get(i)).interrupt(); + } + + /** + * Suspend all Threads in this ThreadGroup and its descendants. + * + * <p>This is inherently unsafe, as suspended threads still hold locks, + * which can lead to deadlock. Hence, there is a security check: + * <code>checkAccess()</code>, followed by further checks on each thread + * being suspended. + * + * @throws SecurityException if permission is denied + * @see #checkAccess() + * @see Thread#suspend() + * @deprecated unsafe operation, try not to use + */ + public final synchronized void suspend() + { + checkAccess(); + if (groups == null) + return; + int i = threads.size(); + while (--i >= 0) + ((Thread) threads.get(i)).suspend(); + i = groups.size(); + while (--i >= 0) + ((ThreadGroup) groups.get(i)).suspend(); + } + + /** + * Resume all suspended Threads in this ThreadGroup and its descendants. + * To mirror suspend(), there is a security check: + * <code>checkAccess()</code>, followed by further checks on each thread + * being resumed. + * + * @throws SecurityException if permission is denied + * @see #checkAccess() + * @see Thread#suspend() + * @deprecated pointless, since suspend is deprecated + */ + public final synchronized void resume() + { + checkAccess(); + if (groups == null) + return; + int i = threads.size(); + while (--i >= 0) + ((Thread) threads.get(i)).resume(); + i = groups.size(); + while (--i >= 0) + ((ThreadGroup) groups.get(i)).resume(); + } + + /** + * Destroy this ThreadGroup. The group must be empty, meaning that all + * threads and sub-groups have completed execution. Daemon groups are + * destroyed automatically. There may be a security check, + * <code>checkAccess</code>. + * + * @throws IllegalThreadStateException if the ThreadGroup is not empty, or + * was previously destroyed + * @throws SecurityException if permission is denied + * @see #checkAccess() + */ + public final synchronized void destroy() + { + checkAccess(); + if (! threads.isEmpty() || groups == null) + throw new IllegalThreadStateException(); + int i = groups.size(); + while (--i >= 0) + ((ThreadGroup) groups.get(i)).destroy(); + groups = null; + if (parent != null) + parent.removeGroup(this); + } + + /** + * Print out information about this ThreadGroup to System.out. This is + * meant for debugging purposes. <b>WARNING:</b> This method is not secure, + * and can print the name of threads to standard out even when you cannot + * otherwise get at such threads. + */ + public void list() + { + list(""); + } + + /** + * When a Thread in this ThreadGroup does not catch an exception, the + * virtual machine calls this method. The default implementation simply + * passes the call to the parent; then in top ThreadGroup, it will + * ignore ThreadDeath and print the stack trace of any other throwable. + * Override this method if you want to handle the exception in a different + * manner. + * + * @param thread the thread that exited + * @param t the uncaught throwable + * @throws NullPointerException if t is null + * @see ThreadDeath + * @see System#err + * @see Throwable#printStackTrace() + */ + public void uncaughtException(Thread thread, Throwable t) + { + if (parent != null) + parent.uncaughtException(thread, t); + else if (! (t instanceof ThreadDeath)) + { + if (t == null) + throw new NullPointerException(); + had_uncaught_exception = true; + try + { + if (thread != null) + System.err.print("Exception in thread \"" + thread.name + "\" "); + t.printStackTrace(System.err); + } + catch (Throwable x) + { + // This means that something is badly screwed up with the runtime, + // or perhaps someone overloaded the Throwable.printStackTrace to + // die. In any case, try to deal with it gracefully. + try + { + System.err.println(t); + System.err.println("*** Got " + x + + " while trying to print stack trace."); + } + catch (Throwable x2) + { + // Here, someone may have overloaded t.toString() or + // x.toString() to die. Give up all hope; we can't even chain + // the exception, because the chain would likewise die. + System.err.println("*** Catastrophic failure while handling " + + "uncaught exception."); + throw new InternalError(); + } + } + } + } + + /** + * Originally intended to tell the VM whether it may suspend Threads in + * low memory situations, this method was never implemented by Sun, and + * is hence a no-op. + * + * @param allow whether to allow low-memory thread suspension; ignored + * @return false + * @since 1.1 + * @deprecated pointless, since suspend is deprecated + */ + public boolean allowThreadSuspension(boolean allow) + { + return false; + } + + /** + * Return a human-readable String representing this ThreadGroup. The format + * of the string is:<br> + * <code>getClass().getName() + "[name=" + getName() + ",maxpri=" + * + getMaxPriority() + ']'</code>. + * + * @return a human-readable String representing this ThreadGroup + */ + public String toString() + { + return getClass().getName() + "[name=" + name + ",maxpri=" + maxpri + ']'; + } + + /** + * Implements enumerate. + * + * @param list the array to put the threads into + * @param next the next open slot in the array + * @param recurse whether to recurse into descendent ThreadGroups + * @return the number of threads put into the array + * @throws SecurityException if permission was denied + * @throws NullPointerException if list is null + * @throws ArrayStoreException if a thread does not fit in the array + * @see #enumerate(Thread[]) + * @see #enumerate(Thread[], boolean) + */ + private int enumerate(Thread[] list, int next, boolean recurse) + { + checkAccess(); + if (groups == null) + return next; + int i = threads.size(); + while (--i >= 0 && next < list.length) + { + Thread t = (Thread) threads.get(i); + if (t.isAlive()) + list[next++] = t; + } + if (recurse) + { + i = groups.size(); + while (--i >= 0 && next < list.length) + { + ThreadGroup g = (ThreadGroup) groups.get(i); + next = g.enumerate(list, next, true); + } + } + return next; + } + + /** + * Implements enumerate. + * + * @param list the array to put the groups into + * @param next the next open slot in the array + * @param recurse whether to recurse into descendent ThreadGroups + * @return the number of groups put into the array + * @throws SecurityException if permission was denied + * @throws NullPointerException if list is null + * @throws ArrayStoreException if a group does not fit in the array + * @see #enumerate(ThreadGroup[]) + * @see #enumerate(ThreadGroup[], boolean) + */ + private int enumerate(ThreadGroup[] list, int next, boolean recurse) + { + checkAccess(); + if (groups == null) + return next; + int i = groups.size(); + while (--i >= 0 && next < list.length) + { + ThreadGroup g = (ThreadGroup) groups.get(i); + list[next++] = g; + if (recurse && next != list.length) + next = g.enumerate(list, next, true); + } + return next; + } + + /** + * Implements list. + * + * @param indentation the current level of indentation + * @see #list() + */ + private void list(String indentation) + { + if (groups == null) + return; + System.out.println(indentation + this); + indentation += " "; + int i = threads.size(); + while (--i >= 0) + System.out.println(indentation + threads.get(i)); + i = groups.size(); + while (--i >= 0) + ((ThreadGroup) groups.get(i)).list(indentation); + } + + /** + * Add a thread to the group. Called by Thread constructors. + * + * @param t the thread to add, non-null + * @throws IllegalThreadStateException if the group is destroyed + */ + final synchronized void addThread(Thread t) + { + if (groups == null) + throw new IllegalThreadStateException("ThreadGroup is destroyed"); + threads.add(t); + } + + /** + * Called by the VM to remove a thread that has died. + * + * @param t the thread to remove, non-null + * @XXX A ThreadListener to call this might be nice. + */ + final synchronized void removeThread(Thread t) + { + if (groups == null) + return; + threads.remove(t); + t.group = null; + // Daemon groups are automatically destroyed when all their threads die. + if (daemon_flag && groups.size() == 0 && threads.size() == 0) + { + // We inline destroy to avoid the access check. + groups = null; + if (parent != null) + parent.removeGroup(this); + } + } + + /** + * Called when a group is destroyed, to remove it from its parent. + * + * @param g the destroyed group, non-null + */ + final synchronized void removeGroup(ThreadGroup g) + { + groups.remove(g); + // Daemon groups are automatically destroyed when all their threads die. + if (daemon_flag && groups.size() == 0 && threads.size() == 0) + { + // We inline destroy to avoid the access check. + groups = null; + if (parent != null) + parent.removeGroup(this); + } + } +} // class ThreadGroup diff --git a/libjava/classpath/java/lang/ThreadLocal.java b/libjava/classpath/java/lang/ThreadLocal.java new file mode 100644 index 0000000..0b2b608 --- /dev/null +++ b/libjava/classpath/java/lang/ThreadLocal.java @@ -0,0 +1,171 @@ +/* ThreadLocal -- a variable with a unique value per thread + Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import java.util.Map; +import java.util.WeakHashMap; + + +/** + * ThreadLocal objects have a different state associated with every + * Thread that accesses them. Every access to the ThreadLocal object + * (through the <code>get()</code> and <code>set()</code> methods) + * only affects the state of the object as seen by the currently + * executing Thread. + * + * <p>The first time a ThreadLocal object is accessed on a particular + * Thread, the state for that Thread's copy of the local variable is set by + * executing the method <code>initialValue()</code>. + * </p> + * + * <p>An example how you can use this: + * </p> + * + * <pre> + * class Connection + * { + * private static ThreadLocal owner = new ThreadLocal() + * { + * public Object initialValue() + * { + * return("nobody"); + * } + * }; + * ... + * } + * </pre> + * + * <p>Now all instances of connection can see who the owner of the currently + * executing Thread is by calling <code>owner.get()</code>. By default any + * Thread would be associated with 'nobody'. But the Connection object could + * offer a method that changes the owner associated with the Thread on + * which the method was called by calling <code>owner.put("somebody")</code>. + * (Such an owner changing method should then be guarded by security checks.) + * </p> + * + * <p>When a Thread is garbage collected all references to values of + * the ThreadLocal objects associated with that Thread are removed. + * </p> + * + * @author Mark Wielaard (mark@klomp.org) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public class ThreadLocal +{ + /** + * Placeholder to distinguish between uninitialized and null set by the + * user. Do not expose this to the public. Package visible for use by + * InheritableThreadLocal + */ + static final Object NULL = new Object(); + + /** + * Serves as a key for the Thread.locals WeakHashMap. + * We can't use "this", because a subclass may override equals/hashCode + * and we need to use object identity for the map. + */ + final Key key = new Key(); + + class Key + { + ThreadLocal get() + { + return ThreadLocal.this; + } + } + + /** + * Creates a ThreadLocal object without associating any value to it yet. + */ + public ThreadLocal() + { + } + + /** + * Called once per thread on the first invocation of get(), if set() was + * not already called. The default implementation returns <code>null</code>. + * Often, this method is overridden to create the appropriate initial object + * for the current thread's view of the ThreadLocal. + * + * @return the initial value of the variable in this thread + */ + protected Object initialValue() + { + return null; + } + + /** + * Gets the value associated with the ThreadLocal object for the currently + * executing Thread. If this is the first time the current thread has called + * get(), and it has not already called set(), the value is obtained by + * <code>initialValue()</code>. + * + * @return the value of the variable in this thread + */ + public Object get() + { + Map map = Thread.getThreadLocals(); + // Note that we don't have to synchronize, as only this thread will + // ever modify the map. + Object value = map.get(key); + if (value == null) + { + value = initialValue(); + map.put(key, value == null ? NULL : value); + } + return value == NULL ? null : value; + } + + /** + * Sets the value associated with the ThreadLocal object for the currently + * executing Thread. This overrides any existing value associated with the + * current Thread and prevents <code>initialValue()</code> from being + * called if this is the first access to this ThreadLocal in this Thread. + * + * @param value the value to set this thread's view of the variable to + */ + public void set(Object value) + { + Map map = Thread.getThreadLocals(); + // Note that we don't have to synchronize, as only this thread will + // ever modify the map. + map.put(key, value == null ? NULL : value); + } +} diff --git a/libjava/classpath/java/lang/Throwable.java b/libjava/classpath/java/lang/Throwable.java new file mode 100644 index 0000000..c47a14b --- /dev/null +++ b/libjava/classpath/java/lang/Throwable.java @@ -0,0 +1,563 @@ +/* java.lang.Throwable -- Root class for all Exceptions and Errors + Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + +import gnu.classpath.SystemProperties; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Serializable; + +/** + * Throwable is the superclass of all exceptions that can be raised. + * + * <p>There are two special cases: {@link Error} and {@link RuntimeException}: + * these two classes (and their subclasses) are considered unchecked + * exceptions, and are either frequent enough or catastrophic enough that you + * do not need to declare them in <code>throws</code> clauses. Everything + * else is a checked exception, and is ususally a subclass of + * {@link Exception}; these exceptions have to be handled or declared. + * + * <p>Instances of this class are usually created with knowledge of the + * execution context, so that you can get a stack trace of the problem spot + * in the code. Also, since JDK 1.4, Throwables participate in "exception + * chaining." This means that one exception can be caused by another, and + * preserve the information of the original. + * + * <p>One reason this is useful is to wrap exceptions to conform to an + * interface. For example, it would be bad design to require all levels + * of a program interface to be aware of the low-level exceptions thrown + * at one level of abstraction. Another example is wrapping a checked + * exception in an unchecked one, to communicate that failure occured + * while still obeying the method throws clause of a superclass. + * + * <p>A cause is assigned in one of two ways; but can only be assigned once + * in the lifetime of the Throwable. There are new constructors added to + * several classes in the exception hierarchy that directly initialize the + * cause, or you can use the <code>initCause</code> method. This second + * method is especially useful if the superclass has not been retrofitted + * with new constructors:<br> + * <pre> + * try + * { + * lowLevelOp(); + * } + * catch (LowLevelException lle) + * { + * throw (HighLevelException) new HighLevelException().initCause(lle); + * } + * </pre> + * Notice the cast in the above example; without it, your method would need + * a throws clase that declared Throwable, defeating the purpose of chainig + * your exceptions. + * + * <p>By convention, exception classes have two constructors: one with no + * arguments, and one that takes a String for a detail message. Further, + * classes which are likely to be used in an exception chain also provide + * a constructor that takes a Throwable, with or without a detail message + * string. + * + * <p>Another 1.4 feature is the StackTrace, a means of reflection that + * allows the program to inspect the context of the exception, and which is + * serialized, so that remote procedure calls can correctly pass exceptions. + * + * @author Brian Jones + * @author John Keiser + * @author Mark Wielaard + * @author Tom Tromey + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.0 + * @status updated to 1.4 + */ +public class Throwable implements Serializable +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -3042686055658047285L; + + /** + * The detail message. + * + * @serial specific details about the exception, may be null + */ + private final String detailMessage; + + /** + * The cause of the throwable, including null for an unknown or non-chained + * cause. This may only be set once; so the field is set to + * <code>this</code> until initialized. + * + * @serial the cause, or null if unknown, or this if not yet set + * @since 1.4 + */ + private Throwable cause = this; + + /** + * The stack trace, in a serialized form. + * + * @serial the elements of the stack trace; this is non-null, and has + * no null entries + * @since 1.4 + */ + private StackTraceElement[] stackTrace; + + /** + * Instantiate this Throwable with an empty message. The cause remains + * uninitialized. {@link #fillInStackTrace()} will be called to set + * up the stack trace. + */ + public Throwable() + { + this((String) null); + } + + /** + * Instantiate this Throwable with the given message. The cause remains + * uninitialized. {@link #fillInStackTrace()} will be called to set + * up the stack trace. + * + * @param message the message to associate with the Throwable + */ + public Throwable(String message) + { + fillInStackTrace(); + detailMessage = message; + } + + /** + * Instantiate this Throwable with the given message and cause. Note that + * the message is unrelated to the message of the cause. + * {@link #fillInStackTrace()} will be called to set up the stack trace. + * + * @param message the message to associate with the Throwable + * @param cause the cause, may be null + * @since 1.4 + */ + public Throwable(String message, Throwable cause) + { + this(message); + this.cause = cause; + } + + /** + * Instantiate this Throwable with the given cause. The message is then + * built as <code>cause == null ? null : cause.toString()</code>. + * {@link #fillInStackTrace()} will be called to set up the stack trace. + * + * @param cause the cause, may be null + * @since 1.4 + */ + public Throwable(Throwable cause) + { + this(cause == null ? null : cause.toString(), cause); + } + + /** + * Get the message associated with this Throwable. + * + * @return the error message associated with this Throwable, may be null + */ + public String getMessage() + { + return detailMessage; + } + + /** + * Get a localized version of this Throwable's error message. + * This method must be overridden in a subclass of Throwable + * to actually produce locale-specific methods. The Throwable + * implementation just returns getMessage(). + * + * @return a localized version of this error message + * @see #getMessage() + * @since 1.1 + */ + public String getLocalizedMessage() + { + return getMessage(); + } + + /** + * Returns the cause of this exception, or null if the cause is not known + * or non-existant. This cause is initialized by the new constructors, + * or by calling initCause. + * + * @return the cause of this Throwable + * @since 1.4 + */ + public Throwable getCause() + { + return cause == this ? null : cause; + } + + /** + * Initialize the cause of this Throwable. This may only be called once + * during the object lifetime, including implicitly by chaining + * constructors. + * + * @param cause the cause of this Throwable, may be null + * @return this + * @throws IllegalArgumentException if cause is this (a Throwable can't be + * its own cause!) + * @throws IllegalStateException if the cause has already been set + * @since 1.4 + */ + public Throwable initCause(Throwable cause) + { + if (cause == this) + throw new IllegalArgumentException(); + if (this.cause != this) + throw new IllegalStateException(); + this.cause = cause; + return this; + } + + /** + * Get a human-readable representation of this Throwable. The detail message + * is retrieved by getLocalizedMessage(). Then, with a null detail + * message, this string is simply the object's class name; otherwise + * the string is <code>getClass().getName() + ": " + message</code>. + * + * @return a human-readable String represting this Throwable + */ + public String toString() + { + String msg = getLocalizedMessage(); + return getClass().getName() + (msg == null ? "" : ": " + msg); + } + + /** + * Print a stack trace to the standard error stream. This stream is the + * current contents of <code>System.err</code>. The first line of output + * is the result of {@link #toString()}, and the remaining lines represent + * the data created by {@link #fillInStackTrace()}. While the format is + * unspecified, this implementation uses the suggested format, demonstrated + * by this example:<br> + * <pre> + * public class Junk + * { + * public static void main(String args[]) + * { + * try + * { + * a(); + * } + * catch(HighLevelException e) + * { + * e.printStackTrace(); + * } + * } + * static void a() throws HighLevelException + * { + * try + * { + * b(); + * } + * catch(MidLevelException e) + * { + * throw new HighLevelException(e); + * } + * } + * static void b() throws MidLevelException + * { + * c(); + * } + * static void c() throws MidLevelException + * { + * try + * { + * d(); + * } + * catch(LowLevelException e) + * { + * throw new MidLevelException(e); + * } + * } + * static void d() throws LowLevelException + * { + * e(); + * } + * static void e() throws LowLevelException + * { + * throw new LowLevelException(); + * } + * } + * class HighLevelException extends Exception + * { + * HighLevelException(Throwable cause) { super(cause); } + * } + * class MidLevelException extends Exception + * { + * MidLevelException(Throwable cause) { super(cause); } + * } + * class LowLevelException extends Exception + * { + * } + * </pre> + * <p> + * <pre> + * HighLevelException: MidLevelException: LowLevelException + * at Junk.a(Junk.java:13) + * at Junk.main(Junk.java:4) + * Caused by: MidLevelException: LowLevelException + * at Junk.c(Junk.java:23) + * at Junk.b(Junk.java:17) + * at Junk.a(Junk.java:11) + * ... 1 more + * Caused by: LowLevelException + * at Junk.e(Junk.java:30) + * at Junk.d(Junk.java:27) + * at Junk.c(Junk.java:21) + * ... 3 more + * </pre> + */ + public void printStackTrace() + { + printStackTrace(System.err); + } + + /** + * Print a stack trace to the specified PrintStream. See + * {@link #printStackTrace()} for the sample format. + * + * @param s the PrintStream to write the trace to + */ + public void printStackTrace(PrintStream s) + { + s.print(stackTraceString()); + } + + /** + * Prints the exception, the detailed message and the stack trace + * associated with this Throwable to the given <code>PrintWriter</code>. + * The actual output written is implemention specific. Use the result of + * <code>getStackTrace()</code> when more precise information is needed. + * + * <p>This implementation first prints a line with the result of this + * object's <code>toString()</code> method. + * <br> + * Then for all elements given by <code>getStackTrace</code> it prints + * a line containing three spaces, the string "at " and the result of calling + * the <code>toString()</code> method on the <code>StackTraceElement</code> + * object. If <code>getStackTrace()</code> returns an empty array it prints + * a line containing three spaces and the string + * "<<No stacktrace available>>". + * <br> + * Then if <code>getCause()</code> doesn't return null it adds a line + * starting with "Caused by: " and the result of calling + * <code>toString()</code> on the cause. + * <br> + * Then for every cause (of a cause, etc) the stacktrace is printed the + * same as for the top level <code>Throwable</code> except that as soon + * as all the remaining stack frames of the cause are the same as the + * the last stack frames of the throwable that the cause is wrapped in + * then a line starting with three spaces and the string "... X more" is + * printed, where X is the number of remaining stackframes. + * + * @param pw the PrintWriter to write the trace to + * @since 1.1 + */ + public void printStackTrace (PrintWriter pw) + { + pw.print(stackTraceString()); + } + + /* + * We use inner class to avoid a static initializer in this basic class. + */ + private static class StaticData + { + static final String nl = SystemProperties.getProperty("line.separator"); + } + + // Create whole stack trace in a stringbuffer so we don't have to print + // it line by line. This prevents printing multiple stack traces from + // different threads to get mixed up when written to the same PrintWriter. + private String stackTraceString() + { + StringBuffer sb = new StringBuffer(); + + // Main stacktrace + StackTraceElement[] stack = getStackTrace(); + stackTraceStringBuffer(sb, this.toString(), stack, 0); + + // The cause(s) + Throwable cause = getCause(); + while (cause != null) + { + // Cause start first line + sb.append("Caused by: "); + + // Cause stacktrace + StackTraceElement[] parentStack = stack; + stack = cause.getStackTrace(); + if (parentStack == null || parentStack.length == 0) + stackTraceStringBuffer(sb, cause.toString(), stack, 0); + else + { + int equal = 0; // Count how many of the last stack frames are equal + int frame = stack.length-1; + int parentFrame = parentStack.length-1; + while (frame > 0 && parentFrame > 0) + { + if (stack[frame].equals(parentStack[parentFrame])) + { + equal++; + frame--; + parentFrame--; + } + else + break; + } + stackTraceStringBuffer(sb, cause.toString(), stack, equal); + } + cause = cause.getCause(); + } + + return sb.toString(); + } + + // Adds to the given StringBuffer a line containing the name and + // all stacktrace elements minus the last equal ones. + private static void stackTraceStringBuffer(StringBuffer sb, String name, + StackTraceElement[] stack, int equal) + { + String nl = StaticData.nl; + // (finish) first line + sb.append(name); + sb.append(nl); + + // The stacktrace + if (stack == null || stack.length == 0) + { + sb.append(" <<No stacktrace available>>"); + sb.append(nl); + } + else + { + for (int i = 0; i < stack.length-equal; i++) + { + sb.append(" at "); + sb.append(stack[i] == null ? "<<Unknown>>" : stack[i].toString()); + sb.append(nl); + } + if (equal > 0) + { + sb.append(" ..."); + sb.append(equal); + sb.append(" more"); + sb.append(nl); + } + } + } + + /** + * Fill in the stack trace with the current execution stack. + * + * @return this same throwable + * @see #printStackTrace() + */ + public Throwable fillInStackTrace() + { + vmState = VMThrowable.fillInStackTrace(this); + stackTrace = null; // Should be regenerated when used. + + return this; + } + + /** + * Provides access to the information printed in {@link #printStackTrace()}. + * The array is non-null, with no null entries, although the virtual + * machine is allowed to skip stack frames. If the array is not 0-length, + * then slot 0 holds the information on the stack frame where the Throwable + * was created (or at least where <code>fillInStackTrace()</code> was + * called). + * + * @return an array of stack trace information, as available from the VM + * @since 1.4 + */ + public StackTraceElement[] getStackTrace() + { + if (stackTrace == null) + if (vmState == null) + stackTrace = new StackTraceElement[0]; + else + { + stackTrace = vmState.getStackTrace(this); + vmState = null; // No longer needed + } + + return stackTrace; + } + + /** + * Change the stack trace manually. This method is designed for remote + * procedure calls, which intend to alter the stack trace before or after + * serialization according to the context of the remote call. + * <p> + * The contents of the given stacktrace is copied so changes to the + * original array do not change the stack trace elements of this + * throwable. + * + * @param stackTrace the new trace to use + * @throws NullPointerException if stackTrace is null or has null elements + * @since 1.4 + */ + public void setStackTrace(StackTraceElement[] stackTrace) + { + int i = stackTrace.length; + StackTraceElement[] st = new StackTraceElement[i]; + + while (--i >= 0) + { + st[i] = stackTrace[i]; + if (st[i] == null) + throw new NullPointerException("Element " + i + " null"); + } + + this.stackTrace = st; + } + + /** + * VM state when fillInStackTrace was called. + * Used by getStackTrace() to get an array of StackTraceElements. + * Cleared when no longer needed. + */ + private transient VMThrowable vmState; +} diff --git a/libjava/classpath/java/lang/TypeNotPresentException.java b/libjava/classpath/java/lang/TypeNotPresentException.java new file mode 100644 index 0000000..3010c96 --- /dev/null +++ b/libjava/classpath/java/lang/TypeNotPresentException.java @@ -0,0 +1,97 @@ +/* TypeNotPresentException.java -- Thrown when a string-based type is missing + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * <p> + * Thrown when a type is accessed using a <code>String</code>-based + * representation, but no definition of the supplied type is found. + * This is effectively an unchecked equivalent of the existing + * <code>ClassNotFound</code> exception. + * </p> + * <p> + * It may occur due to an attempt to load a missing class, interface or + * annotation, or when an undefined type variable is accessed. + * </p> + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @see ClassNotFoundException + * @since 1.5 + */ +public class TypeNotPresentException + extends RuntimeException +{ + + /** + * Constructs a <code>TypeNotPresentException</code> for + * the supplied type. The specified cause <code>Throwable</code> + * may be used to provide additional history, with regards to the + * root of the problem. It is perfectly valid for this to be null, + * if the cause of the problem is unknown. + * + * @param typeName the name of the missing type. + * @param cause the cause of this exception, or null if the cause + * is unknown. + */ + public TypeNotPresentException(String typeName, Throwable cause) + { + super("type \"" + typeName + "\" not found", cause); + this.typeName = typeName; + } + + /** + * Returns the name of the missing type. + * + * @return the missing type's name. + */ + public String typeName() + { + return typeName; + } + + /** + * The name of the missing type. + * + * @serial the missing type's name. + */ + // Name fixed by serialization. + private String typeName; + +} diff --git a/libjava/classpath/java/lang/UnknownError.java b/libjava/classpath/java/lang/UnknownError.java new file mode 100644 index 0000000..7b317bd --- /dev/null +++ b/libjava/classpath/java/lang/UnknownError.java @@ -0,0 +1,72 @@ +/* UnknownError.java -- thrown when the VM cannot provide more information + about a catastrophic error + Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>UnknownError</code> is thrown when a serious but unknown + * problem has occurred in the Java Virtual Machine. + * + * @author Brian Jones + * @status updated to 1.4 + */ +public class UnknownError extends VirtualMachineError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 2524784860676771849L; + + /** + * Create an error without a message. + */ + public UnknownError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public UnknownError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/UnsatisfiedLinkError.java b/libjava/classpath/java/lang/UnsatisfiedLinkError.java new file mode 100644 index 0000000..0d513d8 --- /dev/null +++ b/libjava/classpath/java/lang/UnsatisfiedLinkError.java @@ -0,0 +1,74 @@ +/* UnsatisfiedLinkError.java -- thrown when a native method cannot be loaded + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>UnsatisfiedLinkError</code> is thrown if an appropriate + * native language definition of a method declared <code>native</code> + * cannot be found by the Java Virtual Machine. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @see Runtime + * @status updated to 1.4 + */ +public class UnsatisfiedLinkError extends LinkageError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = -4019343241616879428L; + + /** + * Create an error without a message. + */ + public UnsatisfiedLinkError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public UnsatisfiedLinkError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/UnsupportedClassVersionError.java b/libjava/classpath/java/lang/UnsupportedClassVersionError.java new file mode 100644 index 0000000..d6974b7 --- /dev/null +++ b/libjava/classpath/java/lang/UnsupportedClassVersionError.java @@ -0,0 +1,74 @@ +/* UnsupportedClassVersionError.java -- thrown when a class file version + exceeds the capability of the virtual machine + Copyright (C) 1998, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * An <code>UnsupportedClassVersionError</code> is thrown when the + * Java Virtual Machine determines it does not support the major and minor + * version numbers in the class file it is attempting to read. + * + * @author Brian Jones + * @since 1.2 + * @status updated to 1.4 + */ +public class UnsupportedClassVersionError extends ClassFormatError +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -7123279212883497373L; + + /** + * Create an error without a message. + */ + public UnsupportedClassVersionError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public UnsupportedClassVersionError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/UnsupportedOperationException.java b/libjava/classpath/java/lang/UnsupportedOperationException.java new file mode 100644 index 0000000..0387d0e --- /dev/null +++ b/libjava/classpath/java/lang/UnsupportedOperationException.java @@ -0,0 +1,73 @@ +/* UnsupportedOperationException.java -- thrown when an operation is not + supported + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * This exception is thrown by an object when an operation is + * requested of it that it does not support. + * + * @author Warren Levy (warrenl@cygnus.com) + * @since 1.2 + * @status updated to 1.4 + */ +public class UnsupportedOperationException extends RuntimeException +{ + /** + * Compatible with JDK 1.2+. + */ + private static final long serialVersionUID = -1242599979055084673L; + + /** + * Create an exception without a message. + */ + public UnsupportedOperationException() + { + } + + /** + * Create an exception with a message. + * + * @param s the message + */ + public UnsupportedOperationException(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/VerifyError.java b/libjava/classpath/java/lang/VerifyError.java new file mode 100644 index 0000000..350ceaa --- /dev/null +++ b/libjava/classpath/java/lang/VerifyError.java @@ -0,0 +1,72 @@ +/* VerifyError.java -- thrown when a class fails verification + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>VerifyError</code> is thrown if there is a security problem or + * internal inconsistency in a class file as detected by the "verifier." + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public class VerifyError extends LinkageError +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 7001962396098498785L; + + /** + * Create an error without a message. + */ + public VerifyError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public VerifyError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/VirtualMachineError.java b/libjava/classpath/java/lang/VirtualMachineError.java new file mode 100644 index 0000000..3062c4f --- /dev/null +++ b/libjava/classpath/java/lang/VirtualMachineError.java @@ -0,0 +1,73 @@ +/* VirtualMachineError.java -- thrown when the Virtual Machine has a problem + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang; + +/** + * A <code>VirtualMachineError</code> or its subclasses are thrown to + * indicate there is something wrong with the Java Virtual Machine or that + * it does not have the resources needed for it to continue execution. + * + * @author Brian Jones + * @author Tom Tromey (tromey@cygnus.com) + * @status updated to 1.4 + */ +public abstract class VirtualMachineError extends Error +{ + /** + * Compatible with JDK 1.0+. + */ + private static final long serialVersionUID = 4161983926571568670L; + + /** + * Create an error without a message. + */ + public VirtualMachineError() + { + } + + /** + * Create an error with a message. + * + * @param s the message + */ + public VirtualMachineError(String s) + { + super(s); + } +} diff --git a/libjava/classpath/java/lang/Void.java b/libjava/classpath/java/lang/Void.java new file mode 100644 index 0000000..1503542 --- /dev/null +++ b/libjava/classpath/java/lang/Void.java @@ -0,0 +1,68 @@ +/* Void.class - defines void.class + Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang; + + +/** + * Void is a placeholder class so that the variable <code>Void.TYPE</code> + * (also available as <code>void.class</code>) can be supported for + * reflection return types. + * + * <p>This class could be Serializable, but that is up to Sun.</p> + * + * @author Paul Fisher + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.1 + * @status updated to 1.4 + */ +public final class Void +{ + /** + * The return type <code>void</code> is represented by this + * <code>Class</code> object. + */ + public static final Class TYPE = VMClassLoader.getPrimitiveClass('V'); + + /** + * Void is non-instantiable. + */ + private Void() + { + } +} diff --git a/libjava/classpath/java/lang/annotation/AnnotationFormatError.java b/libjava/classpath/java/lang/annotation/AnnotationFormatError.java new file mode 100644 index 0000000..40ce3ca --- /dev/null +++ b/libjava/classpath/java/lang/annotation/AnnotationFormatError.java @@ -0,0 +1,104 @@ +/* AnnotationFormatError.java - Thrown when an binary annotation is malformed + Copyright (C) 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang.annotation; + +/** + * Thrown when an annotation found in a class file is + * malformed. When the virtual machine finds a class file + * containing annotations, it attempts to parse them. + * This error is thrown if this operation fails. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class AnnotationFormatError extends Error +{ + + /** + * Constructs a new <code>AnnotationFormatError</code> + * using the specified message to give details of the error. + * + * @param message the message to use in the error output. + */ + public AnnotationFormatError(String message) + { + super(message); + } + + /** + * <p> + * Constructs a new <code>AnnotationFormatError</code> + * using the specified message to give details of the error. + * The supplied cause <code>Throwable</code> is used to + * provide additional history, with regards to the root + * of the problem. It is perfectly valid for this to be null, if + * the cause is unknown. + * </p> + * <p> + * <strong>Note</strong>: if a cause is supplied, the error + * message from this cause is not automatically included in the + * error message given by this error. + * </p> + * + * @param message the message to use in the error output + * @param cause the cause of this error, or null if the cause + * is unknown. + */ + public AnnotationFormatError(String message, Throwable cause) + { + super(message, cause); + } + + /** + * Constructs a new <code>AnnotationFormatError</code> using + * the supplied cause <code>Throwable</code> to + * provide additional history, with regards to the root + * of the problem. It is perfectly valid for this to be null, if + * the cause is unknown. If the cause is not null, the error + * message from this cause will also be used as the message + * for this error. + * + * @param cause the cause of the error. + */ + public AnnotationFormatError(Throwable cause) + { + super(cause); + } + +} diff --git a/libjava/classpath/java/lang/annotation/AnnotationTypeMismatchException.java b/libjava/classpath/java/lang/annotation/AnnotationTypeMismatchException.java new file mode 100644 index 0000000..653305d --- /dev/null +++ b/libjava/classpath/java/lang/annotation/AnnotationTypeMismatchException.java @@ -0,0 +1,116 @@ +/* AnnotationTypeMismatchException.java - Thrown when annotation has changed + Copyright (C) 2004, 2005 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang.annotation; + +import java.lang.reflect.Method; + +/** + * Thrown when accessing an element within an annotation for + * which the type has changed, since compilation or serialization + * took place. The mismatch between the compiled or serialized + * type and the current type causes this exception to be thrown. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class AnnotationTypeMismatchException extends RuntimeException +{ + + /** + * For compatability with Sun's JDK + */ + private static final long serialVersionUID = 8125925355765570191L; + + /** + * Constructs an <code>AnnotationTypeMismatchException</code> + * which is due to a mismatched type in the annotation + * element, <code>m</code>. The erroneous type used for the + * data in <code>m</code> is represented by the string, + * <code>type</code>. This string is of an undefined format, + * and may contain the value as well as the type. + * + * @param m the element from the annotation. + * @param type the name of the erroneous type found in <code>m</code>. + */ + public AnnotationTypeMismatchException(Method m, String type) + { + this.element = m; + this.foundType = type; + } + + /** + * Returns the element from the annotation, for which a + * mismatch occurred. + * + * @return the element with the mismatched type. + */ + public Method element() + { + return element; + } + + /** + * Returns the erroneous type used by the element, + * represented as a <code>String</code>. The format + * of this <code>String</code> is not explicitly specified, + * and may contain the value as well as the type. + * + * @return the type found in the element. + */ + public String foundType() + { + return foundType; + } + + // Names are chosen from serialization spec. + /** + * The element from the annotation. + * + * @serial the element with the mismatched type. + */ + private Method element; + + /** + * The erroneous type used by the element. + * + * @serial the type found in the element. + */ + private String foundType; + +} diff --git a/libjava/classpath/java/lang/annotation/package.html b/libjava/classpath/java/lang/annotation/package.html new file mode 100644 index 0000000..ee70daf --- /dev/null +++ b/libjava/classpath/java/lang/annotation/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.lang.annotation package. + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.lang.annotation</title></head> + +<body> +<p>Classes to handle annotations.</p> + +</body> +</html> diff --git a/libjava/classpath/java/lang/class-dependencies.conf b/libjava/classpath/java/lang/class-dependencies.conf new file mode 100644 index 0000000..4fbf75e --- /dev/null +++ b/libjava/classpath/java/lang/class-dependencies.conf @@ -0,0 +1,58 @@ +# This property file contains dependencies of classes, methods, and +# field on other methods or classes. +# +# Syntax: +# +# <used>: <needed 1> [... <needed N>] +# +# means that when <used> is included, <needed 1> (... <needed N>) must +# be included as well. +# +# <needed X> and <used> are of the form +# +# <class.methodOrField(signature)> +# +# or just +# +# <class> +# +# Within dependencies, variables can be used. A variable is defined as +# follows: +# +# {variable}: value1 value2 ... value<n> +# +# variables can be used on the right side of dependencies as follows: +# +# <used>: com.bla.blu.{variable}.Class.m()V +# +# The use of the variable will expand to <n> dependencies of the form +# +# <used>: com.bla.blu.value1.Class.m()V +# <used>: com.bla.blu.value2.Class.m()V +# ... +# <used>: com.bla.blu.value<n>.Class.m()V +# +# Variables can be redefined when building a system to select the +# required support for features like encodings, protocols, etc. +# +# Hints: +# +# - For methods and fields, the signature is mandatory. For +# specification, please see the Java Virtual Machine Specification by +# SUN. Unlike in the spec, field signatures (types) are in brackets. +# +# - Package names must be separated by '/' (and not '.'). E.g., +# java/lang/Class (this is necessary, because the '.' is used to +# separate method or field names from classes) +# +# - In case <needed> refers to a class, only the class itself will be +# included in the resulting binary, NOT necessarily all its methods +# and fields. If you want to refer to all methods and fields, you can +# write class.* as an abbreviation. +# +# - Abbreviations for packages are also possible: my/package/* means all +# methods and fields of all classes in my/package. +# +# - A line with a trailing '\' continues in the next line. + +# end of file diff --git a/libjava/classpath/java/lang/package.html b/libjava/classpath/java/lang/package.html new file mode 100644 index 0000000..715418d --- /dev/null +++ b/libjava/classpath/java/lang/package.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.lang package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.lang</title></head> + +<body> +<p>Core classes including wrappers for primitive types, classes, packages +and class loaders, representations of the system, processes, threads and +the core exception hierarchy.</p> + +</body> +</html> diff --git a/libjava/classpath/java/lang/ref/PhantomReference.java b/libjava/classpath/java/lang/ref/PhantomReference.java new file mode 100644 index 0000000..4d929c2 --- /dev/null +++ b/libjava/classpath/java/lang/ref/PhantomReference.java @@ -0,0 +1,73 @@ +/* java.lang.ref.PhantomReference + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.ref; + +/** + * A phantom reference is useful, to get notified, when an object got + * finalized. You can't access that object though, since it is + * finalized. This is the reason, why <code>get()</code> always + * returns null. + * + * @author Jochen Hoenicke + */ +public class PhantomReference + extends Reference +{ + /** + * Creates a new phantom reference. + * @param referent the object that should be watched. + * @param q the queue that should be notified, if the referent was + * finalized. This mustn't be <code>null</code>. + * @exception NullPointerException if q is null. + */ + public PhantomReference(Object referent, ReferenceQueue q) + { + super(referent, q); + } + + /** + * Returns the object, this reference refers to. + * @return <code>null</code>, since the refered object may be + * finalized and thus not accessible. + */ + public Object get() + { + return null; + } +} diff --git a/libjava/classpath/java/lang/ref/Reference.java b/libjava/classpath/java/lang/ref/Reference.java new file mode 100644 index 0000000..1ec7243 --- /dev/null +++ b/libjava/classpath/java/lang/ref/Reference.java @@ -0,0 +1,177 @@ +/* java.lang.ref.Reference + Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.ref; + +/** + * This is the base class of all references. A reference allows + * refering to an object without preventing the garbage collector to + * collect it. The only way to get the referred object is via the + * <code>get()</code>-method. This method will return + * <code>null</code> if the object was collected. <br> + * + * A reference may be registered with a queue. When a referred + * element gets collected the reference will be put on the queue, so + * that you will be notified. <br> + * + * There are currently three types of references: soft reference, + * weak reference and phantom reference. <br> + * + * Soft references will be cleared if the garbage collector is told + * to free some memory and there are no unreferenced or weakly referenced + * objects. It is useful for caches. <br> + * + * Weak references will be cleared as soon as the garbage collector + * determines that the refered object is only weakly reachable. They + * are useful as keys in hashtables (see <code>WeakHashtable</code>) as + * you get notified when nobody has the key anymore. + * + * Phantom references don't prevent finalization. If an object is only + * phantom reachable, it will be finalized, and the reference will be + * enqueued, but not cleared. Since you mustn't access an finalized + * object, the <code>get</code> method of a phantom reference will never + * work. It is useful to keep track, when an object is finalized. + * + * @author Jochen Hoenicke + * @see java.util.WeakHashtable + */ +public abstract class Reference +{ + /** + * The underlying object. This field is handled in a special way by + * the garbage collector. + */ + Object referent; + + /** + * The queue this reference is registered on. This is null, if this + * wasn't registered to any queue or reference was already enqueued. + */ + ReferenceQueue queue; + + /** + * Link to the next entry on the queue. If this is null, this + * reference is not enqueued. Otherwise it points to the next + * reference. The last reference on a queue will point to itself + * (not to null, that value is used to mark a not enqueued + * reference). + */ + Reference nextOnQueue; + + /** + * This lock should be taken by the garbage collector, before + * determining reachability. It will prevent the get()-method to + * return the reference so that reachability doesn't change. + */ + static Object lock = new Object(); + + /** + * Creates a new reference that is not registered to any queue. + * Since it is package private, it is not possible to overload this + * class in a different package. + * @param referent the object we refer to. + */ + Reference(Object ref) + { + referent = ref; + } + + /** + * Creates a reference that is registered to a queue. Since this is + * package private, it is not possible to overload this class in a + * different package. + * @param referent the object we refer to. + * @param q the reference queue to register on. + * @exception NullPointerException if q is null. + */ + Reference(Object ref, ReferenceQueue q) + { + if (q == null) + throw new NullPointerException(); + referent = ref; + queue = q; + } + + /** + * Returns the object, this reference refers to. + * @return the object, this reference refers to, or null if the + * reference was cleared. + */ + public Object get() + { + synchronized (lock) + { + return referent; + } + } + + /** + * Clears the reference, so that it doesn't refer to its object + * anymore. For soft and weak references this is called by the + * garbage collector. For phantom references you should call + * this when enqueuing the reference. + */ + public void clear() + { + referent = null; + } + + /** + * Tells if the object is enqueued on a reference queue. + * @return true if it is enqueued, false otherwise. + */ + public boolean isEnqueued() + { + return nextOnQueue != null; + } + + /** + * Enqueue an object on a reference queue. This is normally executed + * by the garbage collector. + */ + public boolean enqueue() + { + if (queue != null && nextOnQueue == null) + { + queue.enqueue(this); + queue = null; + return true; + } + return false; + } +} diff --git a/libjava/classpath/java/lang/ref/ReferenceQueue.java b/libjava/classpath/java/lang/ref/ReferenceQueue.java new file mode 100644 index 0000000..f4729f2 --- /dev/null +++ b/libjava/classpath/java/lang/ref/ReferenceQueue.java @@ -0,0 +1,145 @@ +/* java.lang.ref.ReferenceQueue + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.ref; + +/** + * This is the queue, where references can enqueue themselve on. Each + * reference may be registered to a queue at initialization time and + * will be appended to the queue, when the enqueue method is called. + * + * The enqueue method may be automatically called by the garbage + * collector if it detects, that the object is only reachable through + * the Reference objects. + * + * @author Jochen Hoenicke + * @see Reference#enqueue() + */ +public class ReferenceQueue +{ + /** + * This is a linked list of references. If this is null, the list is + * empty. Otherwise this points to the first reference on the queue. + * The first reference will point to the next reference via the + * <code>nextOnQueue</code> field. The last reference will point to + * itself (not to null, since <code>nextOnQueue</code> is used to + * determine if a reference is enqueued). + */ + private Reference first; + + /** + * Creates a new empty reference queue. + */ + public ReferenceQueue() + { + } + + /** + * Checks if there is a reference on the queue, returning it + * immediately. The reference will be dequeued. + * + * @return a reference on the queue, if there is one, + * <code>null</code> otherwise. + */ + public synchronized Reference poll() + { + return dequeue(); + } + + /** + * This is called by reference to enqueue itself on this queue. + * @param ref the reference that should be enqueued. + */ + synchronized void enqueue(Reference ref) + { + /* last reference will point to itself */ + ref.nextOnQueue = first == null ? ref : first; + first = ref; + /* this wakes only one remove thread. */ + notify(); + } + + /** + * Remove a reference from the queue, if there is one. + * @return the first element of the queue, or null if there isn't any. + */ + private Reference dequeue() + { + if (first == null) + return null; + + Reference result = first; + first = (first == first.nextOnQueue) ? null : first.nextOnQueue; + result.nextOnQueue = null; + return result; + } + + /** + * Removes a reference from the queue, blocking for <code>timeout</code> + * until a reference is enqueued. + * @param timeout the timeout period in milliseconds, <code>0</code> means + * wait forever. + * @return the reference removed from the queue, or + * <code>null</code> if timeout period expired. + * @exception InterruptedException if the wait was interrupted. + */ + public synchronized Reference remove(long timeout) + throws InterruptedException + { + if (first == null) + { + wait(timeout); + } + + return dequeue(); + } + + + /** + * Removes a reference from the queue, blocking until a reference is + * enqueued. + * + * @return the reference removed from the queue. + * @exception InterruptedException if the wait was interrupted. + */ + public Reference remove() + throws InterruptedException + { + return remove(0L); + } +} diff --git a/libjava/classpath/java/lang/ref/SoftReference.java b/libjava/classpath/java/lang/ref/SoftReference.java new file mode 100644 index 0000000..97395ea --- /dev/null +++ b/libjava/classpath/java/lang/ref/SoftReference.java @@ -0,0 +1,84 @@ +/* java.lang.ref.SoftReference + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.ref; + +/** + * A soft reference will be cleared, if the object is only softly + * reachable and the garbage collection needs more memory. The garbage + * collection will use an intelligent strategy to determine which soft + * references it should clear. This makes a soft reference ideal for + * caches.<br> + * + * @author Jochen Hoenicke + */ +public class SoftReference + extends Reference +{ + /** + * Create a new soft reference, that is not registered to any queue. + * @param referent the object we refer to. + */ + public SoftReference(Object referent) + { + super(referent); + } + + /** + * Create a new soft reference. + * @param referent the object we refer to. + * @param q the reference queue to register on. + * @exception NullPointerException if q is null. + */ + public SoftReference(Object referent, ReferenceQueue q) + { + super(referent, q); + } + + /** + * Returns the object, this reference refers to. + * @return the object, this reference refers to, or null if the + * reference was cleared. + */ + public Object get() + { + /* Why is this overloaded??? + * Maybe for a kind of LRU strategy. */ + return super.get(); + } +} diff --git a/libjava/classpath/java/lang/ref/WeakReference.java b/libjava/classpath/java/lang/ref/WeakReference.java new file mode 100644 index 0000000..9f758ca --- /dev/null +++ b/libjava/classpath/java/lang/ref/WeakReference.java @@ -0,0 +1,79 @@ +/* java.lang.ref.WeakReference + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.ref; + +/** + * A weak reference will be cleared, if the object is only weakly + * reachable. It is useful for lookup tables, where you aren't + * interested in an entry, if the key isn't reachable anymore. + * <code>WeakHashtable</code> is a complete implementation of such a + * table. <br> + * + * It is also useful to make objects unique: You create a set of weak + * references to those objects, and when you create a new object you + * look in this set, if the object already exists and return it. If + * an object is not referenced anymore, the reference will + * automatically cleared, and you may remove it from the set. <br> + * + * @author Jochen Hoenicke + * @see java.util.WeakHashtable + */ +public class WeakReference + extends Reference +{ + /** + * Create a new weak reference, that is not registered to any queue. + * @param referent the object we refer to. + */ + public WeakReference(Object referent) + { + super(referent); + } + + /** + * Create a new weak reference. + * @param referent the object we refer to. + * @param q the reference queue to register on. + * @exception NullPointerException if q is null. + */ + public WeakReference(Object referent, ReferenceQueue q) + { + super(referent, q); + } +} diff --git a/libjava/classpath/java/lang/ref/package.html b/libjava/classpath/java/lang/ref/package.html new file mode 100644 index 0000000..d3d1762 --- /dev/null +++ b/libjava/classpath/java/lang/ref/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.lang.ref package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.lang.ref</title></head> + +<body> +<p>Low level manipulation and monitoring of object references.</p> + +</body> +</html> diff --git a/libjava/classpath/java/lang/reflect/AccessibleObject.java b/libjava/classpath/java/lang/reflect/AccessibleObject.java new file mode 100644 index 0000000..24418c9 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/AccessibleObject.java @@ -0,0 +1,159 @@ +/* java.lang.reflect.AccessibleObject + Copyright (C) 2001, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * This class is the superclass of various reflection classes, and + * allows sufficiently trusted code to bypass normal restrictions to + * do necessary things like invoke private methods outside of the + * class during Serialization. If you don't have a good reason + * to mess with this, don't try. Fortunately, there are adequate + * security checks before you can set a reflection object as accessible. + * + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see Field + * @see Constructor + * @see Method + * @see ReflectPermission + * @since 1.2 + * @status updated to 1.4 + */ +public class AccessibleObject +{ + /** + * True if this object is marked accessible, which means the reflected + * object bypasses normal security checks. + */ + // default visibility for use by inherited classes + boolean flag = false; + + /** + * Only the three reflection classes that extend this can create an + * accessible object. This is not serializable for security reasons. + */ + protected AccessibleObject() + { + } + + /** + * Return the accessibility status of this object. + * + * @return true if this object bypasses security checks + */ + public boolean isAccessible() + { + return flag; + } + + /** + * Convenience method to set the flag on a number of objects with a single + * security check. If a security manager exists, it is checked for + * <code>ReflectPermission("suppressAccessChecks")</code>.<p> + * + * It is forbidden to set the accessibility flag to true on any constructor + * for java.lang.Class. This will result in a SecurityException. If the + * SecurityException is thrown for any of the passed AccessibleObjects, + * the accessibility flag will be set on AccessibleObjects in the array prior + * to the one which resulted in the exception. + * + * @param array the array of accessible objects + * @param flag the desired state of accessibility, true to bypass security + * @throws NullPointerException if array is null + * @throws SecurityException if the request is denied + * @see SecurityManager#checkPermission(java.security.Permission) + * @see RuntimePermission + */ + public static void setAccessible(AccessibleObject[] array, boolean flag) + { + checkPermission(); + for (int i = 0; i < array.length; i++) + array[i].secureSetAccessible(flag); + } + + /** + * Sets the accessibility flag for this reflection object. If a security + * manager exists, it is checked for + * <code>ReflectPermission("suppressAccessChecks")</code>.<p> + * + * It is forbidden to set the accessibility flag to true on any constructor for + * java.lang.Class. This will result in a SecurityException. + * + * @param flag the desired state of accessibility, true to bypass security + * @throws NullPointerException if array is null + * @throws SecurityException if the request is denied + * @see SecurityManager#checkPermission(java.security.Permission) + * @see RuntimePermission + */ + public void setAccessible(boolean flag) + { + checkPermission(); + secureSetAccessible(flag); + } + + /** + * Performs the specified security check, for + * <code>ReflectPermission("suppressAccessChecks")</code>. + * + * @throws SecurityException if permission is denied + */ + private static void checkPermission() + { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkPermission(new ReflectPermission("suppressAccessChecks")); + } + + /** + * Performs the actual accessibility change, this must always be invoked + * after calling checkPermission. + * + * @param flag the desired status + * @throws SecurityException if flag is true and this is a constructor + * for <code>java.lang.Class</code>. + */ + private void secureSetAccessible(boolean flag) + { + if (flag && + (this instanceof Constructor + && ((Constructor) this).getDeclaringClass() == Class.class)) + throw new SecurityException("Cannot make object accessible: " + this); + this.flag = flag; + } +} diff --git a/libjava/classpath/java/lang/reflect/Array.java b/libjava/classpath/java/lang/reflect/Array.java new file mode 100644 index 0000000..35c77da --- /dev/null +++ b/libjava/classpath/java/lang/reflect/Array.java @@ -0,0 +1,675 @@ +/* java.lang.reflect.Array - manipulate arrays by reflection + Copyright (C) 1998, 1999, 2001, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +import gnu.classpath.Configuration; + +/** + * Array holds static helper functions that allow you to create and + * manipulate arrays by reflection. Operations know how to perform widening + * conversions, but throw {@link IllegalArgumentException} if you attempt + * a narrowing conversion. Also, when accessing primitive arrays, this + * class performs object wrapping and unwrapping as necessary.<p> + * + * <B>Note:</B> This class returns and accepts types as Classes, even + * primitive types; there are Class types defined that represent each + * different primitive type. They are <code>java.lang.Boolean.TYPE, + * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class, + * byte.class</code>, etc. These are not to be confused with the + * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are + * real classes. Note also that the shorthand <code>Object[].class</code> + * is a convenient way to get array Classes.<p> + * + * <B>Performance note:</B> This class performs best when it does not have + * to convert primitive types. The further along the chain it has to convert, + * the worse performance will be. You're best off using the array as whatever + * type it already is, and then converting the result. You will do even + * worse if you do this and use the generic set() function. + * + * @author John Keiser + * @author Eric Blake (ebb9@email.byu.edu) + * @author Per Bothner (bothner@cygnus.com) + * @see java.lang.Boolean#TYPE + * @see java.lang.Byte#TYPE + * @see java.lang.Short#TYPE + * @see java.lang.Character#TYPE + * @see java.lang.Integer#TYPE + * @see java.lang.Long#TYPE + * @see java.lang.Float#TYPE + * @see java.lang.Double#TYPE + * @since 1.1 + * @status updated to 1.4 + */ +public final class Array +{ + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javalangreflect"); + } + } + + /** + * This class is uninstantiable. + */ + private Array() + { + } + + /** + * Creates a new single-dimensioned array. + * @param componentType the type of the array to create + * @param length the length of the array to create + * @return the created array, cast to an Object + * @throws NullPointerException if <code>componentType</code> is null + * @throws IllegalArgumentException if <code>componentType</code> is + * <code>Void.TYPE</code> + * @throws NegativeArraySizeException when length is less than 0 + * @throws OutOfMemoryError if memory allocation fails + */ + public static Object newInstance(Class componentType, int length) + { + if (! componentType.isPrimitive()) + return createObjectArray(componentType, length); + if (componentType == boolean.class) + return new boolean[length]; + if (componentType == byte.class) + return new byte[length]; + if (componentType == char.class) + return new char[length]; + if (componentType == short.class) + return new short[length]; + if (componentType == int.class) + return new int[length]; + if (componentType == long.class) + return new long[length]; + if (componentType == float.class) + return new float[length]; + if (componentType == double.class) + return new double[length]; + // assert componentType == void.class + throw new IllegalArgumentException(); + } + + /** + * Creates a new multi-dimensioned array. The new array has the same + * component type as the argument class, and the number of dimensions + * in the new array is the sum of the dimensions of the argument class + * and the length of the argument dimensions. Virtual Machine limitations + * forbid too many dimensions (usually 255 is the maximum); but even + * 50 dimensions of 2 elements in each dimension would exceed your memory + * long beforehand! + * + * @param componentType the type of the array to create. + * @param dimensions the dimensions of the array to create. Each element + * in <code>dimensions</code> makes another dimension of the new + * array. Thus, <code>Array.newInstance(java.lang.Boolean, + * new int[]{1,2,3})</code> is the same as + * <code>new java.lang.Boolean[1][2][3]</code> + * @return the created array, cast to an Object + * @throws NullPointerException if componentType or dimension is null + * @throws IllegalArgumentException if the the size of + * <code>dimensions</code> is 0 or exceeds the maximum number of + * array dimensions in the VM; or if componentType is Void.TYPE + * @throws NegativeArraySizeException when any of the dimensions is less + * than 0 + * @throws OutOfMemoryError if memory allocation fails + */ + public static Object newInstance(Class componentType, int[] dimensions) + { + if (dimensions.length <= 0) + throw new IllegalArgumentException ("Empty dimensions array."); + return createMultiArray(componentType, dimensions, + dimensions.length - 1); + } + + /** + * Gets the array length. + * @param array the array + * @return the length of the array + * @throws IllegalArgumentException if <code>array</code> is not an array + * @throws NullPointerException if <code>array</code> is null + */ + public static int getLength(Object array) + { + if (array instanceof Object[]) + return ((Object[]) array).length; + if (array instanceof boolean[]) + return ((boolean[]) array).length; + if (array instanceof byte[]) + return ((byte[]) array). length; + if (array instanceof char[]) + return ((char[]) array).length; + if (array instanceof short[]) + return ((short[]) array).length; + if (array instanceof int[]) + return ((int[]) array).length; + if (array instanceof long[]) + return ((long[]) array).length; + if (array instanceof float[]) + return ((float[]) array).length; + if (array instanceof double[]) + return ((double[]) array).length; + if (array == null) + throw new NullPointerException(); + throw new IllegalArgumentException(); + } + + /** + * Gets an element of an array. Primitive elements will be wrapped in + * the corresponding class type. + * + * @param array the array to access + * @param index the array index to access + * @return the element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not an array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #getBoolean(Object, int) + * @see #getByte(Object, int) + * @see #getChar(Object, int) + * @see #getShort(Object, int) + * @see #getInt(Object, int) + * @see #getLong(Object, int) + * @see #getFloat(Object, int) + * @see #getDouble(Object, int) + */ + public static Object get(Object array, int index) + { + if (array instanceof Object[]) + return ((Object[]) array)[index]; + if (array instanceof boolean[]) + return ((boolean[]) array)[index] ? Boolean.TRUE : Boolean.FALSE; + if (array instanceof byte[]) + return new Byte(((byte[]) array)[index]); + if (array instanceof char[]) + return new Character(((char[]) array)[index]); + if (array instanceof short[]) + return new Short(((short[]) array)[index]); + if (array instanceof int[]) + return new Integer(((int[]) array)[index]); + if (array instanceof long[]) + return new Long(((long[]) array)[index]); + if (array instanceof float[]) + return new Float(((float[]) array)[index]); + if (array instanceof double[]) + return new Double(((double[]) array)[index]); + if (array == null) + throw new NullPointerException(); + throw new IllegalArgumentException(); + } + + /** + * Gets an element of a boolean array. + * + * @param array the array to access + * @param index the array index to access + * @return the boolean element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a boolean + * array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static boolean getBoolean(Object array, int index) + { + if (array instanceof boolean[]) + return ((boolean[]) array)[index]; + if (array == null) + throw new NullPointerException(); + throw new IllegalArgumentException(); + } + + /** + * Gets an element of a byte array. + * + * @param array the array to access + * @param index the array index to access + * @return the byte element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a byte + * array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static byte getByte(Object array, int index) + { + if (array instanceof byte[]) + return ((byte[]) array)[index]; + if (array == null) + throw new NullPointerException(); + throw new IllegalArgumentException(); + } + + /** + * Gets an element of a char array. + * + * @param array the array to access + * @param index the array index to access + * @return the char element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a char + * array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static char getChar(Object array, int index) + { + if (array instanceof char[]) + return ((char[]) array)[index]; + if (array == null) + throw new NullPointerException(); + throw new IllegalArgumentException(); + } + + /** + * Gets an element of a short array. + * + * @param array the array to access + * @param index the array index to access + * @return the short element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a byte + * or char array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static short getShort(Object array, int index) + { + if (array instanceof short[]) + return ((short[]) array)[index]; + return getByte(array, index); + } + + /** + * Gets an element of an int array. + * + * @param array the array to access + * @param index the array index to access + * @return the int element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a byte, + * char, short, or int array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static int getInt(Object array, int index) + { + if (array instanceof int[]) + return ((int[]) array)[index]; + if (array instanceof char[]) + return ((char[]) array)[index]; + return getShort(array, index); + } + + /** + * Gets an element of a long array. + * + * @param array the array to access + * @param index the array index to access + * @return the long element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a byte, + * char, short, int, or long array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static long getLong(Object array, int index) + { + if (array instanceof long[]) + return ((long[]) array)[index]; + return getInt(array, index); + } + + /** + * Gets an element of a float array. + * + * @param array the array to access + * @param index the array index to access + * @return the float element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a byte, + * char, short, int, long, or float array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static float getFloat(Object array, int index) + { + if (array instanceof float[]) + return ((float[]) array)[index]; + return getLong(array, index); + } + + /** + * Gets an element of a double array. + * + * @param array the array to access + * @param index the array index to access + * @return the double element at <code>array[index]</code> + * @throws IllegalArgumentException if <code>array</code> is not a byte, + * char, short, int, long, float, or double array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #get(Object, int) + */ + public static double getDouble(Object array, int index) + { + if (array instanceof double[]) + return ((double[]) array)[index]; + return getFloat(array, index); + } + + /** + * Sets an element of an array. If the array is primitive, then the new + * value is unwrapped and widened. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not an array, + * or the array is primitive and unwrapping value fails, or the + * value is not assignable to the array component type + * @throws NullPointerException if array is null, or if array is primitive + * and value is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #setBoolean(Object, int, boolean) + * @see #setByte(Object, int, byte) + * @see #setChar(Object, int, char) + * @see #setShort(Object, int, short) + * @see #setInt(Object, int, int) + * @see #setLong(Object, int, long) + * @see #setFloat(Object, int, float) + * @see #setDouble(Object, int, double) + */ + public static void set(Object array, int index, Object value) + { + if (array instanceof Object[]) + { + // Too bad the API won't let us throw the easier ArrayStoreException! + if (value != null + && ! array.getClass().getComponentType().isInstance(value)) + throw new IllegalArgumentException(); + ((Object[]) array)[index] = value; + } + else if (value instanceof Byte) + setByte(array, index, ((Byte) value).byteValue()); + else if (value instanceof Short) + setShort(array, index, ((Short) value).shortValue()); + else if (value instanceof Integer) + setInt(array, index, ((Integer) value).intValue()); + else if (value instanceof Long) + setLong(array, index, ((Long) value).longValue()); + else if (value instanceof Float) + setFloat(array, index, ((Float) value).floatValue()); + else if (value instanceof Double) + setDouble(array, index, ((Double) value).doubleValue()); + else if (value instanceof Character) + setChar(array, index, ((Character) value).charValue()); + else if (value instanceof Boolean) + setBoolean(array, index, ((Boolean) value).booleanValue()); + else if (array == null) + throw new NullPointerException(); + else + throw new IllegalArgumentException(); + } + + /** + * Sets an element of a boolean array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not a boolean + * array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setBoolean(Object array, int index, boolean value) + { + if (array instanceof boolean[]) + ((boolean[]) array)[index] = value; + else if (array == null) + throw new NullPointerException(); + else + throw new IllegalArgumentException(); + } + + /** + * Sets an element of a byte array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not a byte, + * short, int, long, float, or double array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setByte(Object array, int index, byte value) + { + if (array instanceof byte[]) + ((byte[]) array)[index] = value; + else + setShort(array, index, value); + } + + /** + * Sets an element of a char array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not a char, + * int, long, float, or double array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setChar(Object array, int index, char value) + { + if (array instanceof char[]) + ((char[]) array)[index] = value; + else + setInt(array, index, value); + } + + /** + * Sets an element of a short array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not a short, + * int, long, float, or double array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setShort(Object array, int index, short value) + { + if (array instanceof short[]) + ((short[]) array)[index] = value; + else + setInt(array, index, value); + } + + /** + * Sets an element of an int array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not an int, + * long, float, or double array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setInt(Object array, int index, int value) + { + if (array instanceof int[]) + ((int[]) array)[index] = value; + else + setLong(array, index, value); + } + + /** + * Sets an element of a long array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not a long, + * float, or double array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setLong(Object array, int index, long value) + { + if (array instanceof long[]) + ((long[]) array)[index] = value; + else + setFloat(array, index, value); + } + + /** + * Sets an element of a float array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not a float + * or double array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setFloat(Object array, int index, float value) + { + if (array instanceof float[]) + ((float[]) array)[index] = value; + else + setDouble(array, index, value); + } + + /** + * Sets an element of a double array. + * + * @param array the array to set a value of + * @param index the array index to set the value to + * @param value the value to set + * @throws IllegalArgumentException if <code>array</code> is not a double + * array + * @throws NullPointerException if <code>array</code> is null + * @throws ArrayIndexOutOfBoundsException if <code>index</code> is out of + * bounds + * @see #set(Object, int, Object) + */ + public static void setDouble(Object array, int index, double value) + { + if (array instanceof double[]) + ((double[]) array)[index] = value; + else if (array == null) + throw new NullPointerException(); + else + throw new IllegalArgumentException(); + } + + /** + * Dynamically and recursively create a multi-dimensioned array of objects. + * + * @param type guaranteed to be a valid object type + * @param dimensions the dimensions of the array + * @param index index of the current dimension to build + * @return the new multi-dimensioned array + * @throws NegativeArraySizeException if any entry of dimensions is negative + * @throws OutOfMemoryError if memory allocation fails + */ + // This would be faster if implemented natively, using the multianewarray + // bytecode instead of this recursive call + private static Object createMultiArray(Class type, int[] dimensions, + int index) + { + if (index == 0) + return newInstance(type, dimensions[0]); + + Object toAdd = createMultiArray(type, dimensions, index - 1); + Class thisType = toAdd.getClass(); + Object[] retval + = (Object[]) createObjectArray(thisType, dimensions[index]); + if (dimensions[index] > 0) + retval[0] = toAdd; + int i = dimensions[index]; + while (--i > 0) + retval[i] = createMultiArray(type, dimensions, index - 1); + return retval; + } + + /** + * Dynamically create an array of objects. + * + * @param type guaranteed to be a valid object type + * @param dim the length of the array + * @return the new array + * @throws NegativeArraySizeException if dim is negative + * @throws OutOfMemoryError if memory allocation fails + */ + private static native Object createObjectArray(Class type, int dim); +} diff --git a/libjava/classpath/java/lang/reflect/GenericArrayType.java b/libjava/classpath/java/lang/reflect/GenericArrayType.java new file mode 100644 index 0000000..8dc33a7 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/GenericArrayType.java @@ -0,0 +1,61 @@ +/* GenericArrayType.java - Represent an array type with a generic component + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * Represents the type of an array's components, which may be + * either a parameterized type or a type variable. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public interface GenericArrayType + extends Type +{ + + /** + * Returns the <code>Type</code> of the components within the array. + * + * @return a <code>Type</code> instance representing the type of + * the array's components. + */ + Type getGenericComponentType(); + +} diff --git a/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java new file mode 100644 index 0000000..ab6928d --- /dev/null +++ b/libjava/classpath/java/lang/reflect/GenericSignatureFormatError.java @@ -0,0 +1,62 @@ +/* GenericSignatureFormatError.java - Thrown when a signature is malformed. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * Thrown on encountering a syntactically malformed signature in + * a reflective method. During reflection, the generic type signature + * of a type, method or constructor may be interpreted by the virtual + * machine. This error is thrown if this operation fails. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public class GenericSignatureFormatError + extends ClassFormatError +{ + + /** + * Constructs a new <code>GenericSignatureFormatError</code>. + */ + public GenericSignatureFormatError() + { + } + +} diff --git a/libjava/classpath/java/lang/reflect/InvocationHandler.java b/libjava/classpath/java/lang/reflect/InvocationHandler.java new file mode 100644 index 0000000..208e621 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/InvocationHandler.java @@ -0,0 +1,137 @@ +/* java.lang.reflect.InvocationHandler - dynamically executes methods in + proxy instances + Copyright (C) 2001 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * This interface defines an invocation handler. Suppose you are using + * reflection, and found a method that requires that its parameter + * be an object of a given interface. You want to call this method, + * but have no idea what classes implement that interface. So, you can + * create a {@link Proxy} instance, a convenient way to dynamically + * generate a class that meets all the necessary properties of that + * interface. But in order for the proxy instance to do any good, it + * needs to know what to do when interface methods are invoked! So, + * this interface is basically a cool wrapper that provides runtime + * code generation needed by proxy instances. + * + * <p>While this interface was designed for use by Proxy, it will also + * work on any object in general.</p> + * + * <p>Hints for implementing this class:</p> + * + * <ul> + * <li>Don't forget that Object.equals, Object.hashCode, and + * Object.toString will call this handler. In particular, + * a naive call to proxy.equals, proxy.hashCode, or proxy.toString + * will put you in an infinite loop. And remember that string + * concatenation also invokes toString.</li> + * <li>Obey the contract of the Method object you are handling, or + * the proxy instance will be forced to throw a + * {@link NullPointerException}, {@link ClassCastException}, + * or {@link UndeclaredThrowableException}.</li> + * <li>Be prepared to wrap/unwrap primitives as necessary.</li> + * <li>The Method object may be owned by a different interface than + * what was actually used as the qualifying type of the method + * invocation in the Java source code. This means that it might + * not always be safe to throw an exception listed as belonging + * to the method's throws clause.</li> + * </ul> + * + * <p><small>For a fun time, create an InvocationHandler that handles the + * methods of a proxy instance of the InvocationHandler interface!</small></p> + * + * @see Proxy + * @see UndeclaredThrowableException + * + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4 + */ +public interface InvocationHandler +{ + /** + * When a method is invoked on a proxy instance, it is wrapped and + * this method is called instead, so that you may decide at runtime + * how the original method should behave. + * + * @param proxy the instance that the wrapped method should be + * invoked on. When this method is called by a Proxy object, + * `proxy' will be an instance of {@link Proxy}, and oddly enough, + * <code>Proxy.getInvocationHandler(proxy)</code> will return + * <code>this</code>! + * @param method the reflected method to invoke on the proxy. + * When this method is called by a Proxy object, 'method' + * will be the reflection object owned by the declaring + * class or interface, which may be a supertype of the + * interfaces the proxy directly implements. + * @param args the arguments passed to the original method, or + * <code>null</code> if the method takes no arguments. + * (But also be prepared to handle a 0-length array). + * Arguments of primitive type, such as <code>boolean</code> + * or <code>int</code>, are wrapped in the appropriate + * class such as {@link Boolean} or {@link Integer}. + * @return whatever is necessary to return from the wrapped method. + * If the wrapped method is <code>void</code>, the proxy + * instance will ignore it. If the wrapped method returns + * a primitive, this must be the correct wrapper type whose value + * is exactly assignable to the appropriate type (no widening + * will be performed); a null object in this case causes a + * {@link NullPointerException}. In all remaining cases, if + * the returned object is not assignment compatible to the + * declared type of the original method, the proxy instance + * will generate a {@link ClassCastException}. + * @throws Throwable this interface is listed as throwing anything, + * but the implementation should only throw unchecked + * exceptions and exceptions listed in the throws clause of + * all methods being overridden by the proxy instance. If + * something is thrown that is not compatible with the throws + * clause of all overridden methods, the proxy instance will + * wrap the exception in an UndeclaredThrowableException. + * Note that an exception listed in the throws clause of the + * `method' parameter might not be declared in additional + * interfaces also implemented by the proxy object. + * + * @see Proxy + * @see UndeclaredThrowableException + */ + Object invoke(Object proxy, Method method, Object[] args) + throws Throwable; + +} diff --git a/libjava/classpath/java/lang/reflect/InvocationTargetException.java b/libjava/classpath/java/lang/reflect/InvocationTargetException.java new file mode 100644 index 0000000..af79d3a --- /dev/null +++ b/libjava/classpath/java/lang/reflect/InvocationTargetException.java @@ -0,0 +1,123 @@ +/* InvocationTargetException.java -- Wrapper exception for reflection + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * InvocationTargetException is sort of a way to "wrap" whatever exception + * comes up when a method or constructor is called via Reflection. As of + * JDK 1.4, it was retrofitted to match the exception chaining of all other + * exceptions, but <code>getTargetException()</code> still works. + * + * @author John Keiser + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see Method#invoke(Object,Object[]) + * @see Constructor#newInstance(Object[]) + * @since 1.1 + * @status updated to 1.4 + */ +public class InvocationTargetException extends Exception +{ + /** + * Compatible with JDK 1.1+. + */ + private static final long serialVersionUID = 4085088731926701167L; + + /** + * The chained exception. This field is only around for serial compatibility. + * + * @serial the chained exception + */ + private final Throwable target; + + /** + * Construct an exception with null as the cause. The cause is initialized + * to null. + */ + protected InvocationTargetException() + { + this(null, null); + } + + /** + * Create an <code>InvocationTargetException</code> using another + * exception. + * + * @param targetException the exception to wrap + */ + public InvocationTargetException(Throwable targetException) + { + this(targetException, null); + } + + /** + * Create an <code>InvocationTargetException</code> using another + * exception and an error message. + * + * @param targetException the exception to wrap + * @param err an extra reason for the exception-throwing + */ + public InvocationTargetException(Throwable targetException, String err) + { + super(err, targetException); + target = targetException; + } + + /** + * Get the wrapped (targeted) exception. + * + * @return the targeted exception + * @see #getCause() + */ + public Throwable getTargetException() + { + return target; + } + + /** + * Returns the cause of this exception (which may be null). + * + * @return the cause + * @since 1.4 + */ + public Throwable getCause() + { + return target; + } +} diff --git a/libjava/classpath/java/lang/reflect/Member.java b/libjava/classpath/java/lang/reflect/Member.java new file mode 100644 index 0000000..9983b27 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/Member.java @@ -0,0 +1,100 @@ +/* java.lang.reflect.Member - common query methods in reflection + Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * Member is an interface that represents any member of a class (field or + * method) or a constructor. You can get information about the declaring + * class, name or modifiers of the member with this interface. + * + * @author John Keiser + * @author Per Bothner (bothner@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see Class + * @see Field + * @see Method + * @see Constructor + * @since 1.1 + * @status updated to 1.4 + */ +public interface Member +{ + /** + * Represents all members, whether public, private, protected or + * package-protected, but only which are declared in this class. + * Used in SecurityManager.checkMemberAccess() to determine the + * type of members to access. + * @see SecurityManager#checkMemberAccess() + */ + int DECLARED = 1; + + /** + * Represents public members only, but includes all inherited members. + * Used in SecurityManager.checkMemberAccess() to determine the type of + * members to access. + * @see SecurityManager#checkMemberAccess() + */ + int PUBLIC = 0; + + /** + * Gets the class that declared this member. This is not the class where + * this method was called, or even the class where this Member object + * came to life, but the class that declares the member this represents. + * + * @return the class that declared this member + */ + Class getDeclaringClass(); + + /** + * Gets the simple name of this member. This will be a valid Java + * identifier, with no qualification. + * + * @return the name of this member + */ + String getName(); + + /** + * Gets the modifiers this member uses. Use the <code>Modifier</code> + * class to interpret the values. + * + * @return an integer representing the modifiers to this Member + * @see Modifier + */ + int getModifiers(); +} diff --git a/libjava/classpath/java/lang/reflect/Modifier.java b/libjava/classpath/java/lang/reflect/Modifier.java new file mode 100644 index 0000000..efc88c9 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/Modifier.java @@ -0,0 +1,332 @@ +/* java.lang.reflect.Modifier + Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * Modifier is a helper class with static methods to determine whether an + * int returned from getModifiers() represents static, public, protected, + * native, final, etc... and provides an additional method to print + * out all of the modifiers in an int in order. + * <p> + * The methods in this class use the bitmask values in the VM spec to + * determine the modifiers of an int. This means that a VM must return a + * standard mask, conformant with the VM spec. I don't know if this is how + * Sun does it, but I'm willing to bet money that it is. + * + * @author John Keiser + * @author Tom Tromey (tromey@cygnus.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @see Member#getModifiers() + * @see Method#getModifiers() + * @see Field#getModifiers() + * @see Constructor#getModifiers() + * @see Class#getModifiers() + * @since 1.1 + */ +public class Modifier +{ + /** <STRONG>This constructor really shouldn't be here ... there are no + * instance methods or variables of this class, so instantiation is + * worthless. However, this function is in the 1.1 spec, so it is added + * for completeness.</STRONG> + */ + public Modifier() + { + } + + /** + * Public: accessible from any other class. + */ + public static final int PUBLIC = 0x0001; + + /** + * Private: accessible only from the same enclosing class. + */ + public static final int PRIVATE = 0x0002; + + /** + * Protected: accessible only to subclasses, or within the package. + */ + public static final int PROTECTED = 0x0004; + + /** + * Static:<br><ul> + * <li>Class: no enclosing instance for nested class.</li> + * <li>Field or Method: can be accessed or invoked without an + * instance of the declaring class.</li> + * </ul> + */ + public static final int STATIC = 0x0008; + + /** + * Final:<br><ul> + * <li>Class: no subclasses allowed.</li> + * <li>Field: cannot be changed.</li> + * <li>Method: cannot be overriden.</li> + * </ul> + */ + public static final int FINAL = 0x0010; + + /** + * Synchronized: Method: lock the class while calling this method. + */ + public static final int SYNCHRONIZED = 0x0020; + + /** + * Volatile: Field: cannot be cached. + */ + public static final int VOLATILE = 0x0040; + + /** + * Transient: Field: not serialized or deserialized. + */ + public static final int TRANSIENT = 0x0080; + + /** + * Native: Method: use JNI to call this method. + */ + public static final int NATIVE = 0x0100; + + /** + * Interface: Class: is an interface. + */ + public static final int INTERFACE = 0x0200; + + /** + * Abstract:<br><ul> + * <li>Class: may not be instantiated.</li> + * <li>Method: may not be called.</li> + * </ul> + */ + public static final int ABSTRACT = 0x0400; + + /** + * Strictfp: Method: expressions are FP-strict.<p> + * Also used as a modifier for classes, to mean that all initializers + * and constructors are FP-strict, but does not show up in + * Class.getModifiers. + */ + public static final int STRICT = 0x0800; + + + /** + * Super - treat invokespecial as polymorphic so that super.foo() works + * according to the JLS. This is a reuse of the synchronized constant + * to patch a hole in JDK 1.0. *shudder*. + */ + static final int SUPER = 0x0020; + + /** + * All the flags, only used by code in this package. + */ + static final int ALL_FLAGS = 0xfff; + + /** + * Check whether the given modifier is abstract. + * @param mod the modifier. + * @return <code>true</code> if abstract, <code>false</code> otherwise. + */ + public static boolean isAbstract(int mod) + { + return (mod & ABSTRACT) != 0; + } + + /** + * Check whether the given modifier is final. + * @param mod the modifier. + * @return <code>true</code> if final, <code>false</code> otherwise. + */ + public static boolean isFinal(int mod) + { + return (mod & FINAL) != 0; + } + + /** + * Check whether the given modifier is an interface. + * @param mod the modifier. + * @return <code>true</code> if an interface, <code>false</code> otherwise. + */ + public static boolean isInterface(int mod) + { + return (mod & INTERFACE) != 0; + } + + /** + * Check whether the given modifier is native. + * @param mod the modifier. + * @return <code>true</code> if native, <code>false</code> otherwise. + */ + public static boolean isNative(int mod) + { + return (mod & NATIVE) != 0; + } + + /** + * Check whether the given modifier is private. + * @param mod the modifier. + * @return <code>true</code> if private, <code>false</code> otherwise. + */ + public static boolean isPrivate(int mod) + { + return (mod & PRIVATE) != 0; + } + + /** + * Check whether the given modifier is protected. + * @param mod the modifier. + * @return <code>true</code> if protected, <code>false</code> otherwise. + */ + public static boolean isProtected(int mod) + { + return (mod & PROTECTED) != 0; + } + + /** + * Check whether the given modifier is public. + * @param mod the modifier. + * @return <code>true</code> if public, <code>false</code> otherwise. + */ + public static boolean isPublic(int mod) + { + return (mod & PUBLIC) != 0; + } + + /** + * Check whether the given modifier is static. + * @param mod the modifier. + * @return <code>true</code> if static, <code>false</code> otherwise. + */ + public static boolean isStatic(int mod) + { + return (mod & STATIC) != 0; + } + + /** + * Check whether the given modifier is strictfp. + * @param mod the modifier. + * @return <code>true</code> if strictfp, <code>false</code> otherwise. + */ + public static boolean isStrict(int mod) + { + return (mod & STRICT) != 0; + } + + /** + * Check whether the given modifier is synchronized. + * @param mod the modifier. + * @return <code>true</code> if synchronized, <code>false</code> otherwise. + */ + public static boolean isSynchronized(int mod) + { + return (mod & SYNCHRONIZED) != 0; + } + + /** + * Check whether the given modifier is transient. + * @param mod the modifier. + * @return <code>true</code> if transient, <code>false</code> otherwise. + */ + public static boolean isTransient(int mod) + { + return (mod & TRANSIENT) != 0; + } + + /** + * Check whether the given modifier is volatile. + * @param mod the modifier. + * @return <code>true</code> if volatile, <code>false</code> otherwise. + */ + public static boolean isVolatile(int mod) + { + return (mod & VOLATILE) != 0; + } + + /** + * Get a string representation of all the modifiers represented by the + * given int. The keywords are printed in this order: + * <code><public|protected|private> abstract static final transient + * volatile synchronized native strictfp interface</code>. + * + * @param mod the modifier. + * @return the String representing the modifiers. + */ + public static String toString(int mod) + { + return toString(mod, new StringBuffer()).toString(); + } + + /** + * Package helper method that can take a StringBuffer. + * @param mod the modifier + * @param r the StringBuffer to which the String representation is appended + * @return r, with information appended + */ + static StringBuffer toString(int mod, StringBuffer r) + { + if (isPublic(mod)) + r.append("public "); + if (isProtected(mod)) + r.append("protected "); + if (isPrivate(mod)) + r.append("private "); + if (isAbstract(mod)) + r.append("abstract "); + if (isStatic(mod)) + r.append("static "); + if (isFinal(mod)) + r.append("final "); + if (isTransient(mod)) + r.append("transient "); + if (isVolatile(mod)) + r.append("volatile "); + if (isSynchronized(mod)) + r.append("synchronized "); + if (isNative(mod)) + r.append("native "); + if (isStrict(mod)) + r.append("strictfp "); + if (isInterface(mod)) + r.append("interface "); + + // Trim trailing space. + if ((mod & ALL_FLAGS) != 0) + r.setLength(r.length() - 1); + return r; + } +} diff --git a/libjava/classpath/java/lang/reflect/ParameterizedType.java b/libjava/classpath/java/lang/reflect/ParameterizedType.java new file mode 100644 index 0000000..61081c9 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/ParameterizedType.java @@ -0,0 +1,122 @@ +/* ParameterizedType.java -- Represents parameterized types e.g. List<String> + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * <p> + * Represents a type which is parameterized over one or more other + * types. For example, <code>List<Integer></code> is a parameterized + * type, with <code>List</code> parameterized over the type + * <code>Integer</code>. + * </p> + * <p> + * Instances of this classes are created as needed, during reflection. + * On creating a parameterized type, <code>p</code>, the + * <code>GenericTypeDeclaration</code> corresponding to <code>p</code> + * is created and resolved. Each type argument of <code>p</code> + * is then created recursively; details of this process are availble + * in the documentation of <code>TypeVariable</code>. This creation + * process only happens once; repetition has no effect. + * </p> + * <p> + * Implementors of this interface must implement an appropriate + * <code>equals()</code> method. This method should equate any + * two instances of the implementing class that have the same + * <code>GenericTypeDeclaration</code> and <code>Type</code> + * parameters. + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @see GenericTypeDeclaration + * @see TypeVariable + * @since 1.5 + */ +public interface ParameterizedType + extends Type +{ + + /** + * <p> + * Returns an array of <code>Type</code> objects, which gives + * the parameters of this type. + * </p> + * <p> + * <strong>Note</code>: the returned array may be empty. This + * occurs if the supposed <code>ParameterizedType</code> is simply + * a normal type wrapped inside a parameterized type. + * </p> + * + * @return an array of <code>Type</code>s, representing the arguments + * of this type. + * @throws TypeNotPresentException if any of the types referred to by + * the parameters of this type do not actually exist. + * @throws MalformedParameterizedTypeException if any of the types + * refer to a type which can not be instantiated. + */ + Type[] getActualTypeArguments(); + + /** + * Returns the type of which this type is a member. For example, + * in <code>Top<String>.Bottom<Integer></code>, + * <code>Bottom<Integer></code> is a member of + * <code>Top<String></code>, and so the latter is returned + * by this method. Calling this method on top-level types (such as + * <code>Top<String></code>) returns null. + * + * @return the type which owns this type. + * @throws TypeNotPresentException if the owner type referred to by + * this type do not actually exist. + * @throws MalformedParameterizedTypeException if the owner type + * referred to by this type can not be instantiated. + */ + Type getOwnerType(); + + /** + * Returns a version of this type without parameters, which corresponds + * to the class or interface which declared the type. For example, + * the raw type corresponding to <code>List<Double></code> + * is <code>List</code>, which was declared by the <code>List</code> + * class. + * + * @return the raw variant of this type (i.e. the type without + * parameters). + */ + Type getRawType(); + +} diff --git a/libjava/classpath/java/lang/reflect/Proxy.java b/libjava/classpath/java/lang/reflect/Proxy.java new file mode 100644 index 0000000..dc1ac87 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/Proxy.java @@ -0,0 +1,1615 @@ +/* Proxy.java -- build a proxy class that implements reflected interfaces + Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +import gnu.classpath.Configuration; +import gnu.java.lang.reflect.TypeSignature; + +import java.io.Serializable; +import java.security.ProtectionDomain; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * This class allows you to dynamically create an instance of any (or + * even multiple) interfaces by reflection, and decide at runtime + * how that instance will behave by giving it an appropriate + * {@link InvocationHandler}. Proxy classes serialize specially, so + * that the proxy object can be reused between VMs, without requiring + * a persistent copy of the generated class code. + * + * <h3>Creation</h3> + * To create a proxy for some interface Foo: + * + * <pre> + * InvocationHandler handler = new MyInvocationHandler(...); + * Class proxyClass = Proxy.getProxyClass( + * Foo.class.getClassLoader(), new Class[] { Foo.class }); + * Foo f = (Foo) proxyClass + * .getConstructor(new Class[] { InvocationHandler.class }) + * .newInstance(new Object[] { handler }); + * </pre> + * or more simply: + * <pre> + * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), + * new Class[] { Foo.class }, + * handler); + * </pre> + * + * <h3>Dynamic Proxy Classes</h3> + * A dynamic proxy class is created at runtime, and has the following + * properties: + * <ul> + * <li>The class is <code>public</code> and <code>final</code>, + * and is neither <code>abstract</code> nor an inner class.</li> + * <li>The class has no canonical name (there is no formula you can use + * to determine or generate its name), but begins with the + * sequence "$Proxy". Abuse this knowledge at your own peril. + * (For now, '$' in user identifiers is legal, but it may not + * be that way forever. You weren't using '$' in your + * identifiers, were you?)</li> + * <li>The class extends Proxy, and explicitly implements all the + * interfaces specified at creation, in order (this is important + * for determining how method invocation is resolved). Note that + * a proxy class implements {@link Serializable}, at least + * implicitly, since Proxy does, but true serial behavior + * depends on using a serializable invocation handler as well.</li> + * <li>If at least one interface is non-public, the proxy class + * will be in the same package. Otherwise, the package is + * unspecified. This will work even if the package is sealed + * from user-generated classes, because Proxy classes are + * generated by a trusted source. Meanwhile, the proxy class + * belongs to the classloader you designated.</li> + * <li>Reflection works as expected: {@link Class#getInterfaces()} and + * {@link Class#getMethods()} work as they do on normal classes.</li> + * <li>The method {@link #isProxyClass()} will distinguish between + * true proxy classes and user extensions of this class. It only + * returns true for classes created by {@link #getProxyClass}.</li> + * <li>The {@link ProtectionDomain} of a proxy class is the same as for + * bootstrap classes, such as Object or Proxy, since it is created by + * a trusted source. This protection domain will typically be granted + * {@link java.security.AllPermission}. But this is not a security + * risk, since there are adequate permissions on reflection, which is + * the only way to create an instance of the proxy class.</li> + * <li>The proxy class contains a single constructor, which takes as + * its only argument an {@link InvocationHandler}. The method + * {@link #newInstance} is shorthand to do the necessary + * reflection.</li> + * </ul> + * + * <h3>Proxy Instances</h3> + * A proxy instance is an instance of a proxy class. It has the + * following properties, many of which follow from the properties of a + * proxy class listed above: + * <ul> + * <li>For a proxy class with Foo listed as one of its interfaces, the + * expression <code>proxy instanceof Foo</code> will return true, + * and the expression <code>(Foo) proxy</code> will succeed without + * a {@link ClassCastException}.</li> + * <li>Each proxy instance has an invocation handler, which can be + * accessed by {@link #getInvocationHandler(Object)}. Any call + * to an interface method, including {@link Object#hashcode()}, + * {@link Object#equals(Object)}, or {@link Object#toString()}, + * but excluding the public final methods of Object, will be + * encoded and passed to the {@link InvocationHandler#invoke} + * method of this handler.</li> + * </ul> + * + * <h3>Inheritance Issues</h3> + * A proxy class may inherit a method from more than one interface. + * The order in which interfaces are listed matters, because it determines + * which reflected {@link Method} object will be passed to the invocation + * handler. This means that the dynamically generated class cannot + * determine through which interface a method is being invoked.<p> + * + * In short, if a method is declared in Object (namely, hashCode, + * equals, or toString), then Object will be used; otherwise, the + * leftmost interface that inherits or declares a method will be used, + * even if it has a more permissive throws clause than what the proxy + * class is allowed. Thus, in the invocation handler, it is not always + * safe to assume that every class listed in the throws clause of the + * passed Method object can safely be thrown; fortunately, the Proxy + * instance is robust enough to wrap all illegal checked exceptions in + * {@link UndeclaredThrowableException}. + * + * @see InvocationHandler + * @see UndeclaredThrowableException + * @see Class + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.3 + * @status updated to 1.4, except for the use of ProtectionDomain + */ +public class Proxy implements Serializable +{ + /** + * Compatible with JDK 1.3+. + */ + private static final long serialVersionUID = -2222568056686623797L; + + /** + * Map of ProxyType to proxy class. + * + * @XXX This prevents proxy classes from being garbage collected. + * java.util.WeakHashSet is not appropriate, because that collects the + * keys, but we are interested in collecting the elements. + */ + private static final Map proxyClasses = new HashMap(); + + /** + * The invocation handler for this proxy instance. For Proxy, this + * field is unused, but it appears here in order to be serialized in all + * proxy classes. + * + * <em>NOTE</em>: This implementation is more secure for proxy classes + * than what Sun specifies. Sun does not require h to be immutable, but + * this means you could change h after the fact by reflection. However, + * by making h immutable, we may break non-proxy classes which extend + * Proxy. + * @serial invocation handler associated with this proxy instance + */ + protected InvocationHandler h; + + /** + * Constructs a new Proxy from a subclass (usually a proxy class), + * with the specified invocation handler. + * + * <em>NOTE</em>: This throws a NullPointerException if you attempt + * to create a proxy instance with a null handler using reflection. + * This behavior is not yet specified by Sun; see Sun Bug 4487672. + * + * @param handler the invocation handler, may be null if the subclass + * is not a proxy class + * @throws NullPointerException if handler is null and this is a proxy + * instance + */ + protected Proxy(InvocationHandler handler) + { + if (handler == null && isProxyClass(getClass())) + throw new NullPointerException("invalid handler"); + h = handler; + } + + /** + * Returns the proxy {@link Class} for the given ClassLoader and array + * of interfaces, dynamically generating it if necessary. + * + * <p>There are several restrictions on this method, the violation of + * which will result in an IllegalArgumentException or + * NullPointerException:</p> + * + * <ul> + * <li>All objects in `interfaces' must represent distinct interfaces. + * Classes, primitive types, null, and duplicates are forbidden.</li> + * <li>The interfaces must be visible in the specified ClassLoader. + * In other words, for each interface i: + * <code>Class.forName(i.getName(), false, loader) == i</code> + * must be true.</li> + * <li>All non-public interfaces (if any) must reside in the same + * package, or the proxy class would be non-instantiable. If + * there are no non-public interfaces, the package of the proxy + * class is unspecified.</li> + * <li>All interfaces must be compatible - if two declare a method + * with the same name and parameters, the return type must be + * the same and the throws clause of the proxy class will be + * the maximal subset of subclasses of the throws clauses for + * each method that is overridden.</li> + * <li>VM constraints limit the number of interfaces a proxy class + * may directly implement (however, the indirect inheritance + * of {@link Serializable} does not count against this limit). + * Even though most VMs can theoretically have 65535 + * superinterfaces for a class, the actual limit is smaller + * because a class's constant pool is limited to 65535 entries, + * and not all entries can be interfaces.</li> + * </ul> + * + * <p>Note that different orders of interfaces produce distinct classes.</p> + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param interfaces the array of interfaces the proxy class implements, + * may be empty, but not null + * @return the Class object of the proxy class + * @throws IllegalArgumentException if the constraints above were + * violated, except for problems with null + * @throws NullPointerException if `interfaces' is null or contains + * a null entry + */ + // synchronized so that we aren't trying to build the same class + // simultaneously in two threads + public static synchronized Class getProxyClass(ClassLoader loader, + Class[] interfaces) + { + interfaces = (Class[]) interfaces.clone(); + ProxyType pt = new ProxyType(loader, interfaces); + Class clazz = (Class) proxyClasses.get(pt); + if (clazz == null) + { + if (Configuration.HAVE_NATIVE_GET_PROXY_CLASS) + clazz = getProxyClass0(loader, interfaces); + else + { + ProxyData data = (Configuration.HAVE_NATIVE_GET_PROXY_DATA + ? getProxyData0(loader, interfaces) + : ProxyData.getProxyData(pt)); + + clazz = (Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS + ? generateProxyClass0(loader, data) + : new ClassFactory(data).generate(loader)); + } + + Object check = proxyClasses.put(pt, clazz); + // assert check == null && clazz != null; + if (check != null || clazz == null) + throw new InternalError(/*"Fatal flaw in getProxyClass"*/); + } + return clazz; + } + + /** + * Combines several methods into one. This is equivalent to: + * <pre> + * Proxy.getProxyClass(loader, interfaces) + * .getConstructor(new Class[] {InvocationHandler.class}) + * .newInstance(new Object[] {handler}); + * </pre> + * except that it will not fail with the normal problems caused + * by reflection. It can still fail for the same reasons documented + * in getProxyClass, or if handler is null. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param interfaces the array of interfaces the proxy class implements, + * may be empty, but not null + * @param handler the invocation handler, may not be null + * @return a proxy instance implementing the specified interfaces + * @throws IllegalArgumentException if the constraints for getProxyClass + * were violated, except for problems with null + * @throws NullPointerException if `interfaces' is null or contains + * a null entry, or if handler is null + * @see #getProxyClass(ClassLoader, Class[]) + * @see Class#getConstructor(Class[]) + * @see Constructor#newInstance(Object[]) + */ + public static Object newProxyInstance(ClassLoader loader, + Class[] interfaces, + InvocationHandler handler) + { + try + { + // getProxyClass() and Proxy() throw the necessary exceptions + return getProxyClass(loader, interfaces) + .getConstructor(new Class[] {InvocationHandler.class}) + .newInstance(new Object[] {handler}); + } + catch (RuntimeException e) + { + // Let IllegalArgumentException, NullPointerException escape. + // assert e instanceof IllegalArgumentException + // || e instanceof NullPointerException; + throw e; + } + catch (InvocationTargetException e) + { + // Let wrapped NullPointerException escape. + // assert e.getTargetException() instanceof NullPointerException + throw (NullPointerException) e.getCause(); + } + catch (Exception e) + { + // Covers InstantiationException, IllegalAccessException, + // NoSuchMethodException, none of which should be generated + // if the proxy class was generated correctly. + // assert false; + throw (Error) new InternalError("Unexpected: " + e).initCause(e); + } + } + + /** + * Returns true if and only if the Class object is a dynamically created + * proxy class (created by <code>getProxyClass</code> or by the + * syntactic sugar of <code>newProxyInstance</code>). + * + * <p>This check is secure (in other words, it is not simply + * <code>clazz.getSuperclass() == Proxy.class</code>), it will not + * be spoofed by non-proxy classes that extend Proxy. + * + * @param clazz the class to check, must not be null + * @return true if the class represents a proxy class + * @throws NullPointerException if clazz is null + */ + // This is synchronized on the off chance that another thread is + // trying to add a class to the map at the same time we read it. + public static synchronized boolean isProxyClass(Class clazz) + { + if (! Proxy.class.isAssignableFrom(clazz)) + return false; + // This is a linear search, even though we could do an O(1) search + // using new ProxyType(clazz.getClassLoader(), clazz.getInterfaces()). + return proxyClasses.containsValue(clazz); + } + + /** + * Returns the invocation handler for the given proxy instance.<p> + * + * <em>NOTE</em>: We guarantee a non-null result if successful, + * but Sun allows the creation of a proxy instance with a null + * handler. See the comments for {@link #Proxy(InvocationHandler)}. + * + * @param proxy the proxy instance, must not be null + * @return the invocation handler, guaranteed non-null. + * @throws IllegalArgumentException if + * <code>Proxy.isProxyClass(proxy.getClass())</code> returns false. + * @throws NullPointerException if proxy is null + */ + public static InvocationHandler getInvocationHandler(Object proxy) + { + if (! isProxyClass(proxy.getClass())) + throw new IllegalArgumentException("not a proxy instance"); + return ((Proxy) proxy).h; + } + + /** + * Optional native method to replace (and speed up) the pure Java + * implementation of getProxyClass. Only needed if + * Configuration.HAVE_NATIVE_GET_PROXY_CLASS is true, this does the + * work of both getProxyData0 and generateProxyClass0 with no + * intermediate form in Java. The native code may safely assume that + * this class must be created, and does not already exist. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param interfaces the interfaces the class will extend + * @return the generated proxy class + * @throws IllegalArgumentException if the constraints for getProxyClass + * were violated, except for problems with null + * @throws NullPointerException if `interfaces' is null or contains + * a null entry, or if handler is null + * @see Configuration#HAVE_NATIVE_GET_PROXY_CLASS + * @see #getProxyClass(ClassLoader, Class[]) + * @see #getProxyData0(ClassLoader, Class[]) + * @see #generateProxyClass0(ProxyData) + */ + private static native Class getProxyClass0(ClassLoader loader, + Class[] interfaces); + + /** + * Optional native method to replace (and speed up) the pure Java + * implementation of getProxyData. Only needed if + * Configuration.HAVE_NATIVE_GET_PROXY_DATA is true. The native code + * may safely assume that a new ProxyData object must be created which + * does not duplicate any existing ones. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param interfaces the interfaces the class will extend + * @return all data that is required to make this proxy class + * @throws IllegalArgumentException if the constraints for getProxyClass + * were violated, except for problems with null + * @throws NullPointerException if `interfaces' is null or contains + * a null entry, or if handler is null + * @see Configuration.HAVE_NATIVE_GET_PROXY_DATA + * @see #getProxyClass(ClassLoader, Class[]) + * @see #getProxyClass0(ClassLoader, Class[]) + * @see ProxyType#getProxyData() + */ + private static native ProxyData getProxyData0(ClassLoader loader, + Class[] interfaces); + + /** + * Optional native method to replace (and speed up) the pure Java + * implementation of generateProxyClass. Only needed if + * Configuration.HAVE_NATIVE_GENERATE_PROXY_CLASS is true. The native + * code may safely assume that a new Class must be created, and that + * the ProxyData object does not describe any existing class. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param data the struct of information to convert to a Class. This + * has already been verified for all problems except exceeding + * VM limitations + * @return the newly generated class + * @throws IllegalArgumentException if VM limitations are exceeded + * @see #getProxyClass(ClassLoader, Class[]) + * @see #getProxyClass0(ClassLoader, Class[]) + * @see ProxyData#generateProxyClass(ClassLoader) + */ + private static native Class generateProxyClass0(ClassLoader loader, + ProxyData data); + + /** + * Helper class for mapping unique ClassLoader and interface combinations + * to proxy classes. + * + * @author Eric Blake (ebb9@email.byu.edu) + */ + private static final class ProxyType + { + /** + * Store the class loader (may be null) + */ + final ClassLoader loader; + + /** + * Store the interfaces (never null, all elements are interfaces) + */ + final Class[] interfaces; + + /** + * Construct the helper object. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @param interfaces an array of interfaces + */ + ProxyType(ClassLoader loader, Class[] interfaces) + { + if (loader == null) + loader = ClassLoader.getSystemClassLoader(); + this.loader = loader; + this.interfaces = interfaces; + } + + /** + * Calculates the hash code. + * + * @return a combination of the classloader and interfaces hashcodes. + */ + public int hashCode() + { + //loader is always not null + int hash = loader.hashCode(); + for (int i = 0; i < interfaces.length; i++) + hash = hash * 31 + interfaces[i].hashCode(); + return hash; + } + + // A more comprehensive comparison of two arrays, + // ignore array element order, and + // ignore redundant elements + private static boolean sameTypes(Class arr1[], Class arr2[]) { + if (arr1.length == 1 && arr2.length == 1) { + return arr1[0] == arr2[0]; + } + + // total occurrance of elements of arr1 in arr2 + int total_occ_of_arr1_in_arr2 = 0; + each_type: + for (int i = arr1.length; --i >= 0; ) + { + Class t = arr1[i]; + for (int j = i; --j >= 0; ) + { + if (t == arr1[j]) + { //found duplicate type + continue each_type; + } + } + + // count c(a unique element of arr1)'s + // occurrences in arr2 + int occ_in_arr2 = 0; + for (int j = arr2.length; --j >= 0; ) + { + if (t == arr2[j]) + { + ++occ_in_arr2; + } + } + if (occ_in_arr2 == 0) + { // t does not occur in arr2 + return false; + } + + total_occ_of_arr1_in_arr2 += occ_in_arr2; + } + // now, each element of arr2 must have been visited + return total_occ_of_arr1_in_arr2 == arr2.length; + } + + /** + * Calculates equality. + * + * @param the object to compare to + * @return true if it is a ProxyType with same data + */ + public boolean equals(Object other) + { + ProxyType pt = (ProxyType) other; + if (loader != pt.loader || interfaces.length != pt.interfaces.length) + return false; + return sameTypes(interfaces, pt.interfaces); + } + } // class ProxyType + + /** + * Helper class which allows hashing of a method name and signature + * without worrying about return type, declaring class, or throws clause, + * and which reduces the maximally common throws clause between two methods + * + * @author Eric Blake (ebb9@email.byu.edu) + */ + private static final class ProxySignature + { + /** + * The core signatures which all Proxy instances handle. + */ + static final HashMap coreMethods = new HashMap(); + static + { + try + { + ProxySignature sig + = new ProxySignature(Object.class + .getMethod("equals", + new Class[] {Object.class})); + coreMethods.put(sig, sig); + sig = new ProxySignature(Object.class.getMethod("hashCode", null)); + coreMethods.put(sig, sig); + sig = new ProxySignature(Object.class.getMethod("toString", null)); + coreMethods.put(sig, sig); + } + catch (Exception e) + { + // assert false; + throw (Error) new InternalError("Unexpected: " + e).initCause(e); + } + } + + /** + * The underlying Method object, never null + */ + final Method method; + + /** + * The set of compatible thrown exceptions, may be empty + */ + final Set exceptions = new HashSet(); + + /** + * Construct a signature + * + * @param method the Method this signature is based on, never null + */ + ProxySignature(Method method) + { + this.method = method; + Class[] exc = method.getExceptionTypes(); + int i = exc.length; + while (--i >= 0) + { + // discard unchecked exceptions + if (Error.class.isAssignableFrom(exc[i]) + || RuntimeException.class.isAssignableFrom(exc[i])) + continue; + exceptions.add(exc[i]); + } + } + + /** + * Given a method, make sure it's return type is identical + * to this, and adjust this signature's throws clause appropriately + * + * @param other the signature to merge in + * @throws IllegalArgumentException if the return types conflict + */ + void checkCompatibility(ProxySignature other) + { + if (method.getReturnType() != other.method.getReturnType()) + throw new IllegalArgumentException("incompatible return types: " + + method + ", " + other.method); + + // if you can think of a more efficient way than this O(n^2) search, + // implement it! + int size1 = exceptions.size(); + int size2 = other.exceptions.size(); + boolean[] valid1 = new boolean[size1]; + boolean[] valid2 = new boolean[size2]; + Iterator itr = exceptions.iterator(); + int pos = size1; + while (--pos >= 0) + { + Class c1 = (Class) itr.next(); + Iterator itr2 = other.exceptions.iterator(); + int pos2 = size2; + while (--pos2 >= 0) + { + Class c2 = (Class) itr2.next(); + if (c2.isAssignableFrom(c1)) + valid1[pos] = true; + if (c1.isAssignableFrom(c2)) + valid2[pos2] = true; + } + } + pos = size1; + itr = exceptions.iterator(); + while (--pos >= 0) + { + itr.next(); + if (! valid1[pos]) + itr.remove(); + } + pos = size2; + itr = other.exceptions.iterator(); + while (--pos >= 0) + { + itr.next(); + if (! valid2[pos]) + itr.remove(); + } + exceptions.addAll(other.exceptions); + } + + /** + * Calculates the hash code. + * + * @return a combination of name and parameter types + */ + public int hashCode() + { + int hash = method.getName().hashCode(); + Class[] types = method.getParameterTypes(); + for (int i = 0; i < types.length; i++) + hash = hash * 31 + types[i].hashCode(); + return hash; + } + + /** + * Calculates equality. + * + * @param the object to compare to + * @return true if it is a ProxySignature with same data + */ + public boolean equals(Object other) + { + ProxySignature ps = (ProxySignature) other; + Class[] types1 = method.getParameterTypes(); + Class[] types2 = ps.method.getParameterTypes(); + if (! method.getName().equals(ps.method.getName()) + || types1.length != types2.length) + return false; + int i = types1.length; + while (--i >= 0) + if (types1[i] != types2[i]) + return false; + return true; + } + } // class ProxySignature + + /** + * A flat representation of all data needed to generate bytecode/instantiate + * a proxy class. This is basically a struct. + * + * @author Eric Blake (ebb9@email.byu.edu) + */ + private static final class ProxyData + { + /** + * The package this class is in <b>including the trailing dot</b> + * or an empty string for the unnamed (aka default) package. + */ + String pack; + + /** + * The interfaces this class implements. Non-null, but possibly empty. + */ + Class[] interfaces; + + /** + * The Method objects this class must pass as the second argument to + * invoke (also useful for determining what methods this class has). + * Non-null, non-empty (includes at least Object.hashCode, Object.equals, + * and Object.toString). + */ + Method[] methods; + + /** + * The exceptions that do not need to be wrapped in + * UndeclaredThrowableException. exceptions[i] is the same as, or a + * subset of subclasses, of methods[i].getExceptionTypes(), depending on + * compatible throws clauses with multiple inheritance. It is unspecified + * if these lists include or exclude subclasses of Error and + * RuntimeException, but excluding them is harmless and generates a + * smaller class. + */ + Class[][] exceptions; + + /** + * For unique id's + */ + private static int count; + + /** + * The id of this proxy class + */ + final int id = count++; + + /** + * Construct a ProxyData with uninitialized data members. + */ + ProxyData() + { + } + + /** + * Return the name of a package (including the trailing dot) + * given the name of a class. + * Returns an empty string if no package. We use this in preference to + * using Class.getPackage() to avoid problems with ClassLoaders + * that don't set the package. + */ + private static String getPackage(Class k) + { + String name = k.getName(); + int idx = name.lastIndexOf('.'); + return name.substring(0, idx + 1); + } + + /** + * Verifies that the arguments are legal, and sets up remaining data + * This should only be called when a class must be generated, as + * it is expensive. + * + * @param pt the ProxyType to convert to ProxyData + * @return the flattened, verified ProxyData structure for use in + * class generation + * @throws IllegalArgumentException if `interfaces' contains + * non-interfaces or incompatible combinations, and verify is true + * @throws NullPointerException if interfaces is null or contains null + */ + static ProxyData getProxyData(ProxyType pt) + { + Map method_set = (Map) ProxySignature.coreMethods.clone(); + boolean in_package = false; // true if we encounter non-public interface + + ProxyData data = new ProxyData(); + data.interfaces = pt.interfaces; + + // if interfaces is too large, we croak later on when the constant + // pool overflows + int i = data.interfaces.length; + while (--i >= 0) + { + Class inter = data.interfaces[i]; + if (! inter.isInterface()) + throw new IllegalArgumentException("not an interface: " + inter); + try + { + if (Class.forName(inter.getName(), false, pt.loader) != inter) + throw new IllegalArgumentException("not accessible in " + + "classloader: " + inter); + } + catch (ClassNotFoundException e) + { + throw new IllegalArgumentException("not accessible in " + + "classloader: " + inter); + } + if (! Modifier.isPublic(inter.getModifiers())) + if (in_package) + { + String p = getPackage(inter); + if (! data.pack.equals(p)) + throw new IllegalArgumentException("non-public interfaces " + + "from different " + + "packages"); + } + else + { + in_package = true; + data.pack = getPackage(inter); + } + for (int j = i-1; j >= 0; j--) + if (data.interfaces[j] == inter) + throw new IllegalArgumentException("duplicate interface: " + + inter); + Method[] methods = inter.getMethods(); + int j = methods.length; + while (--j >= 0) + { + ProxySignature sig = new ProxySignature(methods[j]); + ProxySignature old = (ProxySignature) method_set.put(sig, sig); + if (old != null) + sig.checkCompatibility(old); + } + } + + i = method_set.size(); + data.methods = new Method[i]; + data.exceptions = new Class[i][]; + Iterator itr = method_set.values().iterator(); + while (--i >= 0) + { + ProxySignature sig = (ProxySignature) itr.next(); + data.methods[i] = sig.method; + data.exceptions[i] = (Class[]) sig.exceptions + .toArray(new Class[sig.exceptions.size()]); + } + return data; + } + } // class ProxyData + + /** + * Does all the work of building a class. By making this a nested class, + * this code is not loaded in memory if the VM has a native + * implementation instead. + * + * @author Eric Blake (ebb9@email.byu.edu) + */ + private static final class ClassFactory + { + /** Constants for assisting the compilation */ + private static final byte POOL = 0; + private static final byte FIELD = 1; + private static final byte METHOD = 2; + private static final byte INTERFACE = 3; + private static final String CTOR_SIG + = "(Ljava/lang/reflect/InvocationHandler;)V"; + private static final String INVOKE_SIG = "(Ljava/lang/Object;" + + "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;"; + + /** Bytecodes for insertion in the class definition byte[] */ + private static final char ACONST_NULL = 1; + private static final char ICONST_0 = 3; + private static final char BIPUSH = 16; + private static final char SIPUSH = 17; + private static final char ILOAD = 21; + private static final char ILOAD_0 = 26; + private static final char ALOAD_0 = 42; + private static final char ALOAD_1 = 43; + private static final char AALOAD = 50; + private static final char AASTORE = 83; + private static final char DUP = 89; + private static final char DUP_X1 = 90; + private static final char SWAP = 95; + private static final char IRETURN = 172; + private static final char LRETURN = 173; + private static final char FRETURN = 174; + private static final char DRETURN = 175; + private static final char ARETURN = 176; + private static final char RETURN = 177; + private static final char GETSTATIC = 178; + private static final char GETFIELD = 180; + private static final char INVOKEVIRTUAL = 182; + private static final char INVOKESPECIAL = 183; + private static final char INVOKESTATIC = 184; + private static final char INVOKEINTERFACE = 185; + private static final char NEW = 187; + private static final char ANEWARRAY = 189; + private static final char ATHROW = 191; + private static final char CHECKCAST = 192; + + // Implementation note: we use StringBuffers to hold the byte data, since + // they automatically grow. However, we only use the low 8 bits of + // every char in the array, so we are using twice the necessary memory + // for the ease StringBuffer provides. + + /** The constant pool. */ + private final StringBuffer pool = new StringBuffer(); + /** The rest of the class data. */ + private final StringBuffer stream = new StringBuffer(); + + /** Map of strings to byte sequences, to minimize size of pool. */ + private final Map poolEntries = new HashMap(); + + /** The VM name of this proxy class. */ + private final String qualName; + + /** + * The Method objects the proxy class refers to when calling the + * invocation handler. + */ + private final Method[] methods; + + /** + * Initializes the buffers with the bytecode contents for a proxy class. + * + * @param data the remainder of the class data + * @throws IllegalArgumentException if anything else goes wrong this + * late in the game; as far as I can tell, this will only happen + * if the constant pool overflows, which is possible even when + * the user doesn't exceed the 65535 interface limit + */ + ClassFactory(ProxyData data) + { + methods = data.methods; + + // magic = 0xcafebabe + // minor_version = 0 + // major_version = 46 + // constant_pool_count: place-holder for now + pool.append("\u00ca\u00fe\u00ba\u00be\0\0\0\56\0\0"); + // constant_pool[], filled in as we go + + // access_flags + putU2(Modifier.SUPER | Modifier.FINAL | Modifier.PUBLIC); + // this_class + qualName = (data.pack + "$Proxy" + data.id); + putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false))); + // super_class + putU2(classInfo("java/lang/reflect/Proxy")); + + // interfaces_count + putU2(data.interfaces.length); + // interfaces[] + for (int i = 0; i < data.interfaces.length; i++) + putU2(classInfo(data.interfaces[i])); + + // Recall that Proxy classes serialize specially, so we do not need + // to worry about a <clinit> method for this field. Instead, we + // just assign it by reflection after the class is successfully loaded. + // fields_count - private static Method[] m; + putU2(1); + // fields[] + // m.access_flags + putU2(Modifier.PRIVATE | Modifier.STATIC); + // m.name_index + putU2(utf8Info("m")); + // m.descriptor_index + putU2(utf8Info("[Ljava/lang/reflect/Method;")); + // m.attributes_count + putU2(0); + // m.attributes[] + + // methods_count - # handler methods, plus <init> + putU2(methods.length + 1); + // methods[] + // <init>.access_flags + putU2(Modifier.PUBLIC); + // <init>.name_index + putU2(utf8Info("<init>")); + // <init>.descriptor_index + putU2(utf8Info(CTOR_SIG)); + // <init>.attributes_count - only Code is needed + putU2(1); + // <init>.Code.attribute_name_index + putU2(utf8Info("Code")); + // <init>.Code.attribute_length = 18 + // <init>.Code.info: + // $Proxynn(InvocationHandler h) { super(h); } + // <init>.Code.max_stack = 2 + // <init>.Code.max_locals = 2 + // <init>.Code.code_length = 6 + // <init>.Code.code[] + stream.append("\0\0\0\22\0\2\0\2\0\0\0\6" + ALOAD_0 + ALOAD_1 + + INVOKESPECIAL); + putU2(refInfo(METHOD, "java/lang/reflect/Proxy", "<init>", CTOR_SIG)); + // <init>.Code.exception_table_length = 0 + // <init>.Code.exception_table[] + // <init>.Code.attributes_count = 0 + // <init>.Code.attributes[] + stream.append(RETURN + "\0\0\0\0"); + + for (int i = methods.length - 1; i >= 0; i--) + emitMethod(i, data.exceptions[i]); + + // attributes_count + putU2(0); + // attributes[] - empty; omit SourceFile attribute + // XXX should we mark this with a Synthetic attribute? + } + + /** + * Produce the bytecode for a single method. + * + * @param i the index of the method we are building + * @param e the exceptions possible for the method + */ + private void emitMethod(int i, Class[] e) + { + // First, we precalculate the method length and other information. + + Method m = methods[i]; + Class[] paramtypes = m.getParameterTypes(); + int wrap_overhead = 0; // max words taken by wrapped primitive + int param_count = 1; // 1 for this + int code_length = 16; // aload_0, getfield, aload_0, getstatic, const, + // aaload, const/aconst_null, invokeinterface + if (i > 5) + { + if (i > Byte.MAX_VALUE) + code_length += 2; // sipush + else + code_length++; // bipush + } + if (paramtypes.length > 0) + { + code_length += 3; // anewarray + if (paramtypes.length > Byte.MAX_VALUE) + code_length += 2; // sipush + else if (paramtypes.length > 5) + code_length++; // bipush + for (int j = 0; j < paramtypes.length; j++) + { + code_length += 4; // dup, const, load, store + Class type = paramtypes[j]; + if (j > 5) + { + if (j > Byte.MAX_VALUE) + code_length += 2; // sipush + else + code_length++; // bipush + } + if (param_count >= 4) + code_length++; // 2-byte load + param_count++; + if (type.isPrimitive()) + { + code_length += 7; // new, dup, invokespecial + if (type == long.class || type == double.class) + { + wrap_overhead = 3; + param_count++; + } + else if (wrap_overhead < 2) + wrap_overhead = 2; + } + } + } + int end_pc = code_length; + Class ret_type = m.getReturnType(); + if (ret_type == void.class) + code_length++; // return + else if (ret_type.isPrimitive()) + code_length += 7; // cast, invokevirtual, return + else + code_length += 4; // cast, return + int exception_count = 0; + boolean throws_throwable = false; + for (int j = 0; j < e.length; j++) + if (e[j] == Throwable.class) + { + throws_throwable = true; + break; + } + if (! throws_throwable) + { + exception_count = e.length + 3; // Throwable, Error, RuntimeException + code_length += 9; // new, dup_x1, swap, invokespecial, athrow + } + int handler_pc = code_length - 1; + StringBuffer signature = new StringBuffer("("); + for (int j = 0; j < paramtypes.length; j++) + signature.append(TypeSignature.getEncodingOfClass(paramtypes[j])); + signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type)); + + // Now we have enough information to emit the method. + + // handler.access_flags + putU2(Modifier.PUBLIC | Modifier.FINAL); + // handler.name_index + putU2(utf8Info(m.getName())); + // handler.descriptor_index + putU2(utf8Info(signature.toString())); + // handler.attributes_count - Code is necessary, Exceptions possible + putU2(e.length > 0 ? 2 : 1); + + // handler.Code.info: + // type name(args) { + // try { + // return (type) h.invoke(this, methods[i], new Object[] {args}); + // } catch (<declared Exceptions> e) { + // throw e; + // } catch (Throwable t) { + // throw new UndeclaredThrowableException(t); + // } + // } + // Special cases: + // if arg_n is primitive, wrap it + // if method throws Throwable, try-catch is not needed + // if method returns void, return statement not needed + // if method returns primitive, unwrap it + // save space by sharing code for all the declared handlers + + // handler.Code.attribute_name_index + putU2(utf8Info("Code")); + // handler.Code.attribute_length + putU4(12 + code_length + 8 * exception_count); + // handler.Code.max_stack + putU2(param_count == 1 ? 4 : 7 + wrap_overhead); + // handler.Code.max_locals + putU2(param_count); + // handler.Code.code_length + putU4(code_length); + // handler.Code.code[] + putU1(ALOAD_0); + putU1(GETFIELD); + putU2(refInfo(FIELD, "java/lang/reflect/Proxy", "h", + "Ljava/lang/reflect/InvocationHandler;")); + putU1(ALOAD_0); + putU1(GETSTATIC); + putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false), + "m", "[Ljava/lang/reflect/Method;")); + putConst(i); + putU1(AALOAD); + if (paramtypes.length > 0) + { + putConst(paramtypes.length); + putU1(ANEWARRAY); + putU2(classInfo("java/lang/Object")); + param_count = 1; + for (int j = 0; j < paramtypes.length; j++, param_count++) + { + putU1(DUP); + putConst(j); + if (paramtypes[j].isPrimitive()) + { + putU1(NEW); + putU2(classInfo(wrapper(paramtypes[j]))); + putU1(DUP); + } + putLoad(param_count, paramtypes[j]); + if (paramtypes[j].isPrimitive()) + { + putU1(INVOKESPECIAL); + putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>", + '(' + (TypeSignature + .getEncodingOfClass(paramtypes[j]) + + ")V"))); + if (paramtypes[j] == long.class + || paramtypes[j] == double.class) + param_count++; + } + putU1(AASTORE); + } + } + else + putU1(ACONST_NULL); + putU1(INVOKEINTERFACE); + putU2(refInfo(INTERFACE, "java/lang/reflect/InvocationHandler", + "invoke", INVOKE_SIG)); + putU1(4); // InvocationHandler, this, Method, Object[] + putU1(0); + if (ret_type == void.class) + putU1(RETURN); + else if (ret_type.isPrimitive()) + { + putU1(CHECKCAST); + putU2(classInfo(wrapper(ret_type))); + putU1(INVOKEVIRTUAL); + putU2(refInfo(METHOD, wrapper(ret_type), + ret_type.getName() + "Value", + "()" + TypeSignature.getEncodingOfClass(ret_type))); + if (ret_type == long.class) + putU1(LRETURN); + else if (ret_type == float.class) + putU1(FRETURN); + else if (ret_type == double.class) + putU1(DRETURN); + else + putU1(IRETURN); + } + else + { + putU1(CHECKCAST); + putU2(classInfo(ret_type)); + putU1(ARETURN); + } + if (! throws_throwable) + { + putU1(NEW); + putU2(classInfo("java/lang/reflect/UndeclaredThrowableException")); + putU1(DUP_X1); + putU1(SWAP); + putU1(INVOKESPECIAL); + putU2(refInfo(METHOD, + "java/lang/reflect/UndeclaredThrowableException", + "<init>", "(Ljava/lang/Throwable;)V")); + putU1(ATHROW); + } + + // handler.Code.exception_table_length + putU2(exception_count); + // handler.Code.exception_table[] + if (! throws_throwable) + { + // handler.Code.exception_table.start_pc + putU2(0); + // handler.Code.exception_table.end_pc + putU2(end_pc); + // handler.Code.exception_table.handler_pc + putU2(handler_pc); + // handler.Code.exception_table.catch_type + putU2(classInfo("java/lang/Error")); + // handler.Code.exception_table.start_pc + putU2(0); + // handler.Code.exception_table.end_pc + putU2(end_pc); + // handler.Code.exception_table.handler_pc + putU2(handler_pc); + // handler.Code.exception_table.catch_type + putU2(classInfo("java/lang/RuntimeException")); + for (int j = 0; j < e.length; j++) + { + // handler.Code.exception_table.start_pc + putU2(0); + // handler.Code.exception_table.end_pc + putU2(end_pc); + // handler.Code.exception_table.handler_pc + putU2(handler_pc); + // handler.Code.exception_table.catch_type + putU2(classInfo(e[j])); + } + // handler.Code.exception_table.start_pc + putU2(0); + // handler.Code.exception_table.end_pc + putU2(end_pc); + // handler.Code.exception_table.handler_pc - + // -8 for undeclared handler, which falls thru to normal one + putU2(handler_pc - 8); + // handler.Code.exception_table.catch_type + putU2(0); + } + // handler.Code.attributes_count + putU2(0); + // handler.Code.attributes[] + + if (e.length > 0) + { + // handler.Exceptions.attribute_name_index + putU2(utf8Info("Exceptions")); + // handler.Exceptions.attribute_length + putU4(2 * e.length + 2); + // handler.Exceptions.number_of_exceptions + putU2(e.length); + // handler.Exceptions.exception_index_table[] + for (int j = 0; j < e.length; j++) + putU2(classInfo(e[j])); + } + } + + /** + * Creates the Class object that corresponds to the bytecode buffers + * built when this object was constructed. + * + * @param loader the class loader to define the proxy class in; null + * implies the bootstrap class loader + * @return the proxy class Class object + */ + Class generate(ClassLoader loader) + { + byte[] bytecode = new byte[pool.length() + stream.length()]; + // More efficient to bypass calling charAt() repetitively. + char[] c = pool.toString().toCharArray(); + int i = c.length; + while (--i >= 0) + bytecode[i] = (byte) c[i]; + c = stream.toString().toCharArray(); + i = c.length; + int j = bytecode.length; + while (i > 0) + bytecode[--j] = (byte) c[--i]; + + // Patch the constant pool size, which we left at 0 earlier. + int count = poolEntries.size() + 1; + bytecode[8] = (byte) (count >> 8); + bytecode[9] = (byte) count; + + try + { + Class vmClassLoader = Class.forName("java.lang.VMClassLoader"); + Class[] types = {ClassLoader.class, String.class, + byte[].class, int.class, int.class, + ProtectionDomain.class }; + Method m = vmClassLoader.getDeclaredMethod("defineClass", types); + // We can bypass the security check of setAccessible(true), since + // we're in the same package. + m.flag = true; + + Object[] args = {loader, qualName, bytecode, new Integer(0), + new Integer(bytecode.length), + Object.class.getProtectionDomain() }; + Class clazz = (Class) m.invoke(null, args); + + // Finally, initialize the m field of the proxy class, before + // returning it. + Field f = clazz.getDeclaredField("m"); + f.flag = true; + // we can share the array, because it is not publicized + f.set(null, methods); + + return clazz; + } + catch (Exception e) + { + // assert false; + throw (Error) new InternalError("Unexpected: " + e).initCause(e); + } + } + + /** + * Put a single byte on the stream. + * + * @param i the information to add (only lowest 8 bits are used) + */ + private void putU1(int i) + { + stream.append((char) i); + } + + /** + * Put two bytes on the stream. + * + * @param i the information to add (only lowest 16 bits are used) + */ + private void putU2(int i) + { + stream.append((char) (i >> 8)).append((char) i); + } + + /** + * Put four bytes on the stream. + * + * @param i the information to add (treated as unsigned) + */ + private void putU4(int i) + { + stream.append((char) (i >> 24)).append((char) (i >> 16)); + stream.append((char) (i >> 8)).append((char) i); + } + + /** + * Put bytecode to load a constant integer on the stream. This only + * needs to work for values less than Short.MAX_VALUE. + * + * @param i the int to add + */ + private void putConst(int i) + { + if (i >= -1 && i <= 5) + putU1(ICONST_0 + i); + else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) + { + putU1(BIPUSH); + putU1(i); + } + else + { + putU1(SIPUSH); + putU2(i); + } + } + + /** + * Put bytecode to load a given local variable on the stream. + * + * @param i the slot to load + * @param type the base type of the load + */ + private void putLoad(int i, Class type) + { + int offset = 0; + if (type == long.class) + offset = 1; + else if (type == float.class) + offset = 2; + else if (type == double.class) + offset = 3; + else if (! type.isPrimitive()) + offset = 4; + if (i < 4) + putU1(ILOAD_0 + 4 * offset + i); + else + { + putU1(ILOAD + offset); + putU1(i); + } + } + + /** + * Given a primitive type, return its wrapper class name. + * + * @param clazz the primitive type (but not void.class) + * @return the internal form of the wrapper class name + */ + private String wrapper(Class clazz) + { + if (clazz == boolean.class) + return "java/lang/Boolean"; + if (clazz == byte.class) + return "java/lang/Byte"; + if (clazz == short.class) + return "java/lang/Short"; + if (clazz == char.class) + return "java/lang/Character"; + if (clazz == int.class) + return "java/lang/Integer"; + if (clazz == long.class) + return "java/lang/Long"; + if (clazz == float.class) + return "java/lang/Float"; + if (clazz == double.class) + return "java/lang/Double"; + // assert false; + return null; + } + + /** + * Returns the entry of this String in the Constant pool, adding it + * if necessary. + * + * @param str the String to resolve + * @return the index of the String in the constant pool + */ + private char utf8Info(String str) + { + String utf8 = toUtf8(str); + int len = utf8.length(); + return poolIndex("\1" + (char) (len >> 8) + (char) (len & 0xff) + utf8); + } + + /** + * Returns the entry of the appropriate class info structure in the + * Constant pool, adding it if necessary. + * + * @param name the class name, in internal form + * @return the index of the ClassInfo in the constant pool + */ + private char classInfo(String name) + { + char index = utf8Info(name); + char[] c = {7, (char) (index >> 8), (char) (index & 0xff)}; + return poolIndex(new String(c)); + } + + /** + * Returns the entry of the appropriate class info structure in the + * Constant pool, adding it if necessary. + * + * @param clazz the class type + * @return the index of the ClassInfo in the constant pool + */ + private char classInfo(Class clazz) + { + return classInfo(TypeSignature.getEncodingOfClass(clazz.getName(), + false)); + } + + /** + * Returns the entry of the appropriate fieldref, methodref, or + * interfacemethodref info structure in the Constant pool, adding it + * if necessary. + * + * @param structure FIELD, METHOD, or INTERFACE + * @param clazz the class name, in internal form + * @param name the simple reference name + * @param type the type of the reference + * @return the index of the appropriate Info structure in the constant pool + */ + private char refInfo(byte structure, String clazz, String name, + String type) + { + char cindex = classInfo(clazz); + char ntindex = nameAndTypeInfo(name, type); + // relies on FIELD == 1, METHOD == 2, INTERFACE == 3 + char[] c = {(char) (structure + 8), + (char) (cindex >> 8), (char) (cindex & 0xff), + (char) (ntindex >> 8), (char) (ntindex & 0xff)}; + return poolIndex(new String(c)); + } + + /** + * Returns the entry of the appropriate nameAndTyperef info structure + * in the Constant pool, adding it if necessary. + * + * @param name the simple name + * @param type the reference type + * @return the index of the NameAndTypeInfo structure in the constant pool + */ + private char nameAndTypeInfo(String name, String type) + { + char nindex = utf8Info(name); + char tindex = utf8Info(type); + char[] c = {12, (char) (nindex >> 8), (char) (nindex & 0xff), + (char) (tindex >> 8), (char) (tindex & 0xff)}; + return poolIndex(new String(c)); + } + + /** + * Converts a regular string to a UTF8 string, where the upper byte + * of every char is 0, and '\\u0000' is not in the string. This is + * basically to use a String as a fancy byte[], and while it is less + * efficient in memory use, it is easier for hashing. + * + * @param str the original, in straight unicode + * @return a modified string, in UTF8 format in the low bytes + */ + private String toUtf8(String str) + { + final char[] ca = str.toCharArray(); + final int len = ca.length; + + // Avoid object creation, if str is already fits UTF8. + int i; + for (i = 0; i < len; i++) + if (ca[i] == 0 || ca[i] > '\u007f') + break; + if (i == len) + return str; + + final StringBuffer sb = new StringBuffer(str); + sb.setLength(i); + for ( ; i < len; i++) + { + final char c = ca[i]; + if (c > 0 && c <= '\u007f') + sb.append(c); + else if (c <= '\u07ff') // includes '\0' + { + sb.append((char) (0xc0 | (c >> 6))); + sb.append((char) (0x80 | (c & 0x6f))); + } + else + { + sb.append((char) (0xe0 | (c >> 12))); + sb.append((char) (0x80 | ((c >> 6) & 0x6f))); + sb.append((char) (0x80 | (c & 0x6f))); + } + } + return sb.toString(); + } + + /** + * Returns the location of a byte sequence (conveniently wrapped in + * a String with all characters between \u0001 and \u00ff inclusive) + * in the constant pool, adding it if necessary. + * + * @param sequence the byte sequence to look for + * @return the index of the sequence + * @throws IllegalArgumentException if this would make the constant + * pool overflow + */ + private char poolIndex(String sequence) + { + Integer i = (Integer) poolEntries.get(sequence); + if (i == null) + { + // pool starts at index 1 + int size = poolEntries.size() + 1; + if (size >= 65535) + throw new IllegalArgumentException("exceeds VM limitations"); + i = new Integer(size); + poolEntries.put(sequence, i); + pool.append(sequence); + } + return (char) i.intValue(); + } + } // class ClassFactory +} diff --git a/libjava/classpath/java/lang/reflect/README b/libjava/classpath/java/lang/reflect/README new file mode 100644 index 0000000..99ea224 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/README @@ -0,0 +1,4 @@ +README for java.lang.reflect: + +java.lang.reflect is now mostly empty. We've carved out the classes that have +to do with the VM and put them into the VM interface. diff --git a/libjava/classpath/java/lang/reflect/ReflectPermission.java b/libjava/classpath/java/lang/reflect/ReflectPermission.java new file mode 100644 index 0000000..56eccf8 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/ReflectPermission.java @@ -0,0 +1,102 @@ +/* ReflectPermission.java - named permission for reflaction + Copyright (C) 2000, 2001, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package java.lang.reflect; + +import java.security.BasicPermission; + +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + */ + +/** + * This class implements permissions for reflection. This is a named + * permission, and the only defined name is suppressAccessChecks, which + * allows suppression of normal Java objects when using reflection. + * + * <table> + * <tr> + * <th>Permission Target Name</th> + * <th>What Permission Allows</th> + * <th>Risk of Allowing Permission</th> + * </tr> + * <tr> + * <td><code>suppressAccessChecks</code></td> + * <td>Ability to access fields, invoke methods, and construct objects + * via reflection, including non-public members in contexts where + * such access is not legal at compile-time.</td> + * <td>This is dangerous. It exposes possibly confidential information, + * and malicious code could interfere with the internals of the Virtual + * Machine by corrupting private data.</td> + * </tr> + * </table> + * + * @author Tom Tromey (tromey@redhat.com) + * @author Eric Blake (ebb9@email.byu.edu) + * @since 1.2 + * @status updated to 1.4 + */ +public final class ReflectPermission + extends BasicPermission +{ + /** + * Compatible with JDK 1.2. + */ + private static final long serialVersionUID = 7412737110241507485L; + + /** + * Construct a ReflectPermission with the given name. + * + * @param name The permission name + */ + public ReflectPermission(String name) + { + super(name); + } + + /** + * Construct a ReflectPermission with the given name. + * + * @param name The permission name + * @param actions The actions; this is ignored and should be null + */ + public ReflectPermission(String name, String actions) + { + super(name, actions); + } +} diff --git a/libjava/classpath/java/lang/reflect/TODO b/libjava/classpath/java/lang/reflect/TODO new file mode 100755 index 0000000..6514c76 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/TODO @@ -0,0 +1,4 @@ +TODO for java.lang.reflect Java side + +- more tests! +- Java 2 support (waiting on java.lang Java 2 support) diff --git a/libjava/classpath/java/lang/reflect/Type.java b/libjava/classpath/java/lang/reflect/Type.java new file mode 100644 index 0000000..c9ea5bf --- /dev/null +++ b/libjava/classpath/java/lang/reflect/Type.java @@ -0,0 +1,55 @@ +/* Type.java - Superinterface for all types. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * Represents any <code>Type</code> within the Java programming + * language. This may be a primitive type (e.g. <code>int</code>, + * an array type (e.g. <code>double[]>/code>), a raw type + * (e.g. <code>Calendar</code>), a parameterized type + * (e.g. <code>List<Boolean></code>, or a type + * variable (e.g. <code>T extends String</code>). + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public interface Type +{ +} diff --git a/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java b/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java new file mode 100644 index 0000000..6d5a800 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/UndeclaredThrowableException.java @@ -0,0 +1,128 @@ +/* UndeclaredThrowableException.java -- wraps an undeclared checked exception + thrown by a Proxy invocation handler + Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * This exception class is thrown by a {@link Proxy} instance if + * the {@link InvocationHandler#invoke(Object, Method, Object[]) invoke} + * method of that instance's InvocationHandler attempts to throw an + * exception that not declared by the throws clauses of all of the + * interface methods that the proxy instance is implementing. + * + * <p>When thrown by Proxy, this class will always wrap a checked + * exception, never {@link Error} or {@link RuntimeException}, + * which are unchecked. + * + * @author Eric Blake (ebb9@email.byu.edu) + * @see Proxy + * @see InvocationHandler + * @since 1.3 + * @status updated to 1.4 + */ +public class UndeclaredThrowableException extends RuntimeException +{ + /** + * Compatible with JDK 1.3+. + */ + private static final long serialVersionUID = 330127114055056639L; + + /** + * The immutable exception that this wraps. This field is redundant + * with {@link Throwable#cause}, but is necessary for serial compatibility. + * + * @serial the chained exception + */ + private final Throwable undeclaredThrowable; + + /** + * Wraps the given checked exception into a RuntimeException, with no + * detail message. {@link Throwable#initCause(Throwable)} will fail + * on this instance. + * + * @param cause the undeclared throwable that caused this exception, + * may be null + */ + public UndeclaredThrowableException(Throwable cause) + { + this(cause, null); + } + + /** + * Wraps the given checked exception into a RuntimeException, with the + * specified detail message. {@link Throwable#initCause(Throwable)} will + * fail on this instance. + * + * @param cause the undeclared throwable that caused this exception, + * may be null + * @param message the message, may be null + */ + public UndeclaredThrowableException(Throwable cause, String message) + { + super(message, cause); + undeclaredThrowable = cause; + } + + /** + * Returns the cause of this exception. If this exception was created + * by a {@link Proxy} instance, it will be a non-null checked + * exception. This method pre-dates exception chaining, and is now + * simply a longer way to call <code>getCause()</code>. + * + * @return the cause of this exception, may be null + * @see #getCause() + */ + public Throwable getUndeclaredThrowable() + { + return undeclaredThrowable; + } + + /** + * Returns the cause of this exception. If this exception was created + * by a {@link Proxy} instance, it will be a non-null checked + * exception. + * + * @return the cause of this exception, may be null + * @since 1.4 + */ + public Throwable getCause() + { + return undeclaredThrowable; + } +} diff --git a/libjava/classpath/java/lang/reflect/WildcardType.java b/libjava/classpath/java/lang/reflect/WildcardType.java new file mode 100644 index 0000000..4f78906 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/WildcardType.java @@ -0,0 +1,115 @@ +/* WildcardType.java -- A wildcard type expression e.g. ? extends String + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.lang.reflect; + +/** + * Represents a wildcard type expression, where the type variable + * is unnamed. The simplest example of this is <code>?</code>, + * which represents any unbounded type. Another example is + * <code>? extends Number</code>, which specifies any type + * which is a subclass of <code>Number</code> (<code>Number</code> + * is the upper bound). + * </p> + * <p> + * <code>? super String</code> gives the type a less common lower bound, + * which means that the type must be either a <code>String</code> or one + * of its superclasses. This can be useful in working with collections. + * You may want a method to add instances of a class to a collection + * with a more generic type (e.g. adding <code>String</code>s to + * a list of <code>Object</code>s), but don't want to allow users + * to pass in a collection with a more specific type. + * </p> + * + * @author Tom Tromey (tromey@redhat.com) + * @author Andrew John Hughes (gnu_andrew@member.fsf.org) + * @since 1.5 + */ +public interface WildcardType extends Type +{ + + /** + * <p> + * Returns an array of <code>Type</code>s, which specify the + * lower bounds of this type. The default lower bound is + * <code>null</code>, which causes this method to return an + * empty array. + * </p> + * <p> + * In generating the array of <code>Type</code>s, each + * <code>ParameterizedType</code> or <code>TypeVariable</code> is + * created, (see the documentation for these classes for details of this + * process), if necessary, while all other types are simply + * resolved. + * </p> + * + * @return an array of <code>Type</code> objects, representing + * the wildcard type's lower bounds. + * @throws TypeNotPresentException if any of the types referred to by + * the lower bounds of this type do not actually exist. + * @throws MalformedParameterizedTypeException if any of the types + * refer to a type which can not be instantiated. + */ + Type[] getLowerBounds(); + + /** + * <p> + * Returns an array of <code>Type</code>s, which specify the + * upper bounds of this type. The default upper bound is + * <code>Object</code>, which causes this method to return an + * array, containing just the <code>Type</code> instance for + * <code>Object</code>. + * </p> + * <p> + * In generating the array of <code>Type</code>s, each + * <code>ParameterizedType</code> or <code>TypeVariable</code> is + * created, (see the documentation for these classes for details of this + * process), if necessary, while all other types are simply + * resolved. + * </p> + * + * @return an array of <code>Type</code> objects, representing + * the wildcard type's upper bounds. + * @throws TypeNotPresentException if any of the types referred to by + * the upper bounds of this type do not actually exist. + * @throws MalformedParameterizedTypeException if any of the types + * refer to a type which can not be instantiated. + */ + Type[] getUpperBounds(); + +} diff --git a/libjava/classpath/java/lang/reflect/package.html b/libjava/classpath/java/lang/reflect/package.html new file mode 100644 index 0000000..9f7ed63 --- /dev/null +++ b/libjava/classpath/java/lang/reflect/package.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in java.lang.reflect package. + Copyright (C) 2002 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - java.lang.reflect</title></head> + +<body> +<p>Runtime inspection and manipulation of object classes, methods, arguments +and fields.</p> + +</body> +</html> |