1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java Mon Jan 28 18:12:47 2013 +0100
1.3 @@ -0,0 +1,666 @@
1.4 +/*
1.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.lang.reflect;
1.30 +
1.31 +import java.lang.ref.Reference;
1.32 +import java.lang.ref.WeakReference;
1.33 +import java.util.Arrays;
1.34 +import java.util.Collections;
1.35 +import java.util.HashMap;
1.36 +import java.util.HashSet;
1.37 +import java.util.Map;
1.38 +import java.util.Set;
1.39 +import java.util.List;
1.40 +import java.util.WeakHashMap;
1.41 +import sun.misc.ProxyGenerator;
1.42 +
1.43 +/**
1.44 + * {@code Proxy} provides static methods for creating dynamic proxy
1.45 + * classes and instances, and it is also the superclass of all
1.46 + * dynamic proxy classes created by those methods.
1.47 + *
1.48 + * <p>To create a proxy for some interface {@code Foo}:
1.49 + * <pre>
1.50 + * InvocationHandler handler = new MyInvocationHandler(...);
1.51 + * Class proxyClass = Proxy.getProxyClass(
1.52 + * Foo.class.getClassLoader(), new Class[] { Foo.class });
1.53 + * Foo f = (Foo) proxyClass.
1.54 + * getConstructor(new Class[] { InvocationHandler.class }).
1.55 + * newInstance(new Object[] { handler });
1.56 + * </pre>
1.57 + * or more simply:
1.58 + * <pre>
1.59 + * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
1.60 + * new Class[] { Foo.class },
1.61 + * handler);
1.62 + * </pre>
1.63 + *
1.64 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
1.65 + * class</i> below) is a class that implements a list of interfaces
1.66 + * specified at runtime when the class is created, with behavior as
1.67 + * described below.
1.68 + *
1.69 + * A <i>proxy interface</i> is such an interface that is implemented
1.70 + * by a proxy class.
1.71 + *
1.72 + * A <i>proxy instance</i> is an instance of a proxy class.
1.73 + *
1.74 + * Each proxy instance has an associated <i>invocation handler</i>
1.75 + * object, which implements the interface {@link InvocationHandler}.
1.76 + * A method invocation on a proxy instance through one of its proxy
1.77 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
1.78 + * invoke} method of the instance's invocation handler, passing the proxy
1.79 + * instance, a {@code java.lang.reflect.Method} object identifying
1.80 + * the method that was invoked, and an array of type {@code Object}
1.81 + * containing the arguments. The invocation handler processes the
1.82 + * encoded method invocation as appropriate and the result that it
1.83 + * returns will be returned as the result of the method invocation on
1.84 + * the proxy instance.
1.85 + *
1.86 + * <p>A proxy class has the following properties:
1.87 + *
1.88 + * <ul>
1.89 + * <li>Proxy classes are public, final, and not abstract.
1.90 + *
1.91 + * <li>The unqualified name of a proxy class is unspecified. The space
1.92 + * of class names that begin with the string {@code "$Proxy"}
1.93 + * should be, however, reserved for proxy classes.
1.94 + *
1.95 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
1.96 + *
1.97 + * <li>A proxy class implements exactly the interfaces specified at its
1.98 + * creation, in the same order.
1.99 + *
1.100 + * <li>If a proxy class implements a non-public interface, then it will
1.101 + * be defined in the same package as that interface. Otherwise, the
1.102 + * package of a proxy class is also unspecified. Note that package
1.103 + * sealing will not prevent a proxy class from being successfully defined
1.104 + * in a particular package at runtime, and neither will classes already
1.105 + * defined by the same class loader and the same package with particular
1.106 + * signers.
1.107 + *
1.108 + * <li>Since a proxy class implements all of the interfaces specified at
1.109 + * its creation, invoking {@code getInterfaces} on its
1.110 + * {@code Class} object will return an array containing the same
1.111 + * list of interfaces (in the order specified at its creation), invoking
1.112 + * {@code getMethods} on its {@code Class} object will return
1.113 + * an array of {@code Method} objects that include all of the
1.114 + * methods in those interfaces, and invoking {@code getMethod} will
1.115 + * find methods in the proxy interfaces as would be expected.
1.116 + *
1.117 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
1.118 + * return true if it is passed a proxy class-- a class returned by
1.119 + * {@code Proxy.getProxyClass} or the class of an object returned by
1.120 + * {@code Proxy.newProxyInstance}-- and false otherwise.
1.121 + *
1.122 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
1.123 + * is the same as that of system classes loaded by the bootstrap class
1.124 + * loader, such as {@code java.lang.Object}, because the code for a
1.125 + * proxy class is generated by trusted system code. This protection
1.126 + * domain will typically be granted
1.127 + * {@code java.security.AllPermission}.
1.128 + *
1.129 + * <li>Each proxy class has one public constructor that takes one argument,
1.130 + * an implementation of the interface {@link InvocationHandler}, to set
1.131 + * the invocation handler for a proxy instance. Rather than having to use
1.132 + * the reflection API to access the public constructor, a proxy instance
1.133 + * can be also be created by calling the {@link Proxy#newProxyInstance
1.134 + * Proxy.newProxyInstance} method, which combines the actions of calling
1.135 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
1.136 + * constructor with an invocation handler.
1.137 + * </ul>
1.138 + *
1.139 + * <p>A proxy instance has the following properties:
1.140 + *
1.141 + * <ul>
1.142 + * <li>Given a proxy instance {@code proxy} and one of the
1.143 + * interfaces implemented by its proxy class {@code Foo}, the
1.144 + * following expression will return true:
1.145 + * <pre>
1.146 + * {@code proxy instanceof Foo}
1.147 + * </pre>
1.148 + * and the following cast operation will succeed (rather than throwing
1.149 + * a {@code ClassCastException}):
1.150 + * <pre>
1.151 + * {@code (Foo) proxy}
1.152 + * </pre>
1.153 + *
1.154 + * <li>Each proxy instance has an associated invocation handler, the one
1.155 + * that was passed to its constructor. The static
1.156 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
1.157 + * will return the invocation handler associated with the proxy instance
1.158 + * passed as its argument.
1.159 + *
1.160 + * <li>An interface method invocation on a proxy instance will be
1.161 + * encoded and dispatched to the invocation handler's {@link
1.162 + * InvocationHandler#invoke invoke} method as described in the
1.163 + * documentation for that method.
1.164 + *
1.165 + * <li>An invocation of the {@code hashCode},
1.166 + * {@code equals}, or {@code toString} methods declared in
1.167 + * {@code java.lang.Object} on a proxy instance will be encoded and
1.168 + * dispatched to the invocation handler's {@code invoke} method in
1.169 + * the same manner as interface method invocations are encoded and
1.170 + * dispatched, as described above. The declaring class of the
1.171 + * {@code Method} object passed to {@code invoke} will be
1.172 + * {@code java.lang.Object}. Other public methods of a proxy
1.173 + * instance inherited from {@code java.lang.Object} are not
1.174 + * overridden by a proxy class, so invocations of those methods behave
1.175 + * like they do for instances of {@code java.lang.Object}.
1.176 + * </ul>
1.177 + *
1.178 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
1.179 + *
1.180 + * <p>When two or more interfaces of a proxy class contain a method with
1.181 + * the same name and parameter signature, the order of the proxy class's
1.182 + * interfaces becomes significant. When such a <i>duplicate method</i>
1.183 + * is invoked on a proxy instance, the {@code Method} object passed
1.184 + * to the invocation handler will not necessarily be the one whose
1.185 + * declaring class is assignable from the reference type of the interface
1.186 + * that the proxy's method was invoked through. This limitation exists
1.187 + * because the corresponding method implementation in the generated proxy
1.188 + * class cannot determine which interface it was invoked through.
1.189 + * Therefore, when a duplicate method is invoked on a proxy instance,
1.190 + * the {@code Method} object for the method in the foremost interface
1.191 + * that contains the method (either directly or inherited through a
1.192 + * superinterface) in the proxy class's list of interfaces is passed to
1.193 + * the invocation handler's {@code invoke} method, regardless of the
1.194 + * reference type through which the method invocation occurred.
1.195 + *
1.196 + * <p>If a proxy interface contains a method with the same name and
1.197 + * parameter signature as the {@code hashCode}, {@code equals},
1.198 + * or {@code toString} methods of {@code java.lang.Object},
1.199 + * when such a method is invoked on a proxy instance, the
1.200 + * {@code Method} object passed to the invocation handler will have
1.201 + * {@code java.lang.Object} as its declaring class. In other words,
1.202 + * the public, non-final methods of {@code java.lang.Object}
1.203 + * logically precede all of the proxy interfaces for the determination of
1.204 + * which {@code Method} object to pass to the invocation handler.
1.205 + *
1.206 + * <p>Note also that when a duplicate method is dispatched to an
1.207 + * invocation handler, the {@code invoke} method may only throw
1.208 + * checked exception types that are assignable to one of the exception
1.209 + * types in the {@code throws} clause of the method in <i>all</i> of
1.210 + * the proxy interfaces that it can be invoked through. If the
1.211 + * {@code invoke} method throws a checked exception that is not
1.212 + * assignable to any of the exception types declared by the method in one
1.213 + * of the proxy interfaces that it can be invoked through, then an
1.214 + * unchecked {@code UndeclaredThrowableException} will be thrown by
1.215 + * the invocation on the proxy instance. This restriction means that not
1.216 + * all of the exception types returned by invoking
1.217 + * {@code getExceptionTypes} on the {@code Method} object
1.218 + * passed to the {@code invoke} method can necessarily be thrown
1.219 + * successfully by the {@code invoke} method.
1.220 + *
1.221 + * @author Peter Jones
1.222 + * @see InvocationHandler
1.223 + * @since 1.3
1.224 + */
1.225 +public class Proxy implements java.io.Serializable {
1.226 +
1.227 + private static final long serialVersionUID = -2222568056686623797L;
1.228 +
1.229 + /** prefix for all proxy class names */
1.230 + private final static String proxyClassNamePrefix = "$Proxy";
1.231 +
1.232 + /** parameter types of a proxy class constructor */
1.233 + private final static Class[] constructorParams =
1.234 + { InvocationHandler.class };
1.235 +
1.236 + /** maps a class loader to the proxy class cache for that loader */
1.237 + private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
1.238 + = new WeakHashMap<>();
1.239 +
1.240 + /** marks that a particular proxy class is currently being generated */
1.241 + private static Object pendingGenerationMarker = new Object();
1.242 +
1.243 + /** next number to use for generation of unique proxy class names */
1.244 + private static long nextUniqueNumber = 0;
1.245 + private static Object nextUniqueNumberLock = new Object();
1.246 +
1.247 + /** set of all generated proxy classes, for isProxyClass implementation */
1.248 + private static Map<Class<?>, Void> proxyClasses =
1.249 + Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
1.250 +
1.251 + /**
1.252 + * the invocation handler for this proxy instance.
1.253 + * @serial
1.254 + */
1.255 + protected InvocationHandler h;
1.256 +
1.257 + /**
1.258 + * Prohibits instantiation.
1.259 + */
1.260 + private Proxy() {
1.261 + }
1.262 +
1.263 + /**
1.264 + * Constructs a new {@code Proxy} instance from a subclass
1.265 + * (typically, a dynamic proxy class) with the specified value
1.266 + * for its invocation handler.
1.267 + *
1.268 + * @param h the invocation handler for this proxy instance
1.269 + */
1.270 + protected Proxy(InvocationHandler h) {
1.271 + this.h = h;
1.272 + }
1.273 +
1.274 + /**
1.275 + * Returns the {@code java.lang.Class} object for a proxy class
1.276 + * given a class loader and an array of interfaces. The proxy class
1.277 + * will be defined by the specified class loader and will implement
1.278 + * all of the supplied interfaces. If a proxy class for the same
1.279 + * permutation of interfaces has already been defined by the class
1.280 + * loader, then the existing proxy class will be returned; otherwise,
1.281 + * a proxy class for those interfaces will be generated dynamically
1.282 + * and defined by the class loader.
1.283 + *
1.284 + * <p>There are several restrictions on the parameters that may be
1.285 + * passed to {@code Proxy.getProxyClass}:
1.286 + *
1.287 + * <ul>
1.288 + * <li>All of the {@code Class} objects in the
1.289 + * {@code interfaces} array must represent interfaces, not
1.290 + * classes or primitive types.
1.291 + *
1.292 + * <li>No two elements in the {@code interfaces} array may
1.293 + * refer to identical {@code Class} objects.
1.294 + *
1.295 + * <li>All of the interface types must be visible by name through the
1.296 + * specified class loader. In other words, for class loader
1.297 + * {@code cl} and every interface {@code i}, the following
1.298 + * expression must be true:
1.299 + * <pre>
1.300 + * Class.forName(i.getName(), false, cl) == i
1.301 + * </pre>
1.302 + *
1.303 + * <li>All non-public interfaces must be in the same package;
1.304 + * otherwise, it would not be possible for the proxy class to
1.305 + * implement all of the interfaces, regardless of what package it is
1.306 + * defined in.
1.307 + *
1.308 + * <li>For any set of member methods of the specified interfaces
1.309 + * that have the same signature:
1.310 + * <ul>
1.311 + * <li>If the return type of any of the methods is a primitive
1.312 + * type or void, then all of the methods must have that same
1.313 + * return type.
1.314 + * <li>Otherwise, one of the methods must have a return type that
1.315 + * is assignable to all of the return types of the rest of the
1.316 + * methods.
1.317 + * </ul>
1.318 + *
1.319 + * <li>The resulting proxy class must not exceed any limits imposed
1.320 + * on classes by the virtual machine. For example, the VM may limit
1.321 + * the number of interfaces that a class may implement to 65535; in
1.322 + * that case, the size of the {@code interfaces} array must not
1.323 + * exceed 65535.
1.324 + * </ul>
1.325 + *
1.326 + * <p>If any of these restrictions are violated,
1.327 + * {@code Proxy.getProxyClass} will throw an
1.328 + * {@code IllegalArgumentException}. If the {@code interfaces}
1.329 + * array argument or any of its elements are {@code null}, a
1.330 + * {@code NullPointerException} will be thrown.
1.331 + *
1.332 + * <p>Note that the order of the specified proxy interfaces is
1.333 + * significant: two requests for a proxy class with the same combination
1.334 + * of interfaces but in a different order will result in two distinct
1.335 + * proxy classes.
1.336 + *
1.337 + * @param loader the class loader to define the proxy class
1.338 + * @param interfaces the list of interfaces for the proxy class
1.339 + * to implement
1.340 + * @return a proxy class that is defined in the specified class loader
1.341 + * and that implements the specified interfaces
1.342 + * @throws IllegalArgumentException if any of the restrictions on the
1.343 + * parameters that may be passed to {@code getProxyClass}
1.344 + * are violated
1.345 + * @throws NullPointerException if the {@code interfaces} array
1.346 + * argument or any of its elements are {@code null}
1.347 + */
1.348 + public static Class<?> getProxyClass(ClassLoader loader,
1.349 + Class<?>... interfaces)
1.350 + throws IllegalArgumentException
1.351 + {
1.352 + if (interfaces.length > 65535) {
1.353 + throw new IllegalArgumentException("interface limit exceeded");
1.354 + }
1.355 +
1.356 + Class<?> proxyClass = null;
1.357 +
1.358 + /* collect interface names to use as key for proxy class cache */
1.359 + String[] interfaceNames = new String[interfaces.length];
1.360 +
1.361 + // for detecting duplicates
1.362 + Set<Class<?>> interfaceSet = new HashSet<>();
1.363 +
1.364 + for (int i = 0; i < interfaces.length; i++) {
1.365 + /*
1.366 + * Verify that the class loader resolves the name of this
1.367 + * interface to the same Class object.
1.368 + */
1.369 + String interfaceName = interfaces[i].getName();
1.370 + Class<?> interfaceClass = null;
1.371 + try {
1.372 + interfaceClass = Class.forName(interfaceName, false, loader);
1.373 + } catch (ClassNotFoundException e) {
1.374 + }
1.375 + if (interfaceClass != interfaces[i]) {
1.376 + throw new IllegalArgumentException(
1.377 + interfaces[i] + " is not visible from class loader");
1.378 + }
1.379 +
1.380 + /*
1.381 + * Verify that the Class object actually represents an
1.382 + * interface.
1.383 + */
1.384 + if (!interfaceClass.isInterface()) {
1.385 + throw new IllegalArgumentException(
1.386 + interfaceClass.getName() + " is not an interface");
1.387 + }
1.388 +
1.389 + /*
1.390 + * Verify that this interface is not a duplicate.
1.391 + */
1.392 + if (interfaceSet.contains(interfaceClass)) {
1.393 + throw new IllegalArgumentException(
1.394 + "repeated interface: " + interfaceClass.getName());
1.395 + }
1.396 + interfaceSet.add(interfaceClass);
1.397 +
1.398 + interfaceNames[i] = interfaceName;
1.399 + }
1.400 +
1.401 + /*
1.402 + * Using string representations of the proxy interfaces as
1.403 + * keys in the proxy class cache (instead of their Class
1.404 + * objects) is sufficient because we require the proxy
1.405 + * interfaces to be resolvable by name through the supplied
1.406 + * class loader, and it has the advantage that using a string
1.407 + * representation of a class makes for an implicit weak
1.408 + * reference to the class.
1.409 + */
1.410 + List<String> key = Arrays.asList(interfaceNames);
1.411 +
1.412 + /*
1.413 + * Find or create the proxy class cache for the class loader.
1.414 + */
1.415 + Map<List<String>, Object> cache;
1.416 + synchronized (loaderToCache) {
1.417 + cache = loaderToCache.get(loader);
1.418 + if (cache == null) {
1.419 + cache = new HashMap<>();
1.420 + loaderToCache.put(loader, cache);
1.421 + }
1.422 + /*
1.423 + * This mapping will remain valid for the duration of this
1.424 + * method, without further synchronization, because the mapping
1.425 + * will only be removed if the class loader becomes unreachable.
1.426 + */
1.427 + }
1.428 +
1.429 + /*
1.430 + * Look up the list of interfaces in the proxy class cache using
1.431 + * the key. This lookup will result in one of three possible
1.432 + * kinds of values:
1.433 + * null, if there is currently no proxy class for the list of
1.434 + * interfaces in the class loader,
1.435 + * the pendingGenerationMarker object, if a proxy class for the
1.436 + * list of interfaces is currently being generated,
1.437 + * or a weak reference to a Class object, if a proxy class for
1.438 + * the list of interfaces has already been generated.
1.439 + */
1.440 + synchronized (cache) {
1.441 + /*
1.442 + * Note that we need not worry about reaping the cache for
1.443 + * entries with cleared weak references because if a proxy class
1.444 + * has been garbage collected, its class loader will have been
1.445 + * garbage collected as well, so the entire cache will be reaped
1.446 + * from the loaderToCache map.
1.447 + */
1.448 + do {
1.449 + Object value = cache.get(key);
1.450 + if (value instanceof Reference) {
1.451 + proxyClass = (Class<?>) ((Reference) value).get();
1.452 + }
1.453 + if (proxyClass != null) {
1.454 + // proxy class already generated: return it
1.455 + return proxyClass;
1.456 + } else if (value == pendingGenerationMarker) {
1.457 + // proxy class being generated: wait for it
1.458 + try {
1.459 + cache.wait();
1.460 + } catch (InterruptedException e) {
1.461 + /*
1.462 + * The class generation that we are waiting for should
1.463 + * take a small, bounded time, so we can safely ignore
1.464 + * thread interrupts here.
1.465 + */
1.466 + }
1.467 + continue;
1.468 + } else {
1.469 + /*
1.470 + * No proxy class for this list of interfaces has been
1.471 + * generated or is being generated, so we will go and
1.472 + * generate it now. Mark it as pending generation.
1.473 + */
1.474 + cache.put(key, pendingGenerationMarker);
1.475 + break;
1.476 + }
1.477 + } while (true);
1.478 + }
1.479 +
1.480 + try {
1.481 + String proxyPkg = null; // package to define proxy class in
1.482 +
1.483 + /*
1.484 + * Record the package of a non-public proxy interface so that the
1.485 + * proxy class will be defined in the same package. Verify that
1.486 + * all non-public proxy interfaces are in the same package.
1.487 + */
1.488 + for (int i = 0; i < interfaces.length; i++) {
1.489 + int flags = interfaces[i].getModifiers();
1.490 + if (!Modifier.isPublic(flags)) {
1.491 + String name = interfaces[i].getName();
1.492 + int n = name.lastIndexOf('.');
1.493 + String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
1.494 + if (proxyPkg == null) {
1.495 + proxyPkg = pkg;
1.496 + } else if (!pkg.equals(proxyPkg)) {
1.497 + throw new IllegalArgumentException(
1.498 + "non-public interfaces from different packages");
1.499 + }
1.500 + }
1.501 + }
1.502 +
1.503 + if (proxyPkg == null) { // if no non-public proxy interfaces,
1.504 + proxyPkg = ""; // use the unnamed package
1.505 + }
1.506 +
1.507 + {
1.508 + /*
1.509 + * Choose a name for the proxy class to generate.
1.510 + */
1.511 + long num;
1.512 + synchronized (nextUniqueNumberLock) {
1.513 + num = nextUniqueNumber++;
1.514 + }
1.515 + String proxyName = proxyPkg + proxyClassNamePrefix + num;
1.516 + /*
1.517 + * Verify that the class loader hasn't already
1.518 + * defined a class with the chosen name.
1.519 + */
1.520 +
1.521 + /*
1.522 + * Generate the specified proxy class.
1.523 + */
1.524 + byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
1.525 + proxyName, interfaces);
1.526 + try {
1.527 + proxyClass = defineClass0(loader, proxyName,
1.528 + proxyClassFile, 0, proxyClassFile.length);
1.529 + } catch (ClassFormatError e) {
1.530 + /*
1.531 + * A ClassFormatError here means that (barring bugs in the
1.532 + * proxy class generation code) there was some other
1.533 + * invalid aspect of the arguments supplied to the proxy
1.534 + * class creation (such as virtual machine limitations
1.535 + * exceeded).
1.536 + */
1.537 + throw new IllegalArgumentException(e.toString());
1.538 + }
1.539 + }
1.540 + // add to set of all generated proxy classes, for isProxyClass
1.541 + proxyClasses.put(proxyClass, null);
1.542 +
1.543 + } finally {
1.544 + /*
1.545 + * We must clean up the "pending generation" state of the proxy
1.546 + * class cache entry somehow. If a proxy class was successfully
1.547 + * generated, store it in the cache (with a weak reference);
1.548 + * otherwise, remove the reserved entry. In all cases, notify
1.549 + * all waiters on reserved entries in this cache.
1.550 + */
1.551 + synchronized (cache) {
1.552 + if (proxyClass != null) {
1.553 + cache.put(key, new WeakReference<Class<?>>(proxyClass));
1.554 + } else {
1.555 + cache.remove(key);
1.556 + }
1.557 + cache.notifyAll();
1.558 + }
1.559 + }
1.560 + return proxyClass;
1.561 + }
1.562 +
1.563 + /**
1.564 + * Returns an instance of a proxy class for the specified interfaces
1.565 + * that dispatches method invocations to the specified invocation
1.566 + * handler. This method is equivalent to:
1.567 + * <pre>
1.568 + * Proxy.getProxyClass(loader, interfaces).
1.569 + * getConstructor(new Class[] { InvocationHandler.class }).
1.570 + * newInstance(new Object[] { handler });
1.571 + * </pre>
1.572 + *
1.573 + * <p>{@code Proxy.newProxyInstance} throws
1.574 + * {@code IllegalArgumentException} for the same reasons that
1.575 + * {@code Proxy.getProxyClass} does.
1.576 + *
1.577 + * @param loader the class loader to define the proxy class
1.578 + * @param interfaces the list of interfaces for the proxy class
1.579 + * to implement
1.580 + * @param h the invocation handler to dispatch method invocations to
1.581 + * @return a proxy instance with the specified invocation handler of a
1.582 + * proxy class that is defined by the specified class loader
1.583 + * and that implements the specified interfaces
1.584 + * @throws IllegalArgumentException if any of the restrictions on the
1.585 + * parameters that may be passed to {@code getProxyClass}
1.586 + * are violated
1.587 + * @throws NullPointerException if the {@code interfaces} array
1.588 + * argument or any of its elements are {@code null}, or
1.589 + * if the invocation handler, {@code h}, is
1.590 + * {@code null}
1.591 + */
1.592 + public static Object newProxyInstance(ClassLoader loader,
1.593 + Class<?>[] interfaces,
1.594 + InvocationHandler h)
1.595 + throws IllegalArgumentException
1.596 + {
1.597 + if (h == null) {
1.598 + throw new NullPointerException();
1.599 + }
1.600 +
1.601 + /*
1.602 + * Look up or generate the designated proxy class.
1.603 + */
1.604 + Class<?> cl = getProxyClass(loader, interfaces);
1.605 +
1.606 + /*
1.607 + * Invoke its constructor with the designated invocation handler.
1.608 + */
1.609 + try {
1.610 + Constructor cons = cl.getConstructor(constructorParams);
1.611 + return cons.newInstance(new Object[] { h });
1.612 + } catch (NoSuchMethodException e) {
1.613 + throw new InternalError(e.toString());
1.614 + } catch (IllegalAccessException e) {
1.615 + throw new InternalError(e.toString());
1.616 + } catch (InstantiationException e) {
1.617 + throw new InternalError(e.toString());
1.618 + } catch (InvocationTargetException e) {
1.619 + throw new InternalError(e.toString());
1.620 + }
1.621 + }
1.622 +
1.623 + /**
1.624 + * Returns true if and only if the specified class was dynamically
1.625 + * generated to be a proxy class using the {@code getProxyClass}
1.626 + * method or the {@code newProxyInstance} method.
1.627 + *
1.628 + * <p>The reliability of this method is important for the ability
1.629 + * to use it to make security decisions, so its implementation should
1.630 + * not just test if the class in question extends {@code Proxy}.
1.631 + *
1.632 + * @param cl the class to test
1.633 + * @return {@code true} if the class is a proxy class and
1.634 + * {@code false} otherwise
1.635 + * @throws NullPointerException if {@code cl} is {@code null}
1.636 + */
1.637 + public static boolean isProxyClass(Class<?> cl) {
1.638 + if (cl == null) {
1.639 + throw new NullPointerException();
1.640 + }
1.641 +
1.642 + return proxyClasses.containsKey(cl);
1.643 + }
1.644 +
1.645 + /**
1.646 + * Returns the invocation handler for the specified proxy instance.
1.647 + *
1.648 + * @param proxy the proxy instance to return the invocation handler for
1.649 + * @return the invocation handler for the proxy instance
1.650 + * @throws IllegalArgumentException if the argument is not a
1.651 + * proxy instance
1.652 + */
1.653 + public static InvocationHandler getInvocationHandler(Object proxy)
1.654 + throws IllegalArgumentException
1.655 + {
1.656 + /*
1.657 + * Verify that the object is actually a proxy instance.
1.658 + */
1.659 + if (!isProxyClass(proxy.getClass())) {
1.660 + throw new IllegalArgumentException("not a proxy instance");
1.661 + }
1.662 +
1.663 + Proxy p = (Proxy) proxy;
1.664 + return p.h;
1.665 + }
1.666 +
1.667 + private static native Class defineClass0(ClassLoader loader, String name,
1.668 + byte[] b, int off, int len);
1.669 +}