Java Code Examples for java.lang.reflect.Proxy#getInvocationHandler()

The following examples show how to use java.lang.reflect.Proxy#getInvocationHandler() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
@Override
public Object invoke(Model delegate, Method method, Object[] args) throws Exception {
	if(args.length != 1 || args[0] == null) {
		return false;
	}
	Object other = args[0];
	if(Proxy.isProxyClass(other.getClass())) {
		InvocationHandler handler = Proxy.getInvocationHandler(other);
		if(handler instanceof ModelInvocationHandler) {
			return delegate.equals(((ModelInvocationHandler) handler).getDelegate());
		}
	}
	if(other instanceof Model) {
		return delegate.equals(other);
	}
	return false;
}
 
Example 2
/**
 * Transfroms a proxy implementing T in a proxy implementing T plus
 * NotificationEmitter
 *
 **/
public static <T> T makeNotificationEmitter(T proxy,
                    Class<T> mbeanInterface) {
    if (proxy instanceof NotificationEmitter)
        return proxy;
    if (proxy == null) return null;
    if (!(proxy instanceof Proxy))
        throw new IllegalArgumentException("not a "+Proxy.class.getName());
    final Proxy p = (Proxy) proxy;
    final InvocationHandler handler =
            Proxy.getInvocationHandler(proxy);
    if (!(handler instanceof MBeanServerInvocationHandler))
        throw new IllegalArgumentException("not a JMX Proxy");
    final MBeanServerInvocationHandler h =
            (MBeanServerInvocationHandler)handler;
    final ObjectName name = h.getObjectName();
    final MBeanServerConnection mbs = h.getMBeanServerConnection();
    final boolean isMXBean = h.isMXBean();
    final T newProxy;
    if (isMXBean)
        newProxy = JMX.newMXBeanProxy(mbs,name,mbeanInterface,true);
    else
        newProxy = JMX.newMBeanProxy(mbs,name,mbeanInterface,true);
    return newProxy;
}
 
Example 3
static boolean equal(Object o1, Object o2, NamedMXBeans namedMXBeans) {
        if (o1 == o2)
            return true;
        if (o1 == null || o2 == null)
            return false;
        if (o1.getClass().isArray()) {
            if (!o2.getClass().isArray())
                return false;
            return deepEqual(o1, o2, namedMXBeans);
        }
        if (o1 instanceof Map) {
            if (!(o2 instanceof Map))
                return false;
            return equalMap((Map) o1, (Map) o2, namedMXBeans);
        }
        if (o1 instanceof CompositeData && o2 instanceof CompositeData) {
            return compositeDataEqual((CompositeData) o1, (CompositeData) o2,
                                      namedMXBeans);
        }
        if (Proxy.isProxyClass(o1.getClass())) {
            if (Proxy.isProxyClass(o2.getClass()))
                return proxyEqual(o1, o2, namedMXBeans);
            InvocationHandler ih = Proxy.getInvocationHandler(o1);
//            if (ih instanceof MXBeanInvocationHandler) {
//                return proxyEqualsObject((MXBeanInvocationHandler) ih,
//                                         o2, namedMXBeans);
            if (ih instanceof MBeanServerInvocationHandler) {
                return true;
            } else if (ih instanceof CompositeDataInvocationHandler) {
                return o2.equals(o1);
                // We assume the other object has a reasonable equals method
            }
        } else if (Proxy.isProxyClass(o2.getClass()))
            return equal(o2, o1, namedMXBeans);
        return o1.equals(o2);
    }
 
Example 4
/**
 * Returns the stub for the remote object <code>obj</code> passed
 * as a parameter. This operation is only valid <i>after</i>
 * the object has been exported.
 * @param obj the remote object whose stub is needed
 * @return the stub for the remote object, <code>obj</code>.
 * @exception NoSuchObjectException if the stub for the
 * remote object could not be found.
 * @since 1.2
 */
public static Remote toStub(Remote obj) throws NoSuchObjectException {
    if (obj instanceof RemoteStub ||
        (obj != null &&
         Proxy.isProxyClass(obj.getClass()) &&
         Proxy.getInvocationHandler(obj) instanceof
         RemoteObjectInvocationHandler))
    {
        return obj;
    } else {
        return sun.rmi.transport.ObjectTable.getStub(obj);
    }
}
 
