rt/emul/mini/src/main/java/java/lang/reflect/Proxy.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 21 Oct 2013 14:34:12 +0200
changeset 1378 9ee9b36adb53
parent 772 d382dacfd73f
child 1381 033c5641c63f
permissions -rw-r--r--
Can create Proxy for an annotation
     1 /*
     2  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.lang.reflect;
    27 
    28 
    29 /**
    30  * {@code Proxy} provides static methods for creating dynamic proxy
    31  * classes and instances, and it is also the superclass of all
    32  * dynamic proxy classes created by those methods.
    33  *
    34  * <p>To create a proxy for some interface {@code Foo}:
    35  * <pre>
    36  *     InvocationHandler handler = new MyInvocationHandler(...);
    37  *     Class proxyClass = Proxy.getProxyClass(
    38  *         Foo.class.getClassLoader(), new Class[] { Foo.class });
    39  *     Foo f = (Foo) proxyClass.
    40  *         getConstructor(new Class[] { InvocationHandler.class }).
    41  *         newInstance(new Object[] { handler });
    42  * </pre>
    43  * or more simply:
    44  * <pre>
    45  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
    46  *                                          new Class[] { Foo.class },
    47  *                                          handler);
    48  * </pre>
    49  *
    50  * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
    51  * class</i> below) is a class that implements a list of interfaces
    52  * specified at runtime when the class is created, with behavior as
    53  * described below.
    54  *
    55  * A <i>proxy interface</i> is such an interface that is implemented
    56  * by a proxy class.
    57  *
    58  * A <i>proxy instance</i> is an instance of a proxy class.
    59  *
    60  * Each proxy instance has an associated <i>invocation handler</i>
    61  * object, which implements the interface {@link InvocationHandler}.
    62  * A method invocation on a proxy instance through one of its proxy
    63  * interfaces will be dispatched to the {@link InvocationHandler#invoke
    64  * invoke} method of the instance's invocation handler, passing the proxy
    65  * instance, a {@code java.lang.reflect.Method} object identifying
    66  * the method that was invoked, and an array of type {@code Object}
    67  * containing the arguments.  The invocation handler processes the
    68  * encoded method invocation as appropriate and the result that it
    69  * returns will be returned as the result of the method invocation on
    70  * the proxy instance.
    71  *
    72  * <p>A proxy class has the following properties:
    73  *
    74  * <ul>
    75  * <li>Proxy classes are public, final, and not abstract.
    76  *
    77  * <li>The unqualified name of a proxy class is unspecified.  The space
    78  * of class names that begin with the string {@code "$Proxy"}
    79  * should be, however, reserved for proxy classes.
    80  *
    81  * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
    82  *
    83  * <li>A proxy class implements exactly the interfaces specified at its
    84  * creation, in the same order.
    85  *
    86  * <li>If a proxy class implements a non-public interface, then it will
    87  * be defined in the same package as that interface.  Otherwise, the
    88  * package of a proxy class is also unspecified.  Note that package
    89  * sealing will not prevent a proxy class from being successfully defined
    90  * in a particular package at runtime, and neither will classes already
    91  * defined by the same class loader and the same package with particular
    92  * signers.
    93  *
    94  * <li>Since a proxy class implements all of the interfaces specified at
    95  * its creation, invoking {@code getInterfaces} on its
    96  * {@code Class} object will return an array containing the same
    97  * list of interfaces (in the order specified at its creation), invoking
    98  * {@code getMethods} on its {@code Class} object will return
    99  * an array of {@code Method} objects that include all of the
   100  * methods in those interfaces, and invoking {@code getMethod} will
   101  * find methods in the proxy interfaces as would be expected.
   102  *
   103  * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
   104  * return true if it is passed a proxy class-- a class returned by
   105  * {@code Proxy.getProxyClass} or the class of an object returned by
   106  * {@code Proxy.newProxyInstance}-- and false otherwise.
   107  *
   108  * <li>The {@code java.security.ProtectionDomain} of a proxy class
   109  * is the same as that of system classes loaded by the bootstrap class
   110  * loader, such as {@code java.lang.Object}, because the code for a
   111  * proxy class is generated by trusted system code.  This protection
   112  * domain will typically be granted
   113  * {@code java.security.AllPermission}.
   114  *
   115  * <li>Each proxy class has one public constructor that takes one argument,
   116  * an implementation of the interface {@link InvocationHandler}, to set
   117  * the invocation handler for a proxy instance.  Rather than having to use
   118  * the reflection API to access the public constructor, a proxy instance
   119  * can be also be created by calling the {@link Proxy#newProxyInstance
   120  * Proxy.newProxyInstance} method, which combines the actions of calling
   121  * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
   122  * constructor with an invocation handler.
   123  * </ul>
   124  *
   125  * <p>A proxy instance has the following properties:
   126  *
   127  * <ul>
   128  * <li>Given a proxy instance {@code proxy} and one of the
   129  * interfaces implemented by its proxy class {@code Foo}, the
   130  * following expression will return true:
   131  * <pre>
   132  *     {@code proxy instanceof Foo}
   133  * </pre>
   134  * and the following cast operation will succeed (rather than throwing
   135  * a {@code ClassCastException}):
   136  * <pre>
   137  *     {@code (Foo) proxy}
   138  * </pre>
   139  *
   140  * <li>Each proxy instance has an associated invocation handler, the one
   141  * that was passed to its constructor.  The static
   142  * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
   143  * will return the invocation handler associated with the proxy instance
   144  * passed as its argument.
   145  *
   146  * <li>An interface method invocation on a proxy instance will be
   147  * encoded and dispatched to the invocation handler's {@link
   148  * InvocationHandler#invoke invoke} method as described in the
   149  * documentation for that method.
   150  *
   151  * <li>An invocation of the {@code hashCode},
   152  * {@code equals}, or {@code toString} methods declared in
   153  * {@code java.lang.Object} on a proxy instance will be encoded and
   154  * dispatched to the invocation handler's {@code invoke} method in
   155  * the same manner as interface method invocations are encoded and
   156  * dispatched, as described above.  The declaring class of the
   157  * {@code Method} object passed to {@code invoke} will be
   158  * {@code java.lang.Object}.  Other public methods of a proxy
   159  * instance inherited from {@code java.lang.Object} are not
   160  * overridden by a proxy class, so invocations of those methods behave
   161  * like they do for instances of {@code java.lang.Object}.
   162  * </ul>
   163  *
   164  * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
   165  *
   166  * <p>When two or more interfaces of a proxy class contain a method with
   167  * the same name and parameter signature, the order of the proxy class's
   168  * interfaces becomes significant.  When such a <i>duplicate method</i>
   169  * is invoked on a proxy instance, the {@code Method} object passed
   170  * to the invocation handler will not necessarily be the one whose
   171  * declaring class is assignable from the reference type of the interface
   172  * that the proxy's method was invoked through.  This limitation exists
   173  * because the corresponding method implementation in the generated proxy
   174  * class cannot determine which interface it was invoked through.
   175  * Therefore, when a duplicate method is invoked on a proxy instance,
   176  * the {@code Method} object for the method in the foremost interface
   177  * that contains the method (either directly or inherited through a
   178  * superinterface) in the proxy class's list of interfaces is passed to
   179  * the invocation handler's {@code invoke} method, regardless of the
   180  * reference type through which the method invocation occurred.
   181  *
   182  * <p>If a proxy interface contains a method with the same name and
   183  * parameter signature as the {@code hashCode}, {@code equals},
   184  * or {@code toString} methods of {@code java.lang.Object},
   185  * when such a method is invoked on a proxy instance, the
   186  * {@code Method} object passed to the invocation handler will have
   187  * {@code java.lang.Object} as its declaring class.  In other words,
   188  * the public, non-final methods of {@code java.lang.Object}
   189  * logically precede all of the proxy interfaces for the determination of
   190  * which {@code Method} object to pass to the invocation handler.
   191  *
   192  * <p>Note also that when a duplicate method is dispatched to an
   193  * invocation handler, the {@code invoke} method may only throw
   194  * checked exception types that are assignable to one of the exception
   195  * types in the {@code throws} clause of the method in <i>all</i> of
   196  * the proxy interfaces that it can be invoked through.  If the
   197  * {@code invoke} method throws a checked exception that is not
   198  * assignable to any of the exception types declared by the method in one
   199  * of the proxy interfaces that it can be invoked through, then an
   200  * unchecked {@code UndeclaredThrowableException} will be thrown by
   201  * the invocation on the proxy instance.  This restriction means that not
   202  * all of the exception types returned by invoking
   203  * {@code getExceptionTypes} on the {@code Method} object
   204  * passed to the {@code invoke} method can necessarily be thrown
   205  * successfully by the {@code invoke} method.
   206  *
   207  * @author      Peter Jones
   208  * @see         InvocationHandler
   209  * @since       1.3
   210  */
   211 public class Proxy implements java.io.Serializable {
   212 
   213     private static final long serialVersionUID = -2222568056686623797L;
   214 
   215     private final static Method getProxyClass;
   216     static {
   217         Class<?> pg;
   218         try {
   219             pg = Class.forName("org.apidesign.bck2brwsr.emul.reflect.ProxyImpl");
   220             getProxyClass = pg.getMethod("getProxyClass", ClassLoader.class, Class[].class);
   221         } catch (Exception ex) {
   222             throw new IllegalStateException(ex);
   223         }
   224     }
   225 
   226     /**
   227      * the invocation handler for this proxy instance.
   228      * @serial
   229      */
   230     protected InvocationHandler h;
   231 
   232     /**
   233      * Prohibits instantiation.
   234      */
   235     private Proxy() {
   236     }
   237 
   238     /**
   239      * Constructs a new {@code Proxy} instance from a subclass
   240      * (typically, a dynamic proxy class) with the specified value
   241      * for its invocation handler.
   242      *
   243      * @param   h the invocation handler for this proxy instance
   244      */
   245     protected Proxy(InvocationHandler h) {
   246         this.h = h;
   247     }
   248 
   249     /**
   250      * Returns the {@code java.lang.Class} object for a proxy class
   251      * given a class loader and an array of interfaces.  The proxy class
   252      * will be defined by the specified class loader and will implement
   253      * all of the supplied interfaces.  If a proxy class for the same
   254      * permutation of interfaces has already been defined by the class
   255      * loader, then the existing proxy class will be returned; otherwise,
   256      * a proxy class for those interfaces will be generated dynamically
   257      * and defined by the class loader.
   258      *
   259      * <p>There are several restrictions on the parameters that may be
   260      * passed to {@code Proxy.getProxyClass}:
   261      *
   262      * <ul>
   263      * <li>All of the {@code Class} objects in the
   264      * {@code interfaces} array must represent interfaces, not
   265      * classes or primitive types.
   266      *
   267      * <li>No two elements in the {@code interfaces} array may
   268      * refer to identical {@code Class} objects.
   269      *
   270      * <li>All of the interface types must be visible by name through the
   271      * specified class loader.  In other words, for class loader
   272      * {@code cl} and every interface {@code i}, the following
   273      * expression must be true:
   274      * <pre>
   275      *     Class.forName(i.getName(), false, cl) == i
   276      * </pre>
   277      *
   278      * <li>All non-public interfaces must be in the same package;
   279      * otherwise, it would not be possible for the proxy class to
   280      * implement all of the interfaces, regardless of what package it is
   281      * defined in.
   282      *
   283      * <li>For any set of member methods of the specified interfaces
   284      * that have the same signature:
   285      * <ul>
   286      * <li>If the return type of any of the methods is a primitive
   287      * type or void, then all of the methods must have that same
   288      * return type.
   289      * <li>Otherwise, one of the methods must have a return type that
   290      * is assignable to all of the return types of the rest of the
   291      * methods.
   292      * </ul>
   293      *
   294      * <li>The resulting proxy class must not exceed any limits imposed
   295      * on classes by the virtual machine.  For example, the VM may limit
   296      * the number of interfaces that a class may implement to 65535; in
   297      * that case, the size of the {@code interfaces} array must not
   298      * exceed 65535.
   299      * </ul>
   300      *
   301      * <p>If any of these restrictions are violated,
   302      * {@code Proxy.getProxyClass} will throw an
   303      * {@code IllegalArgumentException}.  If the {@code interfaces}
   304      * array argument or any of its elements are {@code null}, a
   305      * {@code NullPointerException} will be thrown.
   306      *
   307      * <p>Note that the order of the specified proxy interfaces is
   308      * significant: two requests for a proxy class with the same combination
   309      * of interfaces but in a different order will result in two distinct
   310      * proxy classes.
   311      *
   312      * @param   loader the class loader to define the proxy class
   313      * @param   interfaces the list of interfaces for the proxy class
   314      *          to implement
   315      * @return  a proxy class that is defined in the specified class loader
   316      *          and that implements the specified interfaces
   317      * @throws  IllegalArgumentException if any of the restrictions on the
   318      *          parameters that may be passed to {@code getProxyClass}
   319      *          are violated
   320      * @throws  NullPointerException if the {@code interfaces} array
   321      *          argument or any of its elements are {@code null}
   322      */
   323     public static Class<?> getProxyClass(ClassLoader loader,
   324                                          Class<?>... interfaces)
   325         throws IllegalArgumentException
   326     {
   327         try {
   328             try { throw new IllegalArgumentException(); } catch (Throwable t) {}
   329             return (Class<?>) getProxyClass.invoke(null, loader, interfaces);
   330         } catch (IllegalAccessException ex) {
   331             throw new IllegalStateException(ex);
   332         } catch (InvocationTargetException ex) {
   333             throw (RuntimeException)ex.getTargetException();
   334         }
   335     }
   336 
   337     /**
   338      * Returns an instance of a proxy class for the specified interfaces
   339      * that dispatches method invocations to the specified invocation
   340      * handler.  This method is equivalent to:
   341      * <pre>
   342      *     Proxy.getProxyClass(loader, interfaces).
   343      *         getConstructor(new Class[] { InvocationHandler.class }).
   344      *         newInstance(new Object[] { handler });
   345      * </pre>
   346      *
   347      * <p>{@code Proxy.newProxyInstance} throws
   348      * {@code IllegalArgumentException} for the same reasons that
   349      * {@code Proxy.getProxyClass} does.
   350      *
   351      * @param   loader the class loader to define the proxy class
   352      * @param   interfaces the list of interfaces for the proxy class
   353      *          to implement
   354      * @param   h the invocation handler to dispatch method invocations to
   355      * @return  a proxy instance with the specified invocation handler of a
   356      *          proxy class that is defined by the specified class loader
   357      *          and that implements the specified interfaces
   358      * @throws  IllegalArgumentException if any of the restrictions on the
   359      *          parameters that may be passed to {@code getProxyClass}
   360      *          are violated
   361      * @throws  NullPointerException if the {@code interfaces} array
   362      *          argument or any of its elements are {@code null}, or
   363      *          if the invocation handler, {@code h}, is
   364      *          {@code null}
   365      */
   366     public static Object newProxyInstance(ClassLoader loader,
   367                                           Class<?>[] interfaces,
   368                                           InvocationHandler h)
   369         throws IllegalArgumentException
   370     {
   371         if (h == null) {
   372             throw new NullPointerException();
   373         }
   374 
   375         /*
   376          * Look up or generate the designated proxy class.
   377          */
   378         Class<?> cl = getProxyClass(loader, interfaces);
   379 
   380         /*
   381          * Invoke its constructor with the designated invocation handler.
   382          */
   383         try {
   384             Constructor cons = cl.getConstructor(InvocationHandler.class);
   385             return cons.newInstance(new Object[] { h });
   386         } catch (NoSuchMethodException e) {
   387             throw new IllegalStateException(e.toString());
   388         } catch (IllegalAccessException e) {
   389             throw new IllegalStateException(e.toString());
   390         } catch (InstantiationException e) {
   391             throw new IllegalStateException(e.toString());
   392         } catch (InvocationTargetException e) {
   393             throw new IllegalStateException(e.toString());
   394         }
   395     }
   396 
   397     /**
   398      * Returns true if and only if the specified class was dynamically
   399      * generated to be a proxy class using the {@code getProxyClass}
   400      * method or the {@code newProxyInstance} method.
   401      *
   402      * <p>The reliability of this method is important for the ability
   403      * to use it to make security decisions, so its implementation should
   404      * not just test if the class in question extends {@code Proxy}.
   405      *
   406      * @param   cl the class to test
   407      * @return  {@code true} if the class is a proxy class and
   408      *          {@code false} otherwise
   409      * @throws  NullPointerException if {@code cl} is {@code null}
   410      */
   411     public static boolean isProxyClass(Class<?> cl) {
   412         if (cl == null) {
   413             throw new NullPointerException();
   414         }
   415         return Proxy.class.isAssignableFrom(cl);
   416     }
   417 
   418     /**
   419      * Returns the invocation handler for the specified proxy instance.
   420      *
   421      * @param   proxy the proxy instance to return the invocation handler for
   422      * @return  the invocation handler for the proxy instance
   423      * @throws  IllegalArgumentException if the argument is not a
   424      *          proxy instance
   425      */
   426     public static InvocationHandler getInvocationHandler(Object proxy)
   427         throws IllegalArgumentException
   428     {
   429         /*
   430          * Verify that the object is actually a proxy instance.
   431          */
   432         if (!isProxyClass(proxy.getClass())) {
   433             throw new IllegalArgumentException("not a proxy instance");
   434         }
   435 
   436         Proxy p = (Proxy) proxy;
   437         return p.h;
   438     }
   439 }