if (xpcom_obj && aVariant.IsValAllocated()) { NS_RELEASE(xpcom_obj); }
NS_IF_RELEASE(xpcom_obj);
FinalizeParams(JNIEnv *env, const jobject aParam,                const nsXPTParamInfo &aParamInfo,                const nsXPTMethodInfo* aMethodInfo,                nsIInterfaceInfo* aIInfo,                PRUint16 aMethodIndex,                nsXPTCVariant* aDispatchParams,                nsXPTCVariant &aVariant){  nsresult rv = NS_OK;  const nsXPTType &type = aParamInfo.GetType();  PRUint8 tag = type.TagPart();  switch (tag)  {    case nsXPTType::T_I8:    case nsXPTType::T_U8:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetByteArrayRegion((jbyteArray) aParam, 0, 1,                                (jbyte*) aVariant.ptr);      }    }    break;    case nsXPTType::T_I16:    case nsXPTType::T_U16:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetShortArrayRegion((jshortArray) aParam, 0, 1,                                 (jshort*) aVariant.ptr);      }    }    break;    case nsXPTType::T_I32:    case nsXPTType::T_U32:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetIntArrayRegion((jintArray) aParam, 0, 1,                               (jint*) aVariant.ptr);      }    }    break;    case nsXPTType::T_I64:    case nsXPTType::T_U64:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetLongArrayRegion((jlongArray) aParam, 0, 1,                                (jlong*) aVariant.ptr);      }    }    break;    case nsXPTType::T_FLOAT:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetFloatArrayRegion((jfloatArray) aParam, 0, 1,                                 (jfloat*) aVariant.ptr);      }    }    break;    case nsXPTType::T_DOUBLE:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetDoubleArrayRegion((jdoubleArray) aParam, 0, 1,                                  (jdouble*) aVariant.ptr);      }    }    break;    case nsXPTType::T_BOOL:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetBooleanArrayRegion((jbooleanArray) aParam, 0, 1,                                   (jboolean*) aVariant.ptr);      }    }    break;    case nsXPTType::T_CHAR:    case nsXPTType::T_WCHAR:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetCharArrayRegion((jcharArray) aParam, 0, 1,                                (jchar*) aVariant.ptr);      }    }    break;    case nsXPTType::T_CHAR_STR:    case nsXPTType::T_WCHAR_STR:    {      if (aParamInfo.IsOut() && aParam) {  // ''inout' & 'out'        // create new string from data        jstring str;        if (aVariant.val.p) {          if (tag == nsXPTType::T_CHAR_STR) {            str = env->NewStringUTF((const char*) aVariant.val.p);          } else {            PRUint32 length = nsCRT::strlen((const PRUnichar*) aVariant.val.p);            str = env->NewString((const jchar*) aVariant.val.p, length);          }          nsMemory::Free(aVariant.val.p);          if (!str) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }        } else {          str = nsnull;        }        // put new string into output array        env->SetObjectArrayElement((jobjectArray) aParam, 0, str);      }      // Delete for 'in', 'inout', and 'out'      if (aVariant.val.p)        nsMemory::Free(aVariant.val.p);    }    break;    case nsXPTType::T_IID:    {      nsID* iid = (nsID*) aVariant.val.p;      if (aParamInfo.IsOut() && aParam) {  // 'inout' & 'out'        // Create the string from nsID        jstring str = nsnull;        if (iid) {          char* iid_str = iid->ToString();          if (iid_str) {            str = env->NewStringUTF(iid_str);          }          if (!iid_str || !str) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }          PR_Free(iid_str);        }        // put new string into output array        env->SetObjectArrayElement((jobjectArray) aParam, 0, str);      }      // Ordinarily, we would delete 'iid' here.  But we cannot do that until      // we've handled all of the params.  See comment in CallXPCOMMethod    }    break;    case nsXPTType::T_INTERFACE:    case nsXPTType::T_INTERFACE_IS:    {      nsISupports* xpcom_obj = NS_STATIC_CAST(nsISupports*, aVariant.val.p);      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        jobject java_obj = nsnull;        if (xpcom_obj) {          nsID iid;          rv = GetIIDForMethodParam(aIInfo, aMethodInfo, aParamInfo,                                    aMethodIndex, aDispatchParams, PR_TRUE, iid);          if (NS_FAILED(rv))            break;          // Get matching Java object for given xpcom object          PRBool isNewProxy;          rv = GetNewOrUsedJavaObject(env, xpcom_obj, iid, &java_obj,                                      &isNewProxy);          if (NS_FAILED(rv))            break;          if (isNewProxy)            NS_RELEASE(xpcom_obj);   // Java proxy owns ref to object        }        // put new Java object into output array        env->SetObjectArrayElement((jobjectArray) aParam, 0, java_obj);      }      // If VAL_IS_ALLOCD is set, that means that an XPCOM object was created      // is SetupParams that now needs to be released.      if (xpcom_obj && aVariant.IsValAllocated()) {        NS_RELEASE(xpcom_obj);      }    }    break;    case nsXPTType::T_ASTRING:    case nsXPTType::T_DOMSTRING:    {      nsString* str = (nsString*) aVariant.val.p;      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        // Create Java string from returned nsString        jstring jstr;        if (str) {          jstr = env->NewString((const jchar*) str->get(), str->Length());          if (!jstr) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }        } else {          jstr = nsnull;        }        // put new Java string into output array        env->SetObjectArrayElement((jobjectArray) aParam, 0, jstr);      }      if (str) {        delete str;      }    }    break;    case nsXPTType::T_UTF8STRING:    case nsXPTType::T_CSTRING:    {      nsCString* str = (nsCString*) aVariant.val.p;      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        // Create Java string from returned nsString        jstring jstr;        if (str) {          jstr = env->NewStringUTF((const char*) str->get());          if (!jstr) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }        } else {          jstr = nsnull;        }        // put new Java string into output array        env->SetObjectArrayElement((jobjectArray) aParam, 0, jstr);      }      if (str) {        delete str;      }    }    break;    case nsXPTType::T_VOID:    {      if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'        env->SetIntArrayRegion((jintArray) aParam, 0, 1,                               (jint*) aVariant.ptr);      }    }    break;  }  return rv;}