Example 5
private Object doLocally(Object proxy, Method method, Object[] args) {
    final String methodName = method.getName();

    if (methodName.equals("equals")) {

        if (this == args[0]) {
            return true;
        }

        if (!(args[0] instanceof Proxy)) {
            return false;
        }

        final InvocationHandler ihandler =
            Proxy.getInvocationHandler(args[0]);

        if (ihandler == null ||
            !(ihandler instanceof MBeanServerInvocationHandler)) {
            return false;
        }

        final MBeanServerInvocationHandler handler =
            (MBeanServerInvocationHandler)ihandler;

        return connection.equals(handler.connection) &&
            objectName.equals(handler.objectName) &&
            proxy.getClass().equals(args[0].getClass());
    } else if (methodName.equals("toString")) {
        return (isMXBean() ? "MX" : "M") + "BeanProxy(" +
            connection + "[" + objectName + "])";
    } else if (methodName.equals("hashCode")) {
        return objectName.hashCode()+connection.hashCode();
    } else if (methodName.equals("finalize")) {
        // ignore the finalizer invocation via proxy
        return null;
    }

    throw new RuntimeException("Unexpected method name: " + methodName);
}
 
Example 6
/**
 * Equality means interfaces, advisors and TargetSource are equal.
 * <p>The compared object may be a JdkDynamicAopProxy instance itself
 * or a dynamic proxy wrapping a JdkDynamicAopProxy instance.
 */
@Override
public boolean equals(@Nullable Object other) {
	if (other == this) {
		return true;
	}
	if (other == null) {
		return false;
	}

	JdkDynamicAopProxy otherProxy;
	if (other instanceof JdkDynamicAopProxy) {
		otherProxy = (JdkDynamicAopProxy) other;
	}
	else if (Proxy.isProxyClass(other.getClass())) {
		InvocationHandler ih = Proxy.getInvocationHandler(other);
		if (!(ih instanceof JdkDynamicAopProxy)) {
			return false;
		}
		otherProxy = (JdkDynamicAopProxy) ih;
	}
	else {
		// Not a valid comparison...
		return false;
	}

	// If we get here, otherProxy is the other AopProxy.
	return AopProxyUtils.equalsInProxy(this.advised, otherProxy.advised);
}
 
Example 7
/**
 * Returns the ObjectName of the MBean that a proxy object
 * is proxying.
 **/
public static ObjectName getObjectName(Object proxy) {
    if (!(proxy instanceof Proxy))
        throw new IllegalArgumentException("not a "+Proxy.class.getName());
    final Proxy p = (Proxy) proxy;
    final InvocationHandler handler =
            Proxy.getInvocationHandler(proxy);
    if (handler instanceof MBeanServerInvocationHandler)
        return ((MBeanServerInvocationHandler)handler).getObjectName();
    throw new IllegalArgumentException("not a JMX Proxy");
}
 
Example 8
/**
 * Handles java.lang.Object methods.
 **/
private Object invokeObjectMethod(Object proxy,
                                  Method method,
                                  Object[] args)
{
    String name = method.getName();

    if (name.equals("hashCode")) {
        return hashCode();

    } else if (name.equals("equals")) {
        Object obj = args[0];
        InvocationHandler hdlr;
        return
            proxy == obj ||
            (obj != null &&
             Proxy.isProxyClass(obj.getClass()) &&
             (hdlr = Proxy.getInvocationHandler(obj)) instanceof RemoteObjectInvocationHandler &&
             this.equals(hdlr));

    } else if (name.equals("toString")) {
        return proxyToString(proxy);

    } else {
        throw new IllegalArgumentException(
            "unexpected Object method: " + method);
    }
}
 
Example 9
private Object doLocally(Object proxy, Method method, Object[] args) {
    final String methodName = method.getName();

    if (methodName.equals("equals")) {

        if (this == args[0]) {
            return true;
        }

        if (!(args[0] instanceof Proxy)) {
            return false;
        }

        final InvocationHandler ihandler =
            Proxy.getInvocationHandler(args[0]);

        if (ihandler == null ||
            !(ihandler instanceof MBeanServerInvocationHandler)) {
            return false;
        }

        final MBeanServerInvocationHandler handler =
            (MBeanServerInvocationHandler)ihandler;

        return connection.equals(handler.connection) &&
            objectName.equals(handler.objectName) &&
            proxy.getClass().equals(args[0].getClass());
    } else if (methodName.equals("toString")) {
        return (isMXBean() ? "MX" : "M") + "BeanProxy(" +
            connection + "[" + objectName + "])";
    } else if (methodName.equals("hashCode")) {
        return objectName.hashCode()+connection.hashCode();
    } else if (methodName.equals("finalize")) {
        // ignore the finalizer invocation via proxy
        return null;
    }

    throw new RuntimeException("Unexpected method name: " + methodName);
}
 
