diff options
author | Tom Tromey <tromey@redhat.com> | 2005-07-16 01:27:14 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 01:27:14 +0000 |
commit | b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1 (patch) | |
tree | 8762d1f992e2f725a6bde1ff966ed6f1e5f4f823 /libjava/java/lang/reflect | |
parent | ea54b29342c8506acb4f858c68340c44b72e3532 (diff) | |
download | gcc-b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1.zip gcc-b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1.tar.gz gcc-b0fa81eea9a270f23d6ad67ca7a6d25c18d20da1.tar.bz2 |
Major merge with Classpath.
Removed many duplicate files.
* HACKING: Updated.x
* classpath: Imported new directory.
* standard.omit: New file.
* Makefile.in, aclocal.m4, configure: Rebuilt.
* sources.am: New file.
* configure.ac: Run Classpath configure script. Moved code around
to support. Disable xlib AWT peers (temporarily).
* Makefile.am (SUBDIRS): Added 'classpath'
(JAVAC): Removed.
(AM_CPPFLAGS): Added more -I options.
(BOOTCLASSPATH): Simplified.
Completely redid how sources are built.
Include sources.am.
* include/Makefile.am (tool_include__HEADERS): Removed jni.h.
* include/jni.h: Removed (in Classpath).
* scripts/classes.pl: Updated to look at built classes.
* scripts/makemake.tcl: New file.
* testsuite/libjava.jni/jni.exp (gcj_jni_compile_c_to_so): Added
-I options.
(gcj_jni_invocation_compile_c_to_binary): Likewise.
From-SVN: r102082
Diffstat (limited to 'libjava/java/lang/reflect')
-rw-r--r-- | libjava/java/lang/reflect/AccessibleObject.java | 159 | ||||
-rw-r--r-- | libjava/java/lang/reflect/InvocationHandler.java | 137 | ||||
-rw-r--r-- | libjava/java/lang/reflect/InvocationTargetException.java | 123 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Member.java | 100 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Proxy.java | 1615 | ||||
-rw-r--r-- | libjava/java/lang/reflect/ReflectPermission.java | 102 | ||||
-rw-r--r-- | libjava/java/lang/reflect/UndeclaredThrowableException.java | 128 |
7 files changed, 0 insertions, 2364 deletions
diff --git a/libjava/java/lang/reflect/AccessibleObject.java b/libjava/java/lang/reflect/AccessibleObject.java deleted file mode 100644 index 24418c9..0000000 --- a/libjava/java/lang/reflect/AccessibleObject.java +++ /dev/null @@ -1,159 +0,0 @@ -/* 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/java/lang/reflect/InvocationHandler.java b/libjava/java/lang/reflect/InvocationHandler.java deleted file mode 100644 index 208e621..0000000 --- a/libjava/java/lang/reflect/InvocationHandler.java +++ /dev/null @@ -1,137 +0,0 @@ -/* 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/java/lang/reflect/InvocationTargetException.java b/libjava/java/lang/reflect/InvocationTargetException.java deleted file mode 100644 index af79d3a..0000000 --- a/libjava/java/lang/reflect/InvocationTargetException.java +++ /dev/null @@ -1,123 +0,0 @@ -/* 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/java/lang/reflect/Member.java b/libjava/java/lang/reflect/Member.java deleted file mode 100644 index 9983b27..0000000 --- a/libjava/java/lang/reflect/Member.java +++ /dev/null @@ -1,100 +0,0 @@ -/* 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/java/lang/reflect/Proxy.java b/libjava/java/lang/reflect/Proxy.java deleted file mode 100644 index dc1ac87..0000000 --- a/libjava/java/lang/reflect/Proxy.java +++ /dev/null @@ -1,1615 +0,0 @@ -/* 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/java/lang/reflect/ReflectPermission.java b/libjava/java/lang/reflect/ReflectPermission.java deleted file mode 100644 index 56eccf8..0000000 --- a/libjava/java/lang/reflect/ReflectPermission.java +++ /dev/null @@ -1,102 +0,0 @@ -/* 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/java/lang/reflect/UndeclaredThrowableException.java b/libjava/java/lang/reflect/UndeclaredThrowableException.java deleted file mode 100644 index 6d5a800..0000000 --- a/libjava/java/lang/reflect/UndeclaredThrowableException.java +++ /dev/null @@ -1,128 +0,0 @@ -/* 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; - } -} |