Back to index

lightning-sunbird  0.9+nobinonly
XPCOMJavaProxy.java
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Java XPCOM Bindings.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * IBM Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2004
00019  * IBM Corporation. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Javier Pedemonte (jhpedemonte@gmail.com)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 package org.mozilla.xpcom.internal;
00039 
00040 import java.lang.reflect.InvocationHandler;
00041 import java.lang.reflect.Method;
00042 import java.lang.reflect.Proxy;
00043 
00044 import org.mozilla.xpcom.XPCOMException;
00045 
00046 
00052 public class XPCOMJavaProxy implements InvocationHandler {
00053 
00057   protected long nativeXPCOMPtr;
00058 
00064   public XPCOMJavaProxy(long aXPCOMInstance) {
00065     nativeXPCOMPtr = aXPCOMInstance;
00066   }
00067 
00075   protected static long getNativeXPCOMInstance(Object aProxy) {
00076     XPCOMJavaProxy proxy = (XPCOMJavaProxy) Proxy.getInvocationHandler(aProxy);
00077     return proxy.nativeXPCOMPtr;
00078   }
00079 
00088   protected static Object createProxy(Class aInterface, long aXPCOMInstance) {
00089     // XXX We should really get the class loader from |aInterface|.  However,
00090     //     that class loader doesn't know about |XPCOMJavaProxyBase|.  So for
00091     //     now, we get the class loader that loaded |XPCOMJavaProxy|.  When
00092     //     we get rid of the "XPCOMJavaProxyBase.java" class, we can revert
00093     //     to the old method below.
00094 //    return Proxy.newProxyInstance(aInterface.getClassLoader(),
00095     return Proxy.newProxyInstance(XPCOMJavaProxy.class.getClassLoader(),
00096             new Class[] { aInterface, XPCOMJavaProxyBase.class },
00097             new XPCOMJavaProxy(aXPCOMInstance));
00098   }
00099 
00111   public Object invoke(Object aProxy, Method aMethod, Object[] aParams)
00112           throws Throwable {
00113     String methodName = aMethod.getName();
00114 
00115     // Handle the three java.lang.Object methods that are passed to us.
00116     if (aMethod.getDeclaringClass() == Object.class)  {
00117       if (methodName.equals("hashCode"))  {
00118         return proxyHashCode(aProxy);
00119       }
00120       if (methodName.equals("equals")) {
00121         return proxyEquals(aProxy, aParams[0]);
00122       }
00123       if (methodName.equals("toString")) {
00124         return proxyToString(aProxy);
00125       }
00126       System.err.println("WARNING: Unhandled Object method [" +
00127                          methodName + "]");
00128       return null;
00129     }
00130 
00131     // Handle the 'finalize' method called during garbage collection
00132     if (aMethod.getDeclaringClass() == XPCOMJavaProxyBase.class) {
00133       if (methodName.equals("finalize")) {
00134         finalizeProxy(aProxy);
00135       } else {
00136         System.err.println("WARNING: Unhandled XPCOMJavaProxyBase method [" +
00137                            methodName + "]");
00138       }
00139       return null;
00140     }
00141 
00142     // If not already handled, pass method calls to XPCOM object.
00143     return callXPCOMMethod(aProxy, methodName, aParams);
00144   }
00145 
00155   protected static Integer proxyHashCode(Object aProxy) {
00156     return new Integer(System.identityHashCode(aProxy));
00157   }
00158 
00170   protected static Boolean proxyEquals(Object aProxy, Object aOther) {
00171     // See if the two are the same Java object
00172     if (aProxy == aOther) {
00173       return Boolean.TRUE;
00174     } else {
00175       // If not, then see if they represent the same XPCOM object.  But first,
00176       // we need to check if |aOther| is an XPCOMJavaProxy.
00177       if (isXPCOMJavaProxy(aOther) && isSameXPCOMObject(aProxy, aOther)) {
00178         return Boolean.TRUE;
00179       }
00180     }
00181     return Boolean.FALSE;
00182   }
00183 
00192   protected static boolean isXPCOMJavaProxy(Object aObject) {
00193     if (aObject != null && Proxy.isProxyClass(aObject.getClass())) {
00194       InvocationHandler h = Proxy.getInvocationHandler(aObject);
00195       if (h instanceof XPCOMJavaProxy) {
00196         return true;
00197       }
00198     }
00199     return false;
00200   }
00201 
00212   protected static native boolean isSameXPCOMObject(Object aProxy1,
00213           Object aProxy2);
00214 
00224   protected static String proxyToString(Object aProxy) {
00225     return aProxy.getClass().getInterfaces()[0].getName() + '@' +
00226            Integer.toHexString(aProxy.hashCode());
00227   }
00228 
00235   protected void finalizeProxy(Object aProxy) throws Throwable {
00236     finalizeProxyNative(aProxy);
00237     super.finalize();
00238   }
00239 
00240   protected static native void finalizeProxyNative(Object aProxy);
00241 
00254   protected static native Object callXPCOMMethod(Object aProxy,
00255           String aMethodName, Object[] aParams);
00256 
00257 }
00258