Example 10
/**
 * Test the monitor notifications.
 */
public int monitorNotifications() throws Exception {

    server = MBeanServerFactory.newMBeanServer();

    MBeanServerForwarderInvocationHandler mbsfih =
        (MBeanServerForwarderInvocationHandler)
        Proxy.getInvocationHandler(server);

    mbsfih.setGetAttributeException(
        new ReflectionException(new RuntimeException(),
                                "Test ReflectionException"));

    domain = server.getDefaultDomain();

    obsObjName = ObjectName.getInstance(domain + ":type=ObservedObject");
    server.registerMBean(new ObservedObject(), obsObjName);

    echo(">>> ----------------------------------------");
    int error = counterMonitorNotification();
    echo(">>> ----------------------------------------");
    error += gaugeMonitorNotification();
    echo(">>> ----------------------------------------");
    error += stringMonitorNotification();
    echo(">>> ----------------------------------------");
    return error;
}
 
Example 11
Source Project: java-technology-stack   File: BshScriptUtils.java    License: MIT License 5 votes vote down vote up
private boolean isProxyForSameBshObject(Object other) {
	if (!Proxy.isProxyClass(other.getClass())) {
		return false;
	}
	InvocationHandler ih = Proxy.getInvocationHandler(other);
	return (ih instanceof BshObjectInvocationHandler &&
			this.xt.equals(((BshObjectInvocationHandler) ih).xt));
}
 
Example 12
private static boolean proxyEqual(Object proxy1, Object proxy2,
                                  NamedMXBeans namedMXBeans) {
    if (proxy1.getClass() != proxy2.getClass())
        return proxy1.equals(proxy2);
    InvocationHandler ih1 = Proxy.getInvocationHandler(proxy1);
    InvocationHandler ih2 = Proxy.getInvocationHandler(proxy2);
    if (!(ih1 instanceof CompositeDataInvocationHandler)
        || !(ih2 instanceof CompositeDataInvocationHandler))
        return proxy1.equals(proxy2);
    CompositeData cd1 =
        ((CompositeDataInvocationHandler) ih1).getCompositeData();
    CompositeData cd2 =
        ((CompositeDataInvocationHandler) ih2).getCompositeData();
    return compositeDataEqual(cd1, cd2, namedMXBeans);
}
 
Example 13
private boolean equals(Object proxy, Object other) {
    if (other == null)
        return false;

    final Class<?> proxyClass = proxy.getClass();
    final Class<?> otherClass = other.getClass();
    if (proxyClass != otherClass)
        return false;
    InvocationHandler otherih = Proxy.getInvocationHandler(other);
    if (!(otherih instanceof CompositeDataInvocationHandler))
        return false;
    CompositeDataInvocationHandler othercdih =
        (CompositeDataInvocationHandler) otherih;
    return compositeData.equals(othercdih.compositeData);
}
 
Example 14
/**
 * Handles java.lang.Object methods.
 **/
private Object invokeObjectMethod(Object proxy,
                                  Method method,
                                  Object[] args)
{
    String name = method.getName();

    if (name.equals("hashCode")) {
        return hashCode();

    } else if (name.equals("equals")) {
        Object obj = args[0];
        InvocationHandler hdlr;
        return
            proxy == obj ||
            (obj != null &&
             Proxy.isProxyClass(obj.getClass()) &&
             (hdlr = Proxy.getInvocationHandler(obj)) instanceof RemoteObjectInvocationHandler &&
             this.equals(hdlr));

    } else if (name.equals("toString")) {
        return proxyToString(proxy);

    } else {
        throw new IllegalArgumentException(
            "unexpected Object method: " + method);
    }
}
 
