diff options
Diffstat (limited to 'src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java')
-rw-r--r-- | src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java new file mode 100644 index 00000000..c6485708 --- /dev/null +++ b/src/libs/xpcom18a4/java/src/org/mozilla/xpcom/internal/XPCOMJavaProxy.java @@ -0,0 +1,257 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Java XPCOM Bindings. + * + * The Initial Developer of the Original Code is + * IBM Corporation. + * Portions created by the Initial Developer are Copyright (C) 2004 + * IBM Corporation. All Rights Reserved. + * + * Contributor(s): + * Javier Pedemonte (jhpedemonte@gmail.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +package org.mozilla.xpcom.internal; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.mozilla.xpcom.XPCOMException; + + +/** + * This class is used to pass XPCOM objects to Java functions. A + * <code>java.lang.reflect.Proxy</code> instance is created using the expected + * interface, and all calls to the proxy are forwarded to the XPCOM object. + */ +public class XPCOMJavaProxy implements InvocationHandler { + + /** + * Pointer to the XPCOM object for which we are a proxy. + */ + protected long nativeXPCOMPtr; + + /** + * Default constructor. + * + * @param aXPCOMInstance address of XPCOM object as a long + */ + public XPCOMJavaProxy(long aXPCOMInstance) { + nativeXPCOMPtr = aXPCOMInstance; + } + + /** + * Returns the XPCOM object that the given proxy references. + * + * @param aProxy Proxy created by <code>createProxy</code> + * + * @return address of XPCOM object as a long + */ + protected static long getNativeXPCOMInstance(Object aProxy) { + XPCOMJavaProxy proxy = (XPCOMJavaProxy) Proxy.getInvocationHandler(aProxy); + return proxy.nativeXPCOMPtr; + } + + /** + * Creates a Proxy for the given XPCOM object. + * + * @param aInterface interface from which to create Proxy + * @param aXPCOMInstance address of XPCOM object as a long + * + * @return Proxy of given XPCOM object + */ + protected static Object createProxy(Class aInterface, long aXPCOMInstance) { + // XXX We should really get the class loader from |aInterface|. However, + // that class loader doesn't know about |XPCOMJavaProxyBase|. So for + // now, we get the class loader that loaded |XPCOMJavaProxy|. When + // we get rid of the "XPCOMJavaProxyBase.java" class, we can revert + // to the old method below. +// return Proxy.newProxyInstance(aInterface.getClassLoader(), + return Proxy.newProxyInstance(XPCOMJavaProxy.class.getClassLoader(), + new Class[] { aInterface, XPCOMJavaProxyBase.class }, + new XPCOMJavaProxy(aXPCOMInstance)); + } + + /** + * All calls to the Java proxy are forwarded to this method. This method + * takes care of a few of the <code>Object</code> method calls; all other + * calls are forwarded to the XPCOM object. + * + * @param aProxy Proxy created by <code>createProxy</code> + * @param aMethod object that describes the called method + * @param aParams array of the arguments passed to the method + * + * @return return value as defined by given <code>aMethod</code> + */ + public Object invoke(Object aProxy, Method aMethod, Object[] aParams) + throws Throwable { + String methodName = aMethod.getName(); + + // Handle the three java.lang.Object methods that are passed to us. + if (aMethod.getDeclaringClass() == Object.class) { + if (methodName.equals("hashCode")) { + return proxyHashCode(aProxy); + } + if (methodName.equals("equals")) { + return proxyEquals(aProxy, aParams[0]); + } + if (methodName.equals("toString")) { + return proxyToString(aProxy); + } + System.err.println("WARNING: Unhandled Object method [" + + methodName + "]"); + return null; + } + + // Handle the 'finalize' method called during garbage collection + if (aMethod.getDeclaringClass() == XPCOMJavaProxyBase.class) { + if (methodName.equals("finalize")) { + finalizeProxy(aProxy); + } else { + System.err.println("WARNING: Unhandled XPCOMJavaProxyBase method [" + + methodName + "]"); + } + return null; + } + + // If not already handled, pass method calls to XPCOM object. + return callXPCOMMethod(aProxy, methodName, aParams); + } + + /** + * Handles method calls of <code>java.lang.Object.hashCode</code> + * + * @param aProxy Proxy created by <code>createProxy</code> + * + * @return Integer object representing hash code of given object + * + * @see Object#hashCode() + */ + protected static Integer proxyHashCode(Object aProxy) { + return new Integer(System.identityHashCode(aProxy)); + } + + /** + * Handles method calls of <code>java.lang.Object.equals</code> + * + * @param aProxy Proxy created by <code>createProxy</code> + * @param aOther another object + * + * @return <code>true</code> if the given objects are the same; + * <code>false</code> otherwise + * + * @see Object#equals(Object) + */ + protected static Boolean proxyEquals(Object aProxy, Object aOther) { + // See if the two are the same Java object + if (aProxy == aOther) { + return Boolean.TRUE; + } else { + // If not, then see if they represent the same XPCOM object. But first, + // we need to check if |aOther| is an XPCOMJavaProxy. + if (isXPCOMJavaProxy(aOther) && isSameXPCOMObject(aProxy, aOther)) { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } + + /** + * Indicates whether the given object is an XPCOMJavaProxy. + * + * @param aObject object to check + * + * @return <code>true</code> if the given object is an XPCOMJavaProxy; + * <code>false</code> otherwise + */ + protected static boolean isXPCOMJavaProxy(Object aObject) { + if (aObject != null && Proxy.isProxyClass(aObject.getClass())) { + InvocationHandler h = Proxy.getInvocationHandler(aObject); + if (h instanceof XPCOMJavaProxy) { + return true; + } + } + return false; + } + + /** + * Checks if the two given XPCOMJavaProxy objects are proxies for + * the same XPCOM object. + * + * @param aProxy1 XPCOMJavaProxy created by <code>createProxy</code> + * @param aProxy2 XPCOMJavaProxy created by <code>createProxy</code> + * + * @return <code>true</code> if both proxies represent the same XPCOM object; + * <code>false</code> otherwise + */ + protected static native boolean isSameXPCOMObject(Object aProxy1, + Object aProxy2); + + /** + * Handles method calls of <code>java.lang.Object.toString</code> + * + * @param aProxy Proxy created by <code>createProxy</code> + * + * @return String representation of given object + * + * @see Object#toString() + */ + protected static String proxyToString(Object aProxy) { + return aProxy.getClass().getInterfaces()[0].getName() + '@' + + Integer.toHexString(aProxy.hashCode()); + } + + /** + * Called when the proxy is garbage collected by the JVM. Allows us to clean + * up any references to the XPCOM object. + * + * @param aProxy reference to Proxy that is being garbage collected + */ + protected void finalizeProxy(Object aProxy) throws Throwable { + finalizeProxyNative(aProxy); + super.finalize(); + } + + protected static native void finalizeProxyNative(Object aProxy); + + /** + * Calls the XPCOM object referenced by the proxy with the given method. + * + * @param aProxy Proxy created by <code>createProxy</code> + * @param aMethodName name of method that we want to call + * @param aParams array of params passed to method + * + * @return return value as defined by given method + * + * @exception XPCOMException if XPCOM method failed. Values of XPCOMException + * are defined by the method called. + */ + protected static native Object callXPCOMMethod(Object aProxy, + String aMethodName, Object[] aParams); + +} |