Back to index

lightning-sunbird  0.9+nobinonly
nsJavaWrapper.cpp
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 IBM Corporation.
00017  * Portions created by the Initial Developer are Copyright (C) 2006
00018  * IBM Corporation. All Rights Reserved.
00019  *
00020  * Contributor(s):
00021  *   Javier Pedemonte (jhpedemonte@gmail.com)
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "nsJavaInterfaces.h"
00038 #include "nsJavaWrapper.h"
00039 #include "nsJavaXPTCStub.h"
00040 #include "nsJavaXPCOMBindingUtils.h"
00041 #include "jni.h"
00042 #include "xptcall.h"
00043 #include "nsIInterfaceInfoManager.h"
00044 #include "nsString.h"
00045 #include "nsCRT.h"
00046 #include "prmem.h"
00047 #include "nsServiceManagerUtils.h"
00048 #include "nsEventQueueUtils.h"
00049 #include "nsProxyRelease.h"
00050 
00051 static nsID nullID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
00052 
00053 
00054 nsresult
00055 CreateJavaArray(JNIEnv* env, PRUint8 aType, PRUint32 aSize, const nsID& aIID,
00056                 jobject* aResult)
00057 {
00058   jobject array = nsnull;
00059   switch (aType)
00060   {
00061     case nsXPTType::T_I8:
00062       array = env->NewByteArray(aSize);
00063       break;
00064 
00065     case nsXPTType::T_I16:
00066     case nsXPTType::T_U8:
00067       array = env->NewShortArray(aSize);
00068       break;
00069 
00070     case nsXPTType::T_I32:
00071     case nsXPTType::T_U16:
00072       array = env->NewIntArray(aSize);
00073       break;
00074 
00075     case nsXPTType::T_I64:
00076     case nsXPTType::T_U32:
00077       array = env->NewLongArray(aSize);
00078       break;
00079 
00080     case nsXPTType::T_FLOAT:
00081       array = env->NewFloatArray(aSize);
00082       break;
00083 
00084     // XXX how do we handle unsigned 64-bit values?
00085     case nsXPTType::T_U64:
00086     case nsXPTType::T_DOUBLE:
00087       array = env->NewDoubleArray(aSize);
00088       break;
00089 
00090     case nsXPTType::T_BOOL:
00091       array = env->NewBooleanArray(aSize);
00092       break;
00093 
00094     case nsXPTType::T_CHAR:
00095     case nsXPTType::T_WCHAR:
00096       array = env->NewCharArray(aSize);
00097       break;
00098 
00099     case nsXPTType::T_CHAR_STR:
00100     case nsXPTType::T_WCHAR_STR:
00101     case nsXPTType::T_IID:
00102     case nsXPTType::T_ASTRING:
00103     case nsXPTType::T_DOMSTRING:
00104     case nsXPTType::T_UTF8STRING:
00105     case nsXPTType::T_CSTRING:
00106       array = env->NewObjectArray(aSize, stringClass, nsnull);
00107       break;
00108 
00109     case nsXPTType::T_INTERFACE:
00110     case nsXPTType::T_INTERFACE_IS:
00111     {
00112       nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
00113       NS_ASSERTION(iim != nsnull, "Failed to get InterfaceInfoManager");
00114       if (!iim)
00115         return NS_ERROR_FAILURE;
00116 
00117       // Get interface info for given IID
00118       nsCOMPtr<nsIInterfaceInfo> info;
00119       nsresult rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
00120       if (NS_FAILED(rv))
00121         return rv;
00122 
00123       // Get interface name
00124       const char* iface_name;
00125       rv = info->GetNameShared(&iface_name);
00126       if (NS_FAILED(rv))
00127         return rv;
00128 
00129       // Create proper Java interface name
00130       nsCAutoString class_name("org/mozilla/interfaces/");
00131       class_name.AppendASCII(iface_name);
00132       jclass ifaceClass = env->FindClass(class_name.get());
00133       if (!ifaceClass)
00134         return NS_ERROR_FAILURE;
00135 
00136       array = env->NewObjectArray(aSize, ifaceClass, nsnull);
00137       break;
00138     }
00139 
00140     case nsXPTType::T_VOID:
00141       array = env->NewLongArray(aSize);
00142       break;
00143 
00144     default:
00145       NS_WARNING("unknown type");
00146       return NS_ERROR_FAILURE;
00147   }
00148 
00149   if (!array)
00150     return NS_ERROR_OUT_OF_MEMORY;
00151 
00152   *aResult = array;
00153   return NS_OK;
00154 }
00155 
00156 nsresult
00157 GetNativeArrayElement(PRUint8 aType, void* aArray, PRUint32 aIndex,
00158                       nsXPTCVariant* aResult)
00159 {
00160   switch (aType)
00161   {
00162     case nsXPTType::T_I8:
00163     case nsXPTType::T_U8:
00164       aResult->val.u8 = NS_STATIC_CAST(PRUint8*, aArray)[aIndex];
00165       break;
00166 
00167     case nsXPTType::T_I16:
00168     case nsXPTType::T_U16:
00169       aResult->val.u16 = NS_STATIC_CAST(PRUint16*, aArray)[aIndex];
00170       break;
00171 
00172     case nsXPTType::T_I32:
00173     case nsXPTType::T_U32:
00174       aResult->val.u32 = NS_STATIC_CAST(PRUint32*, aArray)[aIndex];
00175       break;
00176 
00177     case nsXPTType::T_I64:
00178     case nsXPTType::T_U64:
00179       aResult->val.u64 = NS_STATIC_CAST(PRUint64*, aArray)[aIndex];
00180       break;
00181 
00182     case nsXPTType::T_FLOAT:
00183       aResult->val.f = NS_STATIC_CAST(float*, aArray)[aIndex];
00184       break;
00185 
00186     case nsXPTType::T_DOUBLE:
00187       aResult->val.d = NS_STATIC_CAST(double*, aArray)[aIndex];
00188       break;
00189 
00190     case nsXPTType::T_BOOL:
00191       aResult->val.b = NS_STATIC_CAST(PRBool*, aArray)[aIndex];
00192       break;
00193 
00194     case nsXPTType::T_CHAR:
00195       aResult->val.c = NS_STATIC_CAST(char*, aArray)[aIndex];
00196       break;
00197 
00198     case nsXPTType::T_WCHAR:
00199       aResult->val.wc = NS_STATIC_CAST(PRUnichar*, aArray)[aIndex];
00200       break;
00201 
00202     case nsXPTType::T_CHAR_STR:
00203       aResult->val.p = NS_STATIC_CAST(char**, aArray)[aIndex];
00204       break;
00205 
00206     case nsXPTType::T_WCHAR_STR:
00207       aResult->val.p = NS_STATIC_CAST(PRUnichar**, aArray)[aIndex];
00208       break;
00209 
00210     case nsXPTType::T_IID:
00211       aResult->val.p = NS_STATIC_CAST(nsID**, aArray)[aIndex];
00212       break;
00213 
00214     case nsXPTType::T_INTERFACE:
00215     case nsXPTType::T_INTERFACE_IS:
00216       aResult->val.p = NS_STATIC_CAST(nsISupports**, aArray)[aIndex];
00217       break;
00218 
00219     case nsXPTType::T_ASTRING:
00220     case nsXPTType::T_DOMSTRING:
00221       aResult->val.p = NS_STATIC_CAST(nsString**, aArray)[aIndex];
00222       break;
00223 
00224     case nsXPTType::T_UTF8STRING:
00225     case nsXPTType::T_CSTRING:
00226       aResult->val.p = NS_STATIC_CAST(nsCString**, aArray)[aIndex];
00227       break;
00228 
00229     case nsXPTType::T_VOID:
00230       aResult->val.p = NS_STATIC_CAST(void**, aArray)[aIndex];
00231       break;
00232 
00233     default:
00234       NS_WARNING("unknown type");
00235       return NS_ERROR_FAILURE;
00236   }
00237 
00238   return NS_OK;
00239 }
00240 
00241 nsresult
00242 CreateNativeArray(PRUint8 aType, PRUint32 aSize, void** aResult)
00243 {
00244   void* array = nsnull;
00245   switch (aType)
00246   {
00247     case nsXPTType::T_I8:
00248     case nsXPTType::T_U8:
00249       array = PR_Malloc(aSize * sizeof(PRUint8));
00250       break;
00251 
00252     case nsXPTType::T_I16:
00253     case nsXPTType::T_U16:
00254       array = PR_Malloc(aSize * sizeof(PRUint16));
00255       break;
00256 
00257     case nsXPTType::T_I32:
00258     case nsXPTType::T_U32:
00259       array = PR_Malloc(aSize * sizeof(PRUint32));
00260       break;
00261 
00262     case nsXPTType::T_I64:
00263     case nsXPTType::T_U64:
00264       array = PR_Malloc(aSize * sizeof(PRUint64));
00265       break;
00266 
00267     case nsXPTType::T_FLOAT:
00268       array = PR_Malloc(aSize * sizeof(float));
00269       break;
00270 
00271     case nsXPTType::T_DOUBLE:
00272       array = PR_Malloc(aSize * sizeof(double));
00273       break;
00274 
00275     case nsXPTType::T_BOOL:
00276       array = PR_Malloc(aSize * sizeof(PRBool));
00277       break;
00278 
00279     case nsXPTType::T_CHAR:
00280       array = PR_Malloc(aSize * sizeof(char));
00281       break;
00282 
00283     case nsXPTType::T_WCHAR:
00284       array = PR_Malloc(aSize * sizeof(PRUnichar));
00285       break;
00286 
00287     case nsXPTType::T_CHAR_STR:
00288     case nsXPTType::T_WCHAR_STR:
00289     case nsXPTType::T_IID:
00290     case nsXPTType::T_ASTRING:
00291     case nsXPTType::T_DOMSTRING:
00292     case nsXPTType::T_UTF8STRING:
00293     case nsXPTType::T_CSTRING:
00294     case nsXPTType::T_INTERFACE:
00295     case nsXPTType::T_INTERFACE_IS:
00296       array = PR_Malloc(aSize * sizeof(void*));
00297       break;
00298 
00299     case nsXPTType::T_VOID:
00300       array = PR_Malloc(aSize * sizeof(void*));
00301       break;
00302 
00303     default:
00304       NS_WARNING("unknown type");
00305       return NS_ERROR_FAILURE;
00306   }
00307 
00308   if (!array)
00309     return NS_ERROR_OUT_OF_MEMORY;
00310 
00311   *aResult = array;
00312   return NS_OK;
00313 }
00314 
00318 nsresult
00319 SetupParams(JNIEnv *env, const jobject aParam, PRUint8 aType, PRBool aIsOut,
00320             const nsID& aIID, PRUint8 aArrayType, PRUint32 aArraySize,
00321             PRBool aIsArrayElement, PRUint32 aIndex, nsXPTCVariant &aVariant)
00322 {
00323   nsresult rv = NS_OK;
00324 
00325   switch (aType)
00326   {
00327     case nsXPTType::T_I8:
00328     {
00329       LOG(("byte\n"));
00330       if (!aIsOut && !aIsArrayElement) {  // 'in'
00331         aVariant.val.i8 = env->CallByteMethod(aParam, byteValueMID);
00332       } else { // 'inout' & 'array'
00333         jbyte value;
00334         if (aParam) {
00335           env->GetByteArrayRegion((jbyteArray) aParam, aIndex, 1, &value);
00336         }
00337 
00338         if (aIsOut) { // 'inout'
00339           if (aParam) {
00340             aVariant.val.i8 = value;
00341             aVariant.ptr = &aVariant.val;
00342           } else {
00343             aVariant.ptr = nsnull;
00344           }
00345           aVariant.SetPtrIsData();
00346         } else {  // 'array'
00347           NS_STATIC_CAST(PRInt8*, aVariant.val.p)[aIndex] = value;
00348         }
00349       }
00350       break;
00351     }
00352 
00353     case nsXPTType::T_I16:
00354     case nsXPTType::T_U8:   // C++ unsigned octet <=> Java short
00355     {
00356       LOG(("short\n"));
00357       if (!aIsOut && !aIsArrayElement) {  // 'in'
00358         jshort value = env->CallShortMethod(aParam, shortValueMID);
00359         if (aType == nsXPTType::T_I16)
00360           aVariant.val.i16 = value;
00361         else
00362           aVariant.val.u8 = value;
00363       } else { // 'inout' & 'array'
00364         jshort value;
00365         if (aParam) {
00366           env->GetShortArrayRegion((jshortArray) aParam, aIndex, 1, &value);
00367         }
00368 
00369         if (aIsOut) { // 'inout'
00370           if (aParam) {
00371             if (aType == nsXPTType::T_I16)
00372               aVariant.val.i16 = value;
00373             else
00374               aVariant.val.u8 = value;
00375             aVariant.ptr = &aVariant.val;
00376           } else {
00377             aVariant.ptr = nsnull;
00378           }
00379           aVariant.SetPtrIsData();
00380         } else {  // 'array'
00381           if (aType == nsXPTType::T_I16)
00382             NS_STATIC_CAST(PRInt16*, aVariant.val.p)[aIndex] = value;
00383           else
00384             NS_STATIC_CAST(PRUint8*, aVariant.val.p)[aIndex] = value;
00385         }
00386       }
00387       break;
00388     }
00389 
00390     case nsXPTType::T_I32:
00391     case nsXPTType::T_U16:  // C++ unsigned short <=> Java int
00392     {
00393       LOG(("int\n"));
00394       if (!aIsOut && !aIsArrayElement) {  // 'in'
00395         jint value = env->CallIntMethod(aParam, intValueMID);
00396         if (aType == nsXPTType::T_I32)
00397           aVariant.val.i32 = value;
00398         else
00399           aVariant.val.u16 = value;
00400       } else { // 'inout' & 'array'
00401         jint value;
00402         if (aParam) {
00403           env->GetIntArrayRegion((jintArray) aParam, aIndex, 1, &value);
00404         }
00405 
00406         if (aIsOut) { // 'inout'
00407           if (aParam) {
00408             if (aType == nsXPTType::T_I32)
00409               aVariant.val.i32 = value;
00410             else
00411               aVariant.val.u16 = value;
00412             aVariant.ptr = &aVariant.val;
00413           } else {
00414             aVariant.ptr = nsnull;
00415           }
00416           aVariant.SetPtrIsData();
00417         } else {  // 'array'
00418           if (aType == nsXPTType::T_I32)
00419             NS_STATIC_CAST(PRInt32*, aVariant.val.p)[aIndex] = value;
00420           else
00421             NS_STATIC_CAST(PRUint16*, aVariant.val.p)[aIndex] = value;
00422         }
00423       }
00424       break;
00425     }
00426 
00427     case nsXPTType::T_I64:
00428     case nsXPTType::T_U32:  // C++ unsigned int <=> Java long
00429     {
00430       LOG(("long\n"));
00431       if (!aIsOut && !aIsArrayElement) {  // 'in'
00432         jlong value = env->CallLongMethod(aParam, longValueMID);
00433         if (aType == nsXPTType::T_I64)
00434           aVariant.val.i64 = value;
00435         else
00436           aVariant.val.u32 = value;
00437       } else { // 'inout' & 'array'
00438         jlong value;
00439         if (aParam) {
00440           env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);
00441         }
00442 
00443         if (aIsOut) { // 'inout'
00444           if (aParam) {
00445             if (aType == nsXPTType::T_I64)
00446               aVariant.val.i64 = value;
00447             else
00448               aVariant.val.u32 = value;
00449             aVariant.ptr = &aVariant.val;
00450           } else {
00451             aVariant.ptr = nsnull;
00452           }
00453           aVariant.SetPtrIsData();
00454         } else {  // 'array'
00455           if (aType == nsXPTType::T_I64)
00456             NS_STATIC_CAST(PRInt64*, aVariant.val.p)[aIndex] = value;
00457           else
00458             NS_STATIC_CAST(PRUint32*, aVariant.val.p)[aIndex] = value;
00459         }
00460       }
00461       break;
00462     }
00463 
00464     case nsXPTType::T_FLOAT:
00465     {
00466       LOG(("float\n"));
00467       if (!aIsOut && !aIsArrayElement) {  // 'in'
00468         aVariant.val.f = env->CallFloatMethod(aParam, floatValueMID);
00469       } else { // 'inout' & 'array'
00470         jfloat value;
00471         if (aParam) {
00472           env->GetFloatArrayRegion((jfloatArray) aParam, aIndex, 1, &value);
00473         }
00474 
00475         if (aIsOut) { // 'inout'
00476           if (aParam) {
00477             aVariant.val.f = value;
00478             aVariant.ptr = &aVariant.val;
00479           } else {
00480             aVariant.ptr = nsnull;
00481           }
00482           aVariant.SetPtrIsData();
00483         } else {  // 'array'
00484           NS_STATIC_CAST(float*, aVariant.val.p)[aIndex] = value;
00485         }
00486       }
00487       break;
00488     }
00489 
00490     // XXX how do we handle unsigned 64-bit value?
00491     case nsXPTType::T_U64:  // C++ unsigned long <=> Java double
00492     case nsXPTType::T_DOUBLE:
00493     {
00494       LOG(("double\n"));
00495       if (!aIsOut && !aIsArrayElement) {  // 'in'
00496         jdouble value = env->CallDoubleMethod(aParam, doubleValueMID);
00497         if (aType == nsXPTType::T_DOUBLE)
00498           aVariant.val.d = value;
00499         else
00500           aVariant.val.u64 = NS_STATIC_CAST(PRUint64, value);
00501       } else { // 'inout' & 'array'
00502         jdouble value;
00503         if (aParam) {
00504           env->GetDoubleArrayRegion((jdoubleArray) aParam, aIndex, 1, &value);
00505         }
00506 
00507         if (aIsOut) { // 'inout'
00508           if (aParam) {
00509             if (aType == nsXPTType::T_DOUBLE)
00510               aVariant.val.d = value;
00511             else
00512               aVariant.val.u64 = NS_STATIC_CAST(PRUint64, value);
00513             aVariant.ptr = &aVariant.val;
00514           } else {
00515             aVariant.ptr = nsnull;
00516           }
00517           aVariant.SetPtrIsData();
00518         } else {  // 'array'
00519           if (aType == nsXPTType::T_DOUBLE)
00520             NS_STATIC_CAST(double*, aVariant.val.p)[aIndex] = value;
00521           else
00522             NS_STATIC_CAST(PRUint64*, aVariant.val.p)[aIndex] =
00523                                                 NS_STATIC_CAST(PRUint64, value);
00524         }
00525       }
00526       break;
00527     }
00528 
00529     case nsXPTType::T_BOOL:
00530     {
00531       LOG(("boolean\n"));
00532       if (!aIsOut && !aIsArrayElement) {  // 'in'
00533         aVariant.val.b = env->CallBooleanMethod(aParam, booleanValueMID);
00534       } else { // 'inout' & 'array'
00535         jboolean value;
00536         if (aParam) {
00537           env->GetBooleanArrayRegion((jbooleanArray) aParam, aIndex, 1, &value);
00538         }
00539 
00540         if (aIsOut) { // 'inout'
00541           if (aParam) {
00542             aVariant.val.b = value;
00543             aVariant.ptr = &aVariant.val;
00544           } else {
00545             aVariant.ptr = nsnull;
00546           }
00547           aVariant.SetPtrIsData();
00548         } else {  // 'array'
00549           NS_STATIC_CAST(PRBool*, aVariant.val.p)[aIndex] = value;
00550         }
00551       }
00552       break;
00553     }
00554 
00555     case nsXPTType::T_CHAR:
00556     {
00557       LOG(("char\n"));
00558       if (!aIsOut && !aIsArrayElement) {  // 'in'
00559         aVariant.val.c = env->CallCharMethod(aParam, charValueMID);
00560       } else { // 'inout' & 'array'
00561         jchar value;
00562         if (aParam) {
00563           env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);
00564         }
00565 
00566         if (aIsOut) { // 'inout'
00567           if (aParam) {
00568             aVariant.val.c = value;
00569             aVariant.ptr = &aVariant.val;
00570           } else {
00571             aVariant.ptr = nsnull;
00572           }
00573           aVariant.SetPtrIsData();
00574         } else {  // 'array'
00575           NS_STATIC_CAST(char*, aVariant.val.p)[aIndex] = value;
00576         }
00577       }
00578       break;
00579     }
00580 
00581     case nsXPTType::T_WCHAR:
00582     {
00583       LOG(("char\n"));
00584       if (!aIsOut && !aIsArrayElement) {  // 'in'
00585         aVariant.val.wc = env->CallCharMethod(aParam, charValueMID);
00586       } else { // 'inout' & 'array'
00587         jchar value;
00588         if (aParam) {
00589           env->GetCharArrayRegion((jcharArray) aParam, aIndex, 1, &value);
00590         }
00591 
00592         if (aIsOut) { // 'inout'
00593           if (aParam) {
00594             aVariant.val.wc = value;
00595             aVariant.ptr = &aVariant.val;
00596           } else {
00597             aVariant.ptr = nsnull;
00598           }
00599           aVariant.SetPtrIsData();
00600         } else {  // 'array'
00601           NS_STATIC_CAST(PRUnichar*, aVariant.val.p)[aIndex] = value;
00602         }
00603       }
00604       break;
00605     }
00606 
00607     case nsXPTType::T_CHAR_STR:
00608     case nsXPTType::T_WCHAR_STR:
00609     {
00610       LOG(("String\n"));
00611       jstring data = nsnull;
00612       if (!aIsOut && !aIsArrayElement) {  // 'in'
00613         data = (jstring) aParam;
00614       } else if (aParam) {  // 'inout' & 'array'
00615         data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
00616                                                     aIndex);
00617       }
00618 
00619       void* buf = nsnull;
00620       if (data) {
00621         jsize uniLength = env->GetStringLength(data);
00622         if (uniLength > 0) {
00623           if (aType == nsXPTType::T_CHAR_STR) {
00624             jsize utf8Length = env->GetStringUTFLength(data);
00625             buf = nsMemory::Alloc((utf8Length + 1) * sizeof(char));
00626             if (!buf) {
00627               rv = NS_ERROR_OUT_OF_MEMORY;
00628               break;
00629             }
00630 
00631             char* char_str = NS_STATIC_CAST(char*, buf);
00632             env->GetStringUTFRegion(data, 0, uniLength, char_str);
00633             char_str[utf8Length] = '\0';
00634 
00635           } else {  // if T_WCHAR_STR
00636             buf = nsMemory::Alloc((uniLength + 1) * sizeof(jchar));
00637             if (!buf) {
00638               rv = NS_ERROR_OUT_OF_MEMORY;
00639               break;
00640             }
00641 
00642             jchar* jchar_str = NS_STATIC_CAST(jchar*, buf);
00643             env->GetStringRegion(data, 0, uniLength, jchar_str);
00644             jchar_str[uniLength] = '\0';
00645           }
00646         } else {
00647           // create empty string
00648           buf = nsMemory::Alloc(2);
00649           if (!buf) {
00650             rv = NS_ERROR_OUT_OF_MEMORY;
00651             break;
00652           }
00653           ((jchar*)buf)[0] = '\0';
00654         }
00655       }
00656 
00657       if (!aIsArrayElement) { // 'in' & 'inout'
00658         aVariant.val.p = buf;
00659         if (aIsOut) { // 'inout'
00660           aVariant.ptr = &aVariant.val;
00661           aVariant.SetPtrIsData();
00662         }
00663       } else {  // 'array'
00664         if (aType == nsXPTType::T_CHAR_STR) {
00665           char* str = NS_STATIC_CAST(char*, buf);
00666           NS_STATIC_CAST(char**, aVariant.val.p)[aIndex] = str;
00667         } else {
00668           PRUnichar* str = NS_STATIC_CAST(PRUnichar*, buf);
00669           NS_STATIC_CAST(PRUnichar**, aVariant.val.p)[aIndex] = str;
00670         }
00671       }
00672       break;
00673     }
00674 
00675     case nsXPTType::T_IID:
00676     {
00677       LOG(("String(IID)\n"));
00678       jstring data = nsnull;
00679       if (!aIsOut && !aIsArrayElement) {  // 'in'
00680         data = (jstring) aParam;
00681       } else if (aParam) {  // 'inout' & 'array'
00682         data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
00683                                                     aIndex);
00684       }
00685 
00686       nsID* iid = new nsID;
00687       if (!iid) {
00688         rv = NS_ERROR_OUT_OF_MEMORY;
00689         break;
00690       }
00691       if (data) {
00692         // extract IID string from Java string
00693         const char* str = env->GetStringUTFChars(data, nsnull);
00694         if (!str) {
00695           rv = NS_ERROR_OUT_OF_MEMORY;
00696           break;
00697         }
00698 
00699         // parse string into IID object
00700         iid->Parse(str);
00701         env->ReleaseStringUTFChars(data, str);
00702       } else {
00703         *iid = nullID;
00704       }
00705 
00706       if (!aIsArrayElement) { // 'in' & 'inout'
00707         aVariant.val.p = iid;
00708         if (aIsOut) { // 'inout'
00709           aVariant.ptr = &aVariant.val;
00710           aVariant.SetPtrIsData();
00711         }
00712       } else {  // 'array'
00713         NS_STATIC_CAST(nsID**, aVariant.val.p)[aIndex] = iid;
00714       }
00715       break;
00716     }
00717 
00718     case nsXPTType::T_INTERFACE:
00719     case nsXPTType::T_INTERFACE_IS:
00720     {
00721       LOG(("nsISupports\n"));
00722       jobject java_obj = nsnull;
00723       if (!aIsOut && !aIsArrayElement) {  // 'in'
00724         java_obj = (jobject) aParam;
00725       } else if (aParam) {  // 'inout' & 'array'
00726         java_obj = (jobject) env->GetObjectArrayElement((jobjectArray) aParam,
00727                                                         aIndex);
00728       }
00729 
00730       nsISupports* xpcom_obj;
00731       if (java_obj) {
00732         // If the requested interface is nsIWeakReference, then we look for or
00733         // create a stub for the nsISupports interface.  Then we create a weak
00734         // reference from that stub.
00735         PRBool isWeakRef;
00736         nsID iid;
00737         if (aIID.Equals(NS_GET_IID(nsIWeakReference))) {
00738           isWeakRef = PR_TRUE;
00739           iid = NS_GET_IID(nsISupports);
00740         } else {
00741           isWeakRef = PR_FALSE;
00742           iid = aIID;
00743         }
00744 
00745         rv = GetNewOrUsedXPCOMObject(env, java_obj, iid, &xpcom_obj);
00746         if (NS_FAILED(rv))
00747           break;
00748 
00749         // If the function expects a weak reference, then we need to
00750         // create it here.
00751         if (isWeakRef) {
00752           nsCOMPtr<nsISupportsWeakReference> supportsweak =
00753                                                  do_QueryInterface(xpcom_obj);
00754           if (supportsweak) {
00755             nsWeakPtr weakref;
00756             supportsweak->GetWeakReference(getter_AddRefs(weakref));
00757             NS_RELEASE(xpcom_obj);
00758             xpcom_obj = weakref;
00759             NS_ADDREF(xpcom_obj);
00760           } else {
00761             xpcom_obj = nsnull;
00762           }
00763         }
00764       } else {
00765         xpcom_obj = nsnull;
00766       }
00767 
00768       if (!aIsArrayElement) { // 'in' & 'inout'
00769         aVariant.val.p = xpcom_obj;
00770         aVariant.SetValIsInterface();
00771         if (aIsOut) { // 'inout'
00772           aVariant.ptr = &aVariant.val;
00773           aVariant.SetPtrIsData();
00774         }
00775       } else {  // 'array'
00776         NS_STATIC_CAST(nsISupports**, aVariant.val.p)[aIndex] = xpcom_obj;
00777       }
00778       break;
00779     }
00780 
00781     case nsXPTType::T_ASTRING:
00782     case nsXPTType::T_DOMSTRING:
00783     {
00784       LOG(("String\n"));
00785       // Expecting only 'in' and 'in dipper'
00786       NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
00787       if (aIsOut) {
00788         rv = NS_ERROR_UNEXPECTED;
00789         break;
00790       }
00791 
00792       jstring jstr = NS_STATIC_CAST(jstring, aParam);
00793       nsAString* str = jstring_to_nsAString(env, jstr);
00794       if (!str) {
00795         rv = NS_ERROR_OUT_OF_MEMORY;
00796         break;
00797       }
00798 
00799       aVariant.val.p = str;
00800       aVariant.SetValIsDOMString();
00801       break;
00802     }
00803 
00804     case nsXPTType::T_UTF8STRING:
00805     case nsXPTType::T_CSTRING:
00806     {
00807       LOG(("StringUTF\n"));
00808       // Expecting only 'in' and 'in dipper'
00809       NS_PRECONDITION(!aIsOut, "unexpected param descriptor");
00810       if (aIsOut) {
00811         rv = NS_ERROR_UNEXPECTED;
00812         break;
00813       }
00814 
00815       jstring jstr = NS_STATIC_CAST(jstring, aParam);
00816       nsACString* str = jstring_to_nsACString(env, jstr);
00817       if (!str) {
00818         rv = NS_ERROR_OUT_OF_MEMORY;
00819         break;
00820       }
00821 
00822       aVariant.val.p = str;
00823       if (aType == nsXPTType::T_CSTRING) {
00824         aVariant.SetValIsCString();
00825       } else {
00826         aVariant.SetValIsUTF8String();
00827       }
00828       break;
00829     }
00830 
00831     // handle "void *" as an "long" in Java
00832     case nsXPTType::T_VOID:
00833     {
00834       LOG(("long (void*)\n"));
00835       if (!aIsOut && !aIsArrayElement) {  // 'in'
00836         aVariant.val.p =
00837           NS_REINTERPRET_CAST(void*, env->CallLongMethod(aParam, longValueMID));
00838       } else { // 'inout' & 'array'
00839         jlong value;
00840         if (aParam) {
00841           env->GetLongArrayRegion((jlongArray) aParam, aIndex, 1, &value);
00842         }
00843 
00844         if (aIsOut) { // 'inout'
00845           if (aParam) {
00846             aVariant.val.p = NS_REINTERPRET_CAST(void*, value);
00847             aVariant.ptr = &aVariant.val;
00848           } else {
00849             aVariant.ptr = nsnull;
00850           }
00851           aVariant.SetPtrIsData();
00852         } else {  // 'array'
00853           NS_STATIC_CAST(void**, aVariant.val.p)[aIndex] =
00854                   NS_REINTERPRET_CAST(void*, value);
00855         }
00856       }
00857       break;
00858     }
00859 
00860     case nsXPTType::T_ARRAY:
00861     {
00862       jobject sourceArray = nsnull;
00863       if (!aIsOut) {  // 'in'
00864         sourceArray = aParam;
00865       } else if (aParam) {  // 'inout'
00866         jobjectArray array = NS_STATIC_CAST(jobjectArray, aParam);
00867         sourceArray = env->GetObjectArrayElement(array, 0);
00868       }
00869 
00870       if (sourceArray) {
00871         rv = CreateNativeArray(aArrayType, aArraySize, &aVariant.val.p);
00872 
00873         for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
00874           rv = SetupParams(env, sourceArray, aArrayType, PR_FALSE, aIID, 0, 0,
00875                            PR_TRUE, i, aVariant);
00876         }
00877       }
00878 
00879       if (aIsOut) { // 'inout'
00880         aVariant.ptr = &aVariant.val.p;
00881         aVariant.SetPtrIsData();
00882       }
00883       break;
00884     }
00885 
00886     case nsXPTType::T_PSTRING_SIZE_IS:
00887     case nsXPTType::T_PWSTRING_SIZE_IS:
00888     {
00889       NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
00890       
00891       LOG(("Sized string\n"));
00892       jstring data = nsnull;
00893       if (!aIsOut) {  // 'in'
00894         data = (jstring) aParam;
00895       } else if (aParam) {  // 'inout'
00896         data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
00897                                                     aIndex);
00898       }
00899 
00900       PRUint32 length = 0;
00901       if (data) {
00902         if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
00903           length = env->GetStringUTFLength(data);
00904         } else {
00905           length = env->GetStringLength(data);
00906         }
00907         if (length > aArraySize) {
00908           rv = NS_ERROR_ILLEGAL_VALUE;
00909           break;
00910         }
00911       }
00912 
00913       PRUint32 size_of_char = (aType == nsXPTType::T_PSTRING_SIZE_IS) ?
00914                               sizeof(char) : sizeof(jchar);
00915       PRUint32 allocLength = (aArraySize + 1) * size_of_char;
00916       void* buf = nsMemory::Alloc(allocLength);
00917       if (!buf) {
00918         rv = NS_ERROR_OUT_OF_MEMORY;
00919         break;
00920       }
00921 
00922       if (data) {
00923         if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
00924           const char* str = env->GetStringUTFChars(data, nsnull);
00925           if (!str) {
00926             nsMemory::Free(buf);
00927             rv = NS_ERROR_OUT_OF_MEMORY;
00928             break;
00929           }
00930           memcpy(buf, str, length);
00931           env->ReleaseStringUTFChars(data, str);
00932         } else {
00933           jchar* jchar_str = NS_STATIC_CAST(jchar*, buf);
00934           env->GetStringRegion(data, 0, length, jchar_str);
00935         }
00936       }
00937       
00938       aVariant.val.p = buf;
00939       if (aIsOut) { // 'inout'
00940         aVariant.ptr = &aVariant.val;
00941         aVariant.SetPtrIsData();
00942       }
00943 
00944       break;
00945     }
00946 
00947     default:
00948       NS_WARNING("unexpected parameter type");
00949       return NS_ERROR_UNEXPECTED;
00950   }
00951 
00952   return rv;
00953 }
00954 
00962 nsresult
00963 FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,
00964                nsXPTCVariant &aVariant, const nsID& aIID,
00965                PRBool aIsArrayElement, PRUint8 aArrayType, PRUint32 aArraySize,
00966                PRUint32 aIndex, nsresult aInvokeResult, jobject* aParam)
00967 {
00968   nsresult rv = NS_OK;
00969 
00970   switch (aType)
00971   {
00972     case nsXPTType::T_I8:
00973     {
00974       if (NS_SUCCEEDED(aInvokeResult)) {
00975         jbyte value = aVariant.val.i8;
00976         if (aParamInfo.IsRetval() && !aIsArrayElement) {
00977           *aParam = env->NewObject(byteClass, byteInitMID, value);
00978         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
00979           env->SetByteArrayRegion((jbyteArray) *aParam, aIndex, 1, &value);
00980         }
00981       }
00982       break;
00983     }
00984 
00985     case nsXPTType::T_I16:
00986     case nsXPTType::T_U8:
00987     {
00988       if (NS_SUCCEEDED(aInvokeResult)) {
00989         jshort value = (aType == nsXPTType::T_I16) ? aVariant.val.i16 :
00990                                                      aVariant.val.u8;
00991         if (aParamInfo.IsRetval() && !aIsArrayElement) {
00992           *aParam = env->NewObject(shortClass, shortInitMID, value);
00993         } else if ((aParamInfo.IsOut() || aIsArrayElement) && aParam) {
00994           env->SetShortArrayRegion((jshortArray) *aParam, aIndex, 1, &value);
00995         }
00996       }
00997       break;
00998     }
00999 
01000     case nsXPTType::T_I32:
01001     case nsXPTType::T_U16:
01002     {
01003       if (NS_SUCCEEDED(aInvokeResult)) {
01004         jint value = (aType == nsXPTType::T_I32) ? aVariant.val.i32 :
01005                                                    aVariant.val.u16;
01006         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01007           *aParam = env->NewObject(intClass, intInitMID, value);
01008         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
01009           env->SetIntArrayRegion((jintArray) *aParam, aIndex, 1, &value);
01010         }
01011       }
01012       break;
01013     }
01014 
01015     case nsXPTType::T_I64:
01016     case nsXPTType::T_U32:
01017     {
01018       if (NS_SUCCEEDED(aInvokeResult)) {
01019         jlong value = (aType == nsXPTType::T_I64) ? aVariant.val.i64 :
01020                                                     aVariant.val.u32;
01021         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01022           *aParam = env->NewObject(longClass, longInitMID, value);
01023         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
01024           env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
01025         }
01026       }
01027       break;
01028     }
01029 
01030     case nsXPTType::T_FLOAT:
01031     {
01032       if (NS_SUCCEEDED(aInvokeResult)) {
01033         jfloat value = aVariant.val.f;
01034         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01035           *aParam = env->NewObject(floatClass, floatInitMID, value);
01036         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
01037           env->SetFloatArrayRegion((jfloatArray) *aParam, aIndex, 1, &value);
01038         }
01039       }
01040       break;
01041     }
01042 
01043     // XXX how do we handle unsigned 64-bit values?
01044     case nsXPTType::T_U64:
01045     case nsXPTType::T_DOUBLE:
01046     {
01047       if (NS_SUCCEEDED(aInvokeResult)) {
01048         jdouble value = (aType == nsXPTType::T_DOUBLE) ? aVariant.val.d :
01049                                                          aVariant.val.u64;
01050         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01051           *aParam = env->NewObject(doubleClass, doubleInitMID, value);
01052         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
01053           env->SetDoubleArrayRegion((jdoubleArray) *aParam, aIndex, 1, &value);
01054         }
01055       }
01056       break;
01057     }
01058 
01059     case nsXPTType::T_BOOL:
01060     {
01061       if (NS_SUCCEEDED(aInvokeResult)) {
01062         jboolean value = aVariant.val.b;
01063         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01064           *aParam = env->NewObject(booleanClass, booleanInitMID, value);
01065         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
01066           env->SetBooleanArrayRegion((jbooleanArray) *aParam, aIndex, 1, &value);
01067         }
01068       }
01069       break;
01070     }
01071 
01072     case nsXPTType::T_CHAR:
01073     case nsXPTType::T_WCHAR:
01074     {
01075       if (NS_SUCCEEDED(aInvokeResult)) {
01076         jchar value;
01077         if (aType == nsXPTType::T_CHAR)
01078           value = aVariant.val.c;
01079         else
01080           value = aVariant.val.wc;
01081         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01082           *aParam = env->NewObject(charClass, charInitMID, value);
01083         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
01084           env->SetCharArrayRegion((jcharArray) *aParam, aIndex, 1, &value);
01085         }
01086       }
01087       break;
01088     }
01089 
01090     case nsXPTType::T_CHAR_STR:
01091     case nsXPTType::T_WCHAR_STR:
01092     {
01093       if ((aParamInfo.IsOut() || aIsArrayElement) &&
01094           NS_SUCCEEDED(aInvokeResult))
01095       {
01096         // create new string from data
01097         jstring str = nsnull;
01098         if (aVariant.val.p) {
01099           if (aType == nsXPTType::T_CHAR_STR) {
01100             str = env->NewStringUTF((const char*) aVariant.val.p);
01101           } else {
01102             PRUint32 length = nsCRT::strlen((const PRUnichar*) aVariant.val.p);
01103             str = env->NewString((const jchar*) aVariant.val.p, length);
01104           }
01105           if (!str) {
01106             rv = NS_ERROR_OUT_OF_MEMORY;
01107             break;
01108           }
01109         }
01110 
01111         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01112           *aParam = str;
01113         } else if (*aParam) {
01114           // put new string into output array
01115           env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
01116         }
01117       }
01118 
01119       // cleanup
01120       if (aVariant.val.p)
01121         nsMemory::Free(aVariant.val.p);
01122       break;
01123     }
01124 
01125     case nsXPTType::T_IID:
01126     {
01127       nsID* iid = NS_STATIC_CAST(nsID*, aVariant.val.p);
01128 
01129       if ((aParamInfo.IsOut() || aIsArrayElement) &&
01130           NS_SUCCEEDED(aInvokeResult))
01131       {
01132         // Create the string from nsID
01133         jstring str = nsnull;
01134         if (iid) {
01135           char* iid_str = iid->ToString();
01136           if (iid_str) {
01137             str = env->NewStringUTF(iid_str);
01138           }
01139           if (!iid_str || !str) {
01140             rv = NS_ERROR_OUT_OF_MEMORY;
01141             break;
01142           }
01143           PR_Free(iid_str);
01144         }
01145 
01146         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01147           *aParam = str;
01148         } else if (*aParam) {
01149           // put new string into output array
01150           env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
01151         }
01152       }
01153 
01154       // Ordinarily, we would delete 'iid' here.  But we cannot do that until
01155       // we've handled all of the params.  See comment in CallXPCOMMethod.
01156       // We can safely delete array elements, though.
01157       if (aIsArrayElement)
01158         delete iid;
01159 
01160       break;
01161     }
01162 
01163     case nsXPTType::T_INTERFACE:
01164     case nsXPTType::T_INTERFACE_IS:
01165     {
01166       nsISupports* xpcom_obj = NS_STATIC_CAST(nsISupports*, aVariant.val.p);
01167 
01168       if ((aParamInfo.IsOut() || aIsArrayElement) &&
01169           NS_SUCCEEDED(aInvokeResult))
01170       {
01171         jobject java_obj = nsnull;
01172         if (xpcom_obj) {
01173           // Get matching Java object for given xpcom object
01174           rv = GetNewOrUsedJavaObject(env, xpcom_obj, aIID, nsnull, &java_obj);
01175           if (NS_FAILED(rv))
01176             break;
01177         }
01178 
01179         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01180           *aParam = java_obj;
01181         } else if (*aParam) {
01182           // put new Java object into output array
01183           env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, java_obj);
01184         }
01185       }
01186 
01187       // cleanup
01188       NS_IF_RELEASE(xpcom_obj);
01189       break;
01190     }
01191 
01192     case nsXPTType::T_ASTRING:
01193     case nsXPTType::T_DOMSTRING:
01194     {
01195       NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
01196       if (!aParamInfo.IsIn()) {
01197         rv = NS_ERROR_UNEXPECTED;
01198         break;
01199       }
01200 
01201       nsString* str = NS_STATIC_CAST(nsString*, aVariant.val.p);
01202       if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
01203         // Create Java string from returned nsString
01204         jstring jstr = nsnull;
01205         if (str && !str->IsVoid()) {
01206           jstr = env->NewString((const jchar*) str->get(), str->Length());
01207           if (!jstr) {
01208             rv = NS_ERROR_OUT_OF_MEMORY;
01209             break;
01210           }
01211         }
01212 
01213         *aParam = jstr;        
01214       }
01215 
01216       // cleanup
01217       if (str) {
01218         delete str;
01219       }
01220       break;
01221     }
01222 
01223     case nsXPTType::T_UTF8STRING:
01224     case nsXPTType::T_CSTRING:
01225     {
01226       NS_PRECONDITION(aParamInfo.IsIn(), "unexpected param descriptor");
01227       if (!aParamInfo.IsIn()) {
01228         rv = NS_ERROR_UNEXPECTED;
01229         break;
01230       }
01231 
01232       nsCString* str = NS_STATIC_CAST(nsCString*, aVariant.val.p);
01233       if (NS_SUCCEEDED(aInvokeResult) && aParamInfo.IsDipper()) {
01234         // Create Java string from returned nsString
01235         jstring jstr = nsnull;
01236         if (str && !str->IsVoid()) {
01237           jstr = env->NewStringUTF((const char*) str->get());
01238           if (!jstr) {
01239             rv = NS_ERROR_OUT_OF_MEMORY;
01240             break;
01241           }
01242         }
01243 
01244         *aParam = jstr;        
01245       }
01246 
01247       // cleanup
01248       if (str) {
01249         delete str;
01250       }
01251       break;
01252     }
01253 
01254     case nsXPTType::T_VOID:
01255     {
01256       if (NS_SUCCEEDED(aInvokeResult)) {
01257         jlong value = NS_REINTERPRET_CAST(jlong, aVariant.val.p);
01258         if (aParamInfo.IsRetval() && !aIsArrayElement) {
01259           *aParam = env->NewObject(longClass, longInitMID, value);
01260         } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {
01261           env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);
01262         }
01263       }
01264       break;
01265     }
01266 
01267     case nsXPTType::T_ARRAY:
01268     {
01269       if (aParamInfo.IsOut() && NS_SUCCEEDED(aInvokeResult)) {
01270         // Create Java array from returned native array
01271         jobject jarray = nsnull;
01272         if (aVariant.val.p) {
01273           rv = CreateJavaArray(env, aArrayType, aArraySize, aIID, &jarray);
01274           if (NS_FAILED(rv))
01275             break;
01276 
01277           nsXPTCVariant var;
01278           for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {
01279             rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
01280             if (NS_SUCCEEDED(rv)) {
01281               rv = FinalizeParams(env, aParamInfo, aArrayType, var, aIID,
01282                                   PR_TRUE, 0, 0, i, aInvokeResult, &jarray);
01283             }
01284           }
01285         }
01286 
01287         if (aParamInfo.IsRetval()) {
01288           *aParam = jarray;
01289         } else if (*aParam) {
01290           // put new Java array into output array
01291           env->SetObjectArrayElement((jobjectArray) *aParam, 0, jarray);
01292         }
01293       }
01294 
01295       // cleanup
01296       // If this is not an out param or if the invokeResult is a failure case,
01297       // then the array elements have not been cleaned up.  Do so now.
01298       if (!aParamInfo.IsOut() || (NS_FAILED(aInvokeResult) && aVariant.val.p)) {
01299         nsXPTCVariant var;
01300         for (PRUint32 i = 0; i < aArraySize; i++) {
01301           rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
01302           if (NS_SUCCEEDED(rv)) {
01303             FinalizeParams(env, aParamInfo, aArrayType, var, aIID, PR_TRUE,
01304                            0, 0, i, NS_ERROR_FAILURE, nsnull);
01305           }
01306         }
01307       }
01308       PR_Free(aVariant.val.p);
01309       break;
01310     }
01311 
01312     case nsXPTType::T_PSTRING_SIZE_IS:
01313     case nsXPTType::T_PWSTRING_SIZE_IS:
01314     {
01315       NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
01316 
01317       if ((aParamInfo.IsOut()) && NS_SUCCEEDED(aInvokeResult))
01318       {
01319         // create new string from data
01320         jstring str = nsnull;
01321         if (aVariant.val.p) {
01322           if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
01323             PRUint32 len = (aArraySize + 1) * sizeof(char);
01324             char* buf = (char*) nsMemory::Alloc(len);
01325             if (buf) {
01326               memcpy(buf, aVariant.val.p, len);
01327               buf[aArraySize] = '\0';
01328               str = env->NewStringUTF((const char*) buf);
01329               nsMemory::Free(buf);
01330             }
01331           } else {
01332             str = env->NewString((const jchar*) aVariant.val.p, aArraySize);
01333           }
01334           if (!str) {
01335             rv = NS_ERROR_OUT_OF_MEMORY;
01336             break;
01337           }
01338         }
01339 
01340         if (aParamInfo.IsRetval()) {
01341           *aParam = str;
01342         } else if (*aParam) {
01343           // put new string into output array
01344           env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
01345         }
01346       }
01347 
01348       // cleanup
01349       if (aVariant.val.p)
01350         nsMemory::Free(aVariant.val.p);
01351       break;
01352     }
01353 
01354     default:
01355       NS_WARNING("unexpected parameter type");
01356       return NS_ERROR_UNEXPECTED;
01357   }
01358 
01359   // Check for Java exception, but don't overwrite pre-existing error code.
01360   if (NS_SUCCEEDED(rv) && env->ExceptionCheck())
01361     rv = NS_ERROR_FAILURE;
01362 
01363   return rv;
01364 }
01365 
01366 nsresult
01367 QueryAttributeInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
01368                    PRBool aCapitalizedAttr, PRUint16* aMethodIndex,
01369                    const nsXPTMethodInfo** aMethodInfo)
01370 
01371 {
01372   nsresult rv = NS_ERROR_FAILURE;
01373 
01374   // An 'attribute' will start with either "get" or "set".  But first,
01375   // we check the length, in order to skip over method names that match exactly
01376   // "get" or "set".
01377   if (strlen(aMethodName) > 3) {
01378     if (strncmp("get", aMethodName, 3) == 0) {
01379       char* getterName = strdup(aMethodName + 3);
01380       if (!aCapitalizedAttr) {
01381         getterName[0] = tolower(getterName[0]);
01382       }
01383       rv = aIInfo->GetMethodInfoForName(getterName, aMethodIndex, aMethodInfo);
01384       free(getterName);
01385     } else if (strncmp("set", aMethodName, 3) == 0) {
01386       char* setterName = strdup(aMethodName + 3);
01387       if (!aCapitalizedAttr) {
01388         setterName[0] = tolower(setterName[0]);
01389       }
01390       rv = aIInfo->GetMethodInfoForName(setterName, aMethodIndex, aMethodInfo);
01391       if (NS_SUCCEEDED(rv)) {
01392         // If this succeeded, GetMethodInfoForName will have returned the
01393         // method info for the 'getter'.  We want the 'setter', so increase
01394         // method index by one ('setter' immediately follows the 'getter'),
01395         // and get its method info.
01396         (*aMethodIndex)++;
01397         rv = aIInfo->GetMethodInfo(*aMethodIndex, aMethodInfo);
01398         if (NS_SUCCEEDED(rv)) {
01399           // Double check that this methodInfo matches the given method.
01400           if (!(*aMethodInfo)->IsSetter() ||
01401               strcmp(setterName, (*aMethodInfo)->name) != 0) {
01402             rv = NS_ERROR_FAILURE;
01403           }
01404         }
01405       }
01406       free(setterName);
01407     }
01408   }
01409 
01410   return rv;
01411 }
01412 
01421 nsresult
01422 QueryMethodInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
01423                 PRUint16* aMethodIndex, const nsXPTMethodInfo** aMethodInfo)
01424 {
01425   // Skip over any leading underscores, since these are methods that conflicted
01426   // with existing Java keywords
01427   const char* methodName = aMethodName;
01428   if (methodName[0] == '_') {
01429     methodName++;
01430   }
01431 
01432   // The common case is that the method name is lower case, so we check
01433   // that first.
01434   nsresult rv;
01435   rv = aIInfo->GetMethodInfoForName(methodName, aMethodIndex, aMethodInfo);
01436   if (NS_SUCCEEDED(rv))
01437     return rv;
01438 
01439   // If there is no method called <aMethodName>, then maybe it is an
01440   // 'attribute'.
01441   rv = QueryAttributeInfo(aIInfo, methodName, PR_FALSE, aMethodIndex,
01442                           aMethodInfo);
01443   if (NS_SUCCEEDED(rv))
01444     return rv;
01445 
01446   // If we get here, then maybe the method name is capitalized.
01447   char* name = strdup(methodName);
01448   name[0] = toupper(name[0]);
01449   rv = aIInfo->GetMethodInfoForName(name, aMethodIndex, aMethodInfo);
01450   free(name);
01451   if (NS_SUCCEEDED(rv))
01452     return rv;
01453 
01454   // If there is no method called <aMethodName>, then maybe it is an
01455   // 'attribute'.
01456   rv = QueryAttributeInfo(aIInfo, methodName, PR_TRUE, aMethodIndex,
01457                           aMethodInfo);
01458 
01459   return rv;
01460 }
01461 
01465 extern "C" NS_EXPORT jobject JNICALL
01466 JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
01467                                    jstring aMethodName, jobjectArray aParams)
01468 {
01469   nsresult rv;
01470 
01471   // Get native XPCOM instance
01472   void* xpcom_obj;
01473   rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
01474   if (NS_FAILED(rv)) {
01475     ThrowException(env, 0, "Failed to get matching XPCOM object");
01476     return nsnull;
01477   }
01478   JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);
01479 
01480   // Get method info
01481   PRUint16 methodIndex;
01482   const nsXPTMethodInfo* methodInfo;
01483   nsIInterfaceInfo* iinfo = inst->InterfaceInfo();
01484   const char* methodName = env->GetStringUTFChars(aMethodName, nsnull);
01485   rv = QueryMethodInfo(iinfo, methodName, &methodIndex, &methodInfo);
01486   env->ReleaseStringUTFChars(aMethodName, methodName);
01487 
01488   if (NS_FAILED(rv)) {
01489     ThrowException(env, rv, "GetMethodInfoForName failed");
01490     return nsnull;
01491   }
01492 
01493 #ifdef DEBUG_JAVAXPCOM
01494   const char* ifaceName;
01495   iinfo->GetNameShared(&ifaceName);
01496   LOG(("===> (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
01497 #endif
01498 
01499   // Convert the Java params
01500   PRUint8 paramCount = methodInfo->GetParamCount();
01501   nsXPTCVariant* params = nsnull;
01502   if (paramCount)
01503   {
01504     params = new nsXPTCVariant[paramCount];
01505     if (!params) {
01506       ThrowException(env, NS_ERROR_OUT_OF_MEMORY, "Can't create params array");
01507       return nsnull;
01508     }
01509     memset(params, 0, paramCount * sizeof(nsXPTCVariant));
01510 
01511     PRBool foundDependentParam = PR_FALSE;
01512     for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
01513     {
01514       LOG(("\t Param %d: ", i));
01515       const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
01516       params[i].type = paramInfo.GetType();
01517 
01518       if (params[i].type.IsDependent() && paramInfo.IsIn()) {
01519         foundDependentParam = PR_TRUE;
01520         continue;
01521       }
01522       
01523       if (paramInfo.IsIn()) {
01524         PRUint8 type = params[i].type.TagPart();
01525 
01526         // get IID for interface params
01527         nsID iid;
01528         if (type == nsXPTType::T_INTERFACE) {
01529           rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
01530                                     methodIndex, params, PR_TRUE, iid);
01531         }
01532 
01533         if (NS_SUCCEEDED(rv)) {
01534           jobject param = nsnull;
01535           if (aParams && !paramInfo.IsRetval()) {
01536             param = env->GetObjectArrayElement(aParams, i);
01537           }
01538           rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, 0, 0,
01539                            PR_FALSE, 0, params[i]);
01540         }
01541       } else {
01542         LOG(("out/retval\n"));
01543         params[i].ptr = &(params[i].val);
01544         params[i].SetPtrIsData();
01545       }
01546     }
01547     
01548     // Handle any dependent params by doing a second pass
01549     if (foundDependentParam) {
01550       
01551       for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++) {
01552         
01553         const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
01554         params[j].type = paramInfo.GetType();
01555 
01556         if (!params[j].type.IsDependent())
01557           continue;
01558 
01559         if (paramInfo.IsIn()) {
01560           PRUint8 type = params[j].type.TagPart();
01561 
01562           // is paramater an array or sized string?
01563           PRUint8 arrayType = 0;
01564           PRUint32 arraySize = 0;
01565           PRBool isArray = params[j].type.IsArray();
01566           PRBool isSizedString = isArray ? PR_FALSE :
01567                    type == nsXPTType::T_PSTRING_SIZE_IS ||
01568                    type == nsXPTType::T_PWSTRING_SIZE_IS;
01569 
01570           if (isArray) {
01571             // get array type
01572             nsXPTType xpttype;
01573             rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &xpttype);
01574             if (NS_FAILED(rv))
01575               break;
01576             arrayType = xpttype.TagPart();
01577             // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
01578             // therefore, treat as a signed 8bit value
01579             if (arrayType == nsXPTType::T_U8)
01580               arrayType = nsXPTType::T_I8;
01581           }
01582 
01583           if (isArray || isSizedString) {
01584             // get size of array or string
01585             PRUint8 argnum;
01586             rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
01587                                                    &argnum);
01588             if (NS_FAILED(rv))
01589               break;
01590             arraySize = params[argnum].val.u32;
01591           }
01592 
01593           // get IID for interface params
01594           nsID iid;
01595           if (type == nsXPTType::T_INTERFACE_IS ||
01596               type == nsXPTType::T_ARRAY &&
01597                 (arrayType == nsXPTType::T_INTERFACE ||
01598                  arrayType == nsXPTType::T_INTERFACE_IS))
01599           {
01600             PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
01601             rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
01602                                       methodIndex, params, PR_TRUE, iid);
01603           }
01604 
01605           if (NS_SUCCEEDED(rv)) {
01606             jobject param = nsnull;
01607             if (aParams && !paramInfo.IsRetval()) {
01608               param = env->GetObjectArrayElement(aParams, j);
01609             }
01610             rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, arrayType,
01611                              arraySize, PR_FALSE, 0, params[j]);
01612           }
01613         }
01614       }
01615     }
01616     
01617     if (NS_FAILED(rv)) {
01618       ThrowException(env, rv, "SetupParams failed");
01619       return nsnull;
01620     }
01621   }
01622 
01623   // Call the XPCOM method
01624   const nsIID* iid;
01625   iinfo->GetIIDShared(&iid);
01626   nsISupports* realObject;
01627   rv = inst->GetInstance()->QueryInterface(*iid, (void**) &realObject);
01628   if (NS_FAILED(rv)) {
01629     ThrowException(env, rv, "Failed to get real XPCOM object");
01630     return nsnull;
01631   }
01632   nsresult invokeResult = XPTC_InvokeByIndex(realObject, methodIndex,
01633                                              paramCount, params);
01634   NS_RELEASE(realObject);
01635 
01636   // Clean up params
01637   jobject result = nsnull;
01638   for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
01639   {
01640     const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
01641     PRUint8 type = paramInfo.GetType().TagPart();
01642 
01643     // is paramater an array or sized string?
01644     PRUint8 arrayType = 0;
01645     PRUint32 arraySize = 0;
01646     PRBool isArray = params[i].type.IsArray();
01647     PRBool isSizedString = isArray ? PR_FALSE :
01648              type == nsXPTType::T_PSTRING_SIZE_IS ||
01649              type == nsXPTType::T_PWSTRING_SIZE_IS;
01650 
01651     if (isArray) {
01652       // get array type
01653       nsXPTType array_xpttype;
01654       rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &array_xpttype);
01655       if (NS_FAILED(rv))
01656         break;
01657       arrayType = array_xpttype.TagPart();
01658       // IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
01659       // therefore, treat as a signed 8bit value
01660       if (arrayType == nsXPTType::T_U8)
01661         arrayType = nsXPTType::T_I8;
01662     }
01663 
01664     if (isArray || isSizedString) {
01665       // get size of array
01666       PRUint8 argnum;
01667       rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
01668                                              &argnum);
01669       if (NS_FAILED(rv))
01670         break;
01671       arraySize = params[argnum].val.u32;
01672     }
01673 
01674     // get IID for interface params
01675     nsID iid;
01676     if (type == nsXPTType::T_INTERFACE || type == nsXPTType::T_INTERFACE_IS ||
01677         type == nsXPTType::T_ARRAY && (arrayType == nsXPTType::T_INTERFACE ||
01678                                        arrayType == nsXPTType::T_INTERFACE_IS))
01679     {
01680       PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
01681       rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
01682                                 methodIndex, params, PR_TRUE, iid);
01683       if (NS_FAILED(rv))
01684         break;
01685     }
01686 
01687     jobject* javaElement;
01688     if (!paramInfo.IsRetval()) {
01689       jobject element = env->GetObjectArrayElement(aParams, i);
01690       javaElement = &element;
01691     } else {
01692       javaElement = &result;
01693     }
01694     rv = FinalizeParams(env, paramInfo, type, params[i], iid, PR_FALSE,
01695                         arrayType, arraySize, 0, invokeResult, javaElement);
01696   }
01697 
01698   // Normally, we would delete any created nsID object in the above loop.
01699   // However, GetIIDForMethodParam may need some of the nsID params when it's
01700   // looking for the IID of an INTERFACE_IS.  Therefore, we can't delete it
01701   // until we've gone through the 'Finalize' loop once and created the result.
01702   for (PRUint8 j = 0; j < paramCount; j++)
01703   {
01704     const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
01705     const nsXPTType &type = paramInfo.GetType();
01706     if (type.TagPart() == nsXPTType::T_IID) {
01707       nsID* iid = (nsID*) params[j].val.p;
01708       delete iid;
01709     }
01710   }
01711 
01712   if (params) {
01713     delete params;
01714   }
01715 
01716   // If the XPCOM method invocation failed, we don't immediately throw an
01717   // exception and return so that we can clean up any parameters.
01718   if (NS_FAILED(invokeResult)) {
01719     nsCAutoString message("The function \"");
01720     message.AppendASCII(methodInfo->GetName());
01721     message.AppendLiteral("\" returned an error condition");
01722     ThrowException(env, invokeResult, message.get());
01723   }
01724   if (NS_FAILED(rv)) {
01725     ThrowException(env, rv, "FinalizeParams failed");
01726     return nsnull;
01727   }
01728 
01729   LOG(("<=== (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
01730   return result;
01731 }
01732 
01733 nsresult
01734 CreateJavaProxy(JNIEnv* env, nsISupports* aXPCOMObject, const nsIID& aIID,
01735                 jobject aObjectLoader, jobject* aResult)
01736 {
01737   NS_PRECONDITION(aResult != nsnull, "null ptr");
01738   if (!aResult)
01739     return NS_ERROR_NULL_POINTER;
01740 
01741   nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
01742   NS_ASSERTION(iim != nsnull, "Failed to get InterfaceInfoManager");
01743   if (!iim)
01744     return NS_ERROR_FAILURE;
01745 
01746   // Get interface info for class
01747   nsCOMPtr<nsIInterfaceInfo> info;
01748   nsresult rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
01749   if (NS_FAILED(rv))
01750     return rv;
01751 
01752   // Wrap XPCOM object (addrefs aXPCOMObject)
01753   JavaXPCOMInstance* inst = new JavaXPCOMInstance(aXPCOMObject, info);
01754   if (!inst)
01755     return NS_ERROR_OUT_OF_MEMORY;
01756 
01757   // Get interface name
01758   const char* iface_name;
01759   rv = info->GetNameShared(&iface_name);
01760 
01761   if (NS_SUCCEEDED(rv)) {
01762     jobject java_obj = nsnull;
01763 
01764     // Create proper Java interface name
01765     nsCAutoString class_name("org.mozilla.interfaces.");
01766     class_name.AppendASCII(iface_name);
01767     jclass ifaceClass = FindClassInLoader(env, aObjectLoader, class_name.get());
01768 
01769     if (ifaceClass) {
01770       java_obj = env->CallStaticObjectMethod(xpcomJavaProxyClass,
01771                                              createProxyMID, ifaceClass,
01772                                              NS_REINTERPRET_CAST(jlong, inst));
01773       if (env->ExceptionCheck())
01774         java_obj = nsnull;
01775     }
01776 
01777     if (java_obj) {
01778 #ifdef DEBUG_JAVAXPCOM
01779       char* iid_str = aIID.ToString();
01780       LOG(("+ CreateJavaProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
01781            (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
01782                                                java_obj),
01783            (PRUint32) aXPCOMObject, iid_str));
01784       PR_Free(iid_str);
01785 #endif
01786 
01787       // Associate XPCOM object with Java proxy
01788       rv = gNativeToJavaProxyMap->Add(env, aXPCOMObject, aIID, java_obj);
01789       if (NS_SUCCEEDED(rv)) {
01790         *aResult = java_obj;
01791         return NS_OK;
01792       }
01793     } else {
01794       rv = NS_ERROR_FAILURE;
01795     }
01796   }
01797 
01798   // If there was an error, clean up.
01799   delete inst;
01800   return rv;
01801 }
01802 
01803 nsresult
01804 GetXPCOMInstFromProxy(JNIEnv* env, jobject aJavaObject, void** aResult)
01805 {
01806   NS_PRECONDITION(aResult != nsnull, "null ptr");
01807   if (!aResult)
01808     return NS_ERROR_NULL_POINTER;
01809 
01810   jlong xpcom_obj = env->CallStaticLongMethod(xpcomJavaProxyClass,
01811                                             getNativeXPCOMInstMID, aJavaObject);
01812 
01813   if (!xpcom_obj || env->ExceptionCheck()) {
01814     return NS_ERROR_FAILURE;
01815   }
01816 
01817   *aResult = NS_REINTERPRET_CAST(void*, xpcom_obj);
01818 #ifdef DEBUG_JAVAXPCOM
01819   JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, *aResult);
01820   nsIID* iid;
01821   inst->InterfaceInfo()->GetInterfaceIID(&iid);
01822   char* iid_str = iid->ToString();
01823   LOG(("< GetXPCOMInstFromProxy (Java=%08x | XPCOM=%08x | IID=%s)\n",
01824        (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
01825                                            aJavaObject),
01826        (PRUint32) inst->GetInstance(), iid_str));
01827   PR_Free(iid_str);
01828   nsMemory::Free(iid);
01829 #endif
01830   return NS_OK;
01831 }
01832 
01836 extern "C" NS_EXPORT void JNICALL
01837 JAVAPROXY_NATIVE(finalizeProxy) (JNIEnv *env, jclass that, jobject aJavaProxy)
01838 {
01839 #ifdef DEBUG_JAVAXPCOM
01840   PRUint32 xpcom_addr = 0;
01841 #endif
01842 
01843   // Due to Java's garbage collection, this finalize statement may get called
01844   // after FreeJavaGlobals().  So check to make sure that everything is still
01845   // initialized.
01846   if (gJavaXPCOMLock) {
01847     nsAutoLock lock(gJavaXPCOMLock);
01848 
01849     // If may be possible for the lock to be acquired here when FreeGlobals is
01850     // in the middle of running.  If so, then this thread will sleep until
01851     // FreeGlobals releases its lock.  At that point, we resume this thread
01852     // here, but JavaXPCOM may no longer be initialized.  So we need to check
01853     // that everything is legit after acquiring the lock.
01854     if (gJavaXPCOMInitialized) {
01855       // Get native XPCOM instance
01856       void* xpcom_obj;
01857       nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
01858       if (NS_SUCCEEDED(rv)) {
01859         JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);
01860 #ifdef DEBUG_JAVAXPCOM
01861         xpcom_addr = NS_REINTERPRET_CAST(PRUint32, inst->GetInstance());
01862 #endif
01863         nsIID* iid;
01864         rv = inst->InterfaceInfo()->GetInterfaceIID(&iid);
01865         if (NS_SUCCEEDED(rv)) {
01866           rv = gNativeToJavaProxyMap->Remove(env, inst->GetInstance(), *iid);
01867           nsMemory::Free(iid);
01868         }
01869         NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to RemoveJavaProxy");
01870         // Release gJavaXPCOMLock before deleting inst (see bug 340022)
01871         lock.unlock();
01872         delete inst;
01873       }
01874     }
01875   }
01876 
01877 #ifdef DEBUG_JAVAXPCOM
01878   LOG(("- Finalize (Java=%08x | XPCOM=%08x)\n",
01879        (PRUint32) env->CallStaticIntMethod(systemClass, hashCodeMID,
01880                                            aJavaProxy),
01881        xpcom_addr));
01882 #endif
01883 }
01884 
01888 extern "C" NS_EXPORT jboolean JNICALL
01889 JAVAPROXY_NATIVE(isSameXPCOMObject) (JNIEnv *env, jclass that,
01890                                      jobject aProxy1, jobject aProxy2)
01891 {
01892   void* xpcom_obj1;
01893   nsresult rv = GetXPCOMInstFromProxy(env, aProxy1, &xpcom_obj1);
01894   if (NS_SUCCEEDED(rv)) {
01895     void* xpcom_obj2;
01896     rv = GetXPCOMInstFromProxy(env, aProxy2, &xpcom_obj2);
01897     if (NS_SUCCEEDED(rv)) {
01898       JavaXPCOMInstance* inst1 = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj1);
01899       JavaXPCOMInstance* inst2 = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj2);
01900       if (inst1->GetInstance() == inst2->GetInstance()) {
01901         return JNI_TRUE;
01902       }
01903     }
01904   }
01905   return JNI_FALSE;
01906 }
01907 
01911 extern "C" NS_EXPORT void JNICALL
01912 LOCKPROXY_NATIVE(release) (JNIEnv *env, jclass that, jlong aLockObject)
01913 {
01914   // Need to release object on the main thread.
01915   nsCOMPtr<nsIEventQueue> eventQ;
01916   nsresult rv = NS_GetMainEventQ(getter_AddRefs(eventQ));
01917   if (NS_SUCCEEDED(rv)) {
01918     rv = NS_ProxyRelease(eventQ, NS_REINTERPRET_CAST(nsISupports*, aLockObject));
01919   }
01920   NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to release using NS_ProxyRelease");
01921 }
01922