Example 15
private static boolean proxyEqual(Object proxy1, Object proxy2,
                                  NamedMXBeans namedMXBeans) {
    if (proxy1.getClass() != proxy2.getClass())
        return proxy1.equals(proxy2);
    InvocationHandler ih1 = Proxy.getInvocationHandler(proxy1);
    InvocationHandler ih2 = Proxy.getInvocationHandler(proxy2);
    if (!(ih1 instanceof CompositeDataInvocationHandler)
        || !(ih2 instanceof CompositeDataInvocationHandler))
        return proxy1.equals(proxy2);
    CompositeData cd1 =
        ((CompositeDataInvocationHandler) ih1).getCompositeData();
    CompositeData cd2 =
        ((CompositeDataInvocationHandler) ih2).getCompositeData();
    return compositeDataEqual(cd1, cd2, namedMXBeans);
}
 
Example 16
/**
 * <code>writeObject</code> for custom serialization.
 *
 * <p>This method writes this object's serialized form for
 * this class as follows:
 *
 * <p>The <code>writeObject</code> method is invoked on
 * <code>out</code> passing this object's unique identifier
 * (a {@link java.rmi.server.UID UID} instance) as the argument.
 *
 * <p>Next, the {@link
 * java.rmi.server.RemoteRef#getRefClass(java.io.ObjectOutput)
 * getRefClass} method is invoked on the activator's
 * <code>RemoteRef</code> instance to obtain its external ref
 * type name.  Next, the <code>writeUTF</code> method is
 * invoked on <code>out</code> with the value returned by
 * <code>getRefClass</code>, and then the
 * <code>writeExternal</code> method is invoked on the
 * <code>RemoteRef</code> instance passing <code>out</code>
 * as the argument.
 *
 * @serialData The serialized data for this class comprises a
 * <code>java.rmi.server.UID</code> (written with
 * <code>ObjectOutput.writeObject</code>) followed by the
 * external ref type name of the activator's
 * <code>RemoteRef</code> instance (a string written with
 * <code>ObjectOutput.writeUTF</code>), followed by the
 * external form of the <code>RemoteRef</code> instance as
 * written by its <code>writeExternal</code> method.
 *
 * <p>The external ref type name of the
 * <code>RemoteRef</Code> instance is
 * determined using the definitions of external ref type
 * names specified in the {@link java.rmi.server.RemoteObject
 * RemoteObject} <code>writeObject</code> method
 * <b>serialData</b> specification.  Similarly, the data
 * written by the <code>writeExternal</code> method and read
 * by the <code>readExternal</code> method of
 * <code>RemoteRef</code> implementation classes
 * corresponding to each of the defined external ref type
 * names is specified in the {@link
 * java.rmi.server.RemoteObject RemoteObject}
 * <code>writeObject</code> method <b>serialData</b>
 * specification.
 **/
private void writeObject(ObjectOutputStream out)
    throws IOException, ClassNotFoundException
{
    out.writeObject(uid);

    RemoteRef ref;
    if (activator instanceof RemoteObject) {
        ref = ((RemoteObject) activator).getRef();
    } else if (Proxy.isProxyClass(activator.getClass())) {
        InvocationHandler handler = Proxy.getInvocationHandler(activator);
        if (!(handler instanceof RemoteObjectInvocationHandler)) {
            throw new InvalidObjectException(
                "unexpected invocation handler");
        }
        ref = ((RemoteObjectInvocationHandler) handler).getRef();

    } else {
        throw new InvalidObjectException("unexpected activator type");
    }
    out.writeUTF(ref.getRefClass(out));
    ref.writeExternal(out);
}
 
Example 17
public static void main(String[] args) throws Exception {

        RemoteInterface server = null;
        RemoteInterface proxy = null;

        try {
            System.setProperty("java.rmi.server.ignoreStubClasses", args[0]);
            boolean ignoreStubClasses = Boolean.parseBoolean(args[0]);

            if (System.getSecurityManager() == null) {
                System.setSecurityManager(new SecurityManager());
            }

            System.err.println("export object");
            server = new UseDynamicProxies();
            proxy =
                (RemoteInterface) UnicastRemoteObject.exportObject(server, 0);

            System.err.println("proxy = " + proxy);
            if (ignoreStubClasses) {
                if (!Proxy.isProxyClass(proxy.getClass())) {
                    throw new RuntimeException(
                        "server proxy is not a dynamic proxy");
                }
                if (!(Proxy.getInvocationHandler(proxy) instanceof
                      RemoteObjectInvocationHandler))
                {
                    throw new RuntimeException("invalid invocation handler");
                }

            } else if (!(proxy instanceof RemoteStub)) {
                throw new RuntimeException(
                    "server proxy is not a RemoteStub");
            }

            System.err.println("invoke methods");
            Object obj = proxy.passObject(proxy);
            if (!proxy.equals(obj)) {
                throw new RuntimeException("returned proxy not equal");
            }

            int x = proxy.passInt(53);
            if (x != 53) {
                throw new RuntimeException("returned int not equal");
            }

            String string = proxy.passString("test");
            if (!string.equals("test")) {
                throw new RuntimeException("returned string not equal");
            }

            System.err.println("TEST PASSED");

        } finally {
            if (proxy != null) {
                UnicastRemoteObject.unexportObject(server, true);
            }
        }
    }
 
