if (!aParamInfo.IsOut() || NS_FAILED(aInvokeResult)) { nsXPTCVariant var; for (PRUint32 i = 0; i < aArraySize; i++) { rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var); if (NS_SUCCEEDED(rv)) { FinalizeParams(env, aParamInfo, aArrayType, var, aIID, PR_TRUE, 0, 0, i, NS_ERROR_FAILURE, nsnull); } } }
FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,               nsXPTCVariant &aVariant, const nsID& aIID,               PRBool aIsArrayElement, PRUint8 aArrayType, PRUint32 aArraySize,               PRUint32 aIndex, nsresult aInvokeResult, jobject* aParam){  nsresult rv = NS_OK;  switch (aType)  {    case nsXPTType::T_I8:    case nsXPTType::T_U8:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jbyte value = aVariant.val.u8;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(byteClass, byteInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetByteArrayRegion((jbyteArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_I16:    case nsXPTType::T_U16:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jshort value = aVariant.val.u16;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(shortClass, shortInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && aParam) {          env->SetShortArrayRegion((jshortArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_I32:    case nsXPTType::T_U32:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jint value = aVariant.val.u32;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(intClass, intInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetIntArrayRegion((jintArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_I64:    case nsXPTType::T_U64:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jlong value = aVariant.val.u64;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(longClass, longInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetLongArrayRegion((jlongArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_FLOAT:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jfloat value = aVariant.val.f;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(floatClass, floatInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetFloatArrayRegion((jfloatArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_DOUBLE:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jdouble value = aVariant.val.d;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(doubleClass, doubleInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetDoubleArrayRegion((jdoubleArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_BOOL:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jboolean value = aVariant.val.b;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(booleanClass, booleanInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetBooleanArrayRegion((jbooleanArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_CHAR:    case nsXPTType::T_WCHAR:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jchar value;        if (aType == nsXPTType::T_CHAR)          value = aVariant.val.c;        else          value = aVariant.val.wc;        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(charClass, charInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetCharArrayRegion((jcharArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_CHAR_STR:    case nsXPTType::T_WCHAR_STR:    {      if ((aParamInfo.IsOut() || aIsArrayElement) &&          NS_SUCCEEDED(aInvokeResult))      {        // create new string from data        jstring str = nsnull;        if (aVariant.val.p) {          if (aType == 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);          }          if (!str) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }        }        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = str;        } else if (*aParam) {          // put new string into output array          env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);        }      }      // cleanup      if (aVariant.val.p)        nsMemory::Free(aVariant.val.p);      break;    }    case nsXPTType::T_IID:    {      nsID* iid = NS_STATIC_CAST(nsID*, aVariant.val.p);      if ((aParamInfo.IsOut() || aIsArrayElement) &&          NS_SUCCEEDED(aInvokeResult))      {        // 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);        }        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = str;        } else if (*aParam) {          // put new string into output array          env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, 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() || aIsArrayElement) &&          NS_SUCCEEDED(aInvokeResult))      {        jobject java_obj = nsnull;        if (xpcom_obj) {          // Get matching Java object for given xpcom object          rv = GetNewOrUsedJavaObject(env, xpcom_obj, aIID, &java_obj);          if (NS_FAILED(rv))            break;        }        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = java_obj;        } else if (*aParam) {          // put new Java object into output array          env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, java_obj);        }      }      // cleanup      NS_IF_RELEASE(xpcom_obj);      break;    }    case nsXPTType::T_ASTRING:    case nsXPTType::T_DOMSTRING:    {      nsString* str = NS_STATIC_CAST(nsString*, aVariant.val.p);      if ((aParamInfo.IsOut() || aParamInfo.IsDipper() || aIsArrayElement) &&          NS_SUCCEEDED(aInvokeResult))      {        // Create Java string from returned nsString        jstring jstr = nsnull;        if (str) {          jstr = env->NewString((const jchar*) str->get(), str->Length());          if (!jstr) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }        }        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = jstr;        } else if (*aParam) {          // put new Java string into output array          env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, jstr);        }      }      // cleanup      if (str) {        delete str;      }      break;    }    case nsXPTType::T_UTF8STRING:    case nsXPTType::T_CSTRING:    {      nsCString* str = NS_STATIC_CAST(nsCString*, aVariant.val.p);      if ((aParamInfo.IsOut() || aParamInfo.IsDipper() || aIsArrayElement) &&          NS_SUCCEEDED(aInvokeResult))      {        // Create Java string from returned nsString        jstring jstr = nsnull;        if (str) {          jstr = env->NewStringUTF((const char*) str->get());          if (!jstr) {            rv = NS_ERROR_OUT_OF_MEMORY;            break;          }        }        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = jstr;        } else if (*aParam) {          // put new Java string into output array          env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, jstr);        }      }      // cleanup      if (str) {        delete str;      }      break;    }    case nsXPTType::T_VOID:    {      if (NS_SUCCEEDED(aInvokeResult)) {        jint value = NS_REINTERPRET_CAST(jint, aVariant.val.p);        if (aParamInfo.IsRetval() && !aIsArrayElement) {          *aParam = env->NewObject(intClass, intInitMID, value);        } else if ((aParamInfo.IsOut() || aIsArrayElement) && *aParam) {          env->SetIntArrayRegion((jintArray) *aParam, aIndex, 1, &value);        }      }      break;    }    case nsXPTType::T_ARRAY:    {      if (aParamInfo.IsOut() && NS_SUCCEEDED(aInvokeResult)) {        // Create Java array from returned native array        jobject jarray = nsnull;        if (aVariant.val.p) {          rv = CreateJavaArray(env, aArrayType, aArraySize, aIID, &jarray);          if (NS_FAILED(rv))            break;          nsXPTCVariant var;          for (PRUint32 i = 0; i < aArraySize && NS_SUCCEEDED(rv); i++) {            rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);            if (NS_SUCCEEDED(rv)) {              rv = FinalizeParams(env, aParamInfo, aArrayType, var, aIID,                                  PR_TRUE, 0, 0, i, aInvokeResult, &jarray);            }          }        }        if (aParamInfo.IsRetval()) {          *aParam = jarray;        } else if (*aParam) {          // put new Java array into output array          env->SetObjectArrayElement((jobjectArray) *aParam, 0, jarray);        }      }      // cleanup      PR_Free(aVariant.val.p);      break;    }    default:      NS_WARNING("unexpected parameter type");      return NS_ERROR_UNEXPECTED;  }  // Check for Java exception, but don't overwrite pre-existing error code.  if (NS_SUCCEEDED(rv) && env->ExceptionCheck())    rv = NS_ERROR_FAILURE;  return rv;}