PRUint8 arrayType; PRUint32 arraySize;
PRUint8 arrayType = 0; PRUint32 arraySize = 0;
JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,                                   jstring aMethodName, jobjectArray aParams){  nsresult rv;  // Get native XPCOM instance  void* xpcom_obj;  rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);  if (NS_FAILED(rv)) {    ThrowException(env, 0, "Failed to get matching XPCOM object");    return nsnull;  }  JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);  // Get method info  PRUint16 methodIndex;  const nsXPTMethodInfo* methodInfo;  nsIInterfaceInfo* iinfo = inst->InterfaceInfo();  const char* methodName = env->GetStringUTFChars(aMethodName, nsnull);  rv = QueryMethodInfo(iinfo, methodName, &methodIndex, &methodInfo);  env->ReleaseStringUTFChars(aMethodName, methodName);  if (NS_FAILED(rv)) {    ThrowException(env, rv, "GetMethodInfoForName failed");    return nsnull;  }#ifdef DEBUG_JAVAXPCOM  const char* ifaceName;  iinfo->GetNameShared(&ifaceName);  LOG(("===> (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));#endif  // Convert the Java params  PRUint8 paramCount = methodInfo->GetParamCount();  nsXPTCVariant* params = nsnull;  if (paramCount)  {    params = new nsXPTCVariant[paramCount];    if (!params) {      ThrowException(env, NS_ERROR_OUT_OF_MEMORY, "Can't create params array");      return nsnull;    }    memset(params, 0, paramCount * sizeof(nsXPTCVariant));    for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)    {      LOG(("\t Param %d: ", i));      const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);      params[i].type = paramInfo.GetType();      if (paramInfo.IsIn() && !paramInfo.IsDipper()) {        PRUint8 type = params[i].type.TagPart();        // is paramater an array?        PRUint8 arrayType;        PRUint32 arraySize;        if (type == nsXPTType::T_ARRAY) {          // get array type          nsXPTType xpttype;          rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &xpttype);          if (NS_FAILED(rv))            break;          arrayType = xpttype.TagPart();          // get size of array          PRUint8 argnum;          rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,                                                 &argnum);          if (NS_FAILED(rv))            break;          arraySize = params[argnum].val.u32;        }        // get IID for interface params        nsID iid;        if (type == nsXPTType::T_INTERFACE ||            type == nsXPTType::T_INTERFACE_IS ||            type == nsXPTType::T_ARRAY &&              (arrayType == nsXPTType::T_INTERFACE ||               arrayType == nsXPTType::T_INTERFACE_IS))        {          PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;          rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,                                    methodIndex, params, PR_TRUE, iid);        }        if (NS_SUCCEEDED(rv)) {          rv = SetupParams(env, env->GetObjectArrayElement(aParams, i), type,                           paramInfo.IsOut(), iid, arrayType, arraySize,                           PR_FALSE, 0, params[i]);        }      } else if (paramInfo.IsDipper()) {        LOG(("dipper\n"));        switch (params[i].type.TagPart())        {          case nsXPTType::T_ASTRING:          case nsXPTType::T_DOMSTRING:          {            params[i].val.p = new nsString();            if (params[i].val.p == nsnull) {              rv = NS_ERROR_OUT_OF_MEMORY;              break;            }            params[i].SetValIsDOMString();            break;          }          case nsXPTType::T_UTF8STRING:          case nsXPTType::T_CSTRING:          {            params[i].val.p = new nsCString();            if (params[i].val.p == nsnull) {              rv = NS_ERROR_OUT_OF_MEMORY;              break;            }            params[i].SetValIsCString();            break;          }          default:            LOG(("unhandled dipper type\n"));            rv = NS_ERROR_UNEXPECTED;        }      } else {        LOG(("out/retval\n"));        params[i].ptr = &(params[i].val);        params[i].SetPtrIsData();      }    }    if (NS_FAILED(rv)) {      ThrowException(env, rv, "SetupParams failed");      return nsnull;    }  }  // Call the XPCOM method  nsresult invokeResult;  invokeResult = XPTC_InvokeByIndex(inst->GetInstance(), methodIndex,                                    paramCount, params);  // Clean up params  jobject result = nsnull;  for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)  {    const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);    PRUint8 type = paramInfo.GetType().TagPart();    // is paramater an array?    PRUint8 arrayType;    PRUint32 arraySize;    if (type == nsXPTType::T_ARRAY) {      // get array type      nsXPTType array_xpttype;      rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &array_xpttype);      if (NS_FAILED(rv))        break;      arrayType = array_xpttype.TagPart();      // get size of array      PRUint8 argnum;      rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,                                             &argnum);      if (NS_FAILED(rv))        break;      arraySize = params[argnum].val.u32;    }    // get IID for interface params    nsID iid;    if (type == nsXPTType::T_INTERFACE || type == nsXPTType::T_INTERFACE_IS ||        type == nsXPTType::T_ARRAY && (arrayType == nsXPTType::T_INTERFACE ||                                       arrayType == nsXPTType::T_INTERFACE_IS))    {      PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;      rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,                                methodIndex, params, PR_TRUE, iid);      if (NS_FAILED(rv))        break;    }    jobject* javaElement;    if (!paramInfo.IsRetval()) {      jobject element = env->GetObjectArrayElement(aParams, i);      javaElement = &element;    } else {      javaElement = &result;    }    rv = FinalizeParams(env, paramInfo, type, params[i], iid, PR_FALSE,                        arrayType, arraySize, 0, invokeResult, javaElement);  }  if (NS_FAILED(rv)) {    ThrowException(env, rv, "FinalizeParams failed");    return nsnull;  }  // Normally, we would delete any created nsID object in the above loop.  // However, GetIIDForMethodParam may need some of the nsID params when it's  // looking for the IID of an INTERFACE_IS.  Therefore, we can't delete it  // until we've gone through the 'Finalize' loop once and created the result.  for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++)  {    const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);    const nsXPTType &type = paramInfo.GetType();    if (type.TagPart() == nsXPTType::T_IID) {      nsID* iid = (nsID*) params[j].val.p;      delete iid;    }  }  if (params) {    delete params;  }  // If the XPCOM method invocation failed, we don't immediately throw an  // exception and return so that we can clean up any parameters.  if (NS_FAILED(invokeResult)) {    nsCAutoString message("The function \"");    message.AppendASCII(methodInfo->GetName());    message.AppendLiteral("\" returned an error condition");    ThrowException(env, invokeResult, message.get());  }  LOG(("<=== (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));  return result;}