Example 18
/**
 * Run test
 */
public int runTest(boolean setBeforeStart) throws Exception {

    echo("=-=-= MBSFPreStartPostStartTest: Set MBSF " +
         (setBeforeStart ? "before" : "after") +
         " starting the connector server =-=-=");

    JMXConnectorServer server = null;
    JMXConnector client = null;

    // Create a new MBeanServer
    //
    final MBeanServer mbs = MBeanServerFactory.createMBeanServer();

    try {
        // Create the JMXServiceURL
        //
        final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");

        // Create a JMXConnectorServer
        //
        server = JMXConnectorServerFactory.newJMXConnectorServer(url,
                                                                 null,
                                                                 mbs);

        // Create MBeanServerForwarder
        //
        MBeanServerForwarder mbsf =
            MBSFInvocationHandler.newProxyInstance();

        // Set MBeanServerForwarder before start()
        //
        if (setBeforeStart)
            server.setMBeanServerForwarder(mbsf);

        // Start the JMXConnectorServer
        //
        server.start();

        // Set MBeanServerForwarder after start()
        //
        if (!setBeforeStart)
            server.setMBeanServerForwarder(mbsf);

        // Create a JMXConnector
        //
        client = server.toJMXConnector(null);

        // Connect to the connector server
        //
        client.connect(null);

        // Get non-secure MBeanServerConnection
        //
        final MBeanServerConnection mbsc =
            client.getMBeanServerConnection();

        // Run method
        //
        mbsc.getDefaultDomain();

        // Check flag in MBeanServerForwarder
        //
        MBSFInvocationHandler mbsfih =
            (MBSFInvocationHandler) Proxy.getInvocationHandler(mbsf);
        if (mbsfih.getFlag() == true) {
            echo("OK: Did go into MBeanServerForwarder!");
        } else {
            echo("KO: Didn't go into MBeanServerForwarder!");
            return 1;
        }
    } catch (Exception e) {
        echo("Failed to perform operation: " + e);
        return 1;
    } finally {
        // Close the connection
        //
        if (client != null)
            client.close();

        // Stop the connector server
        //
        if (server != null)
            server.stop();

        // Release the MBeanServer
        //
        if (mbs != null)
            MBeanServerFactory.releaseMBeanServer(mbs);
    }

    return 0;
}
 
Example 19
/**
 * <code>writeObject</code> for custom serialization.
 *
 * <p>This method writes this object's serialized form for
 * this class as follows:
 *
 * <p>The <code>writeObject</code> method is invoked on
 * <code>out</code> passing this object's unique identifier
 * (a {@link java.rmi.server.UID UID} instance) as the argument.
 *
 * <p>Next, the {@link
 * java.rmi.server.RemoteRef#getRefClass(java.io.ObjectOutput)
 * getRefClass} method is invoked on the activator's
 * <code>RemoteRef</code> instance to obtain its external ref
 * type name.  Next, the <code>writeUTF</code> method is
 * invoked on <code>out</code> with the value returned by
 * <code>getRefClass</code>, and then the
 * <code>writeExternal</code> method is invoked on the
 * <code>RemoteRef</code> instance passing <code>out</code>
 * as the argument.
 *
 * @serialData The serialized data for this class comprises a
 * <code>java.rmi.server.UID</code> (written with
 * <code>ObjectOutput.writeObject</code>) followed by the
 * external ref type name of the activator's
 * <code>RemoteRef</code> instance (a string written with
 * <code>ObjectOutput.writeUTF</code>), followed by the
 * external form of the <code>RemoteRef</code> instance as
 * written by its <code>writeExternal</code> method.
 *
 * <p>The external ref type name of the
 * <code>RemoteRef</Code> instance is
 * determined using the definitions of external ref type
 * names specified in the {@link java.rmi.server.RemoteObject
 * RemoteObject} <code>writeObject</code> method
 * <b>serialData</b> specification.  Similarly, the data
 * written by the <code>writeExternal</code> method and read
 * by the <code>readExternal</code> method of
 * <code>RemoteRef</code> implementation classes
 * corresponding to each of the defined external ref type
 * names is specified in the {@link
 * java.rmi.server.RemoteObject RemoteObject}
 * <code>writeObject</code> method <b>serialData</b>
 * specification.
 **/
private void writeObject(ObjectOutputStream out)
    throws IOException, ClassNotFoundException
{
    out.writeObject(uid);

    RemoteRef ref;
    if (activator instanceof RemoteObject) {
        ref = ((RemoteObject) activator).getRef();
    } else if (Proxy.isProxyClass(activator.getClass())) {
        InvocationHandler handler = Proxy.getInvocationHandler(activator);
        if (!(handler instanceof RemoteObjectInvocationHandler)) {
            throw new InvalidObjectException(
                "unexpected invocation handler");
        }
        ref = ((RemoteObjectInvocationHandler) handler).getRef();

    } else {
        throw new InvalidObjectException("unexpected activator type");
    }
    out.writeUTF(ref.getRefClass(out));
    ref.writeExternal(out);
}
 
Example 20
/**
 * Processes a method invocation made on the encapsulating
 * proxy instance, <code>proxy</code>, and returns the result.
 *
 * <p><code>RemoteObjectInvocationHandler</code> implements this method
 * as follows:
 *
 * <p>If <code>method</code> is one of the following methods, it
 * is processed as described below:
 *
 * <ul>
 *
 * <li>{@link Object#hashCode Object.hashCode}: Returns the hash
 * code value for the proxy.
 *
 * <li>{@link Object#equals Object.equals}: Returns <code>true</code>
 * if the argument (<code>args[0]</code>) is an instance of a dynamic
 * proxy class and this invocation handler is equal to the invocation
 * handler of that argument, and returns <code>false</code> otherwise.
 *
 * <li>{@link Object#toString Object.toString}: Returns a string
 * representation of the proxy.
 * </ul>
 *
 * <p>Otherwise, a remote call is made as follows:
 *
 * <ul>
 * <li>If <code>proxy</code> is not an instance of the interface
 * {@link Remote}, then an {@link IllegalArgumentException} is thrown.
 *
 * <li>Otherwise, the {@link RemoteRef#invoke invoke} method is invoked
 * on this invocation handler's <code>RemoteRef</code>, passing
 * <code>proxy</code>, <code>method</code>, <code>args</code>, and the
 * method hash (defined in section 8.3 of the "Java Remote Method
 * Invocation (RMI) Specification") for <code>method</code>, and the
 * result is returned.
 *
 * <li>If an exception is thrown by <code>RemoteRef.invoke</code> and
 * that exception is a checked exception that is not assignable to any
 * exception in the <code>throws</code> clause of the method
 * implemented by the <code>proxy</code>'s class, then that exception
 * is wrapped in an {@link UnexpectedException} and the wrapped
 * exception is thrown.  Otherwise, the exception thrown by
 * <code>invoke</code> is thrown by this method.
 * </ul>
 *
 * <p>The semantics of this method are unspecified if the
 * arguments could not have been produced by an instance of some
 * valid dynamic proxy class containing this invocation handler.
 *
 * @param proxy the proxy instance that the method was invoked on
 * @param method the <code>Method</code> instance corresponding to the
 * interface method invoked on the proxy instance
 * @param args an array of objects containing the values of the
 * arguments passed in the method invocation on the proxy instance, or
 * <code>null</code> if the method takes no arguments
 * @return the value to return from the method invocation on the proxy
 * instance
 * @throws  Throwable the exception to throw from the method invocation
 * on the proxy instance
 **/
public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable
{
    if (! Proxy.isProxyClass(proxy.getClass())) {
        throw new IllegalArgumentException("not a proxy");
    }

    if (Proxy.getInvocationHandler(proxy) != this) {
        throw new IllegalArgumentException("handler mismatch");
    }

    if (method.getDeclaringClass() == Object.class) {
        return invokeObjectMethod(proxy, method, args);
    } else if ("finalize".equals(method.getName()) && method.getParameterCount() == 0 &&
        !allowFinalizeInvocation) {
        return null; // ignore
    } else {
        return invokeRemoteMethod(proxy, method, args);
    }
}