NS_IMETHODIMP nsJavaXPTCStub::CallMethod(PRUint16 aMethodIndex, const XPTMethodDescriptor *aMethodInfo, nsXPTCMiniVariant *aParams) { #ifdef DEBUG_JAVAXPCOM const char* ifaceName; mIInfo->GetNameShared(&ifaceName); LOG(("---> (Java) %s::%s()\n", ifaceName, aMethodInfo->name)); #endif nsresult rv = NS_OK; JNIEnv* env = GetJNIEnv(); jobject javaObject = env->CallObjectMethod(mJavaWeakRef, getReferentMID); nsCAutoString methodSig("("); // Create jvalue array to hold Java params PRUint8 paramCount = aMethodInfo->num_args; jvalue* java_params = nsnull; const nsXPTParamInfo* retvalInfo = nsnull; if (paramCount) { java_params = new jvalue[paramCount]; if (!java_params) return NS_ERROR_OUT_OF_MEMORY; for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++) { const nsXPTParamInfo ¶mInfo = aMethodInfo->params[i]; if (!paramInfo.IsRetval()) { rv = SetupJavaParams(paramInfo, aMethodInfo, aMethodIndex, aParams, aParams[i], java_params[i], methodSig); } else { retvalInfo = ¶mInfo; } } NS_ASSERTION(NS_SUCCEEDED(rv), "SetupJavaParams failed"); } // Finish method signature if (NS_SUCCEEDED(rv)) { methodSig.Append(')'); if (retvalInfo) { nsCAutoString retvalSig; rv = GetRetvalSig(retvalInfo, aMethodInfo, aMethodIndex, aParams, retvalSig); methodSig.Append(retvalSig); } else { methodSig.Append('V'); } NS_ASSERTION(NS_SUCCEEDED(rv), "GetRetvalSig failed"); } // Get Java method to call jmethodID mid = nsnull; if (NS_SUCCEEDED(rv)) { nsCAutoString methodName; if (XPT_MD_IS_GETTER(aMethodInfo->flags) || XPT_MD_IS_SETTER(aMethodInfo->flags)) { if (XPT_MD_IS_GETTER(aMethodInfo->flags)) methodName.AppendLiteral("get"); else methodName.AppendLiteral("set"); methodName.AppendASCII(aMethodInfo->name); methodName.SetCharAt(toupper(methodName[3]), 3); } else { methodName.AppendASCII(aMethodInfo->name); methodName.SetCharAt(tolower(methodName[0]), 0); } // If it's a Java keyword, then prepend an underscore if (gJavaKeywords->GetEntry(methodName.get())) { methodName.Insert('_', 0); } jclass clazz = env->GetObjectClass(javaObject); if (clazz) mid = env->GetMethodID(clazz, methodName.get(), methodSig.get()); NS_ASSERTION(mid, "Failed to get requested method for Java object"); if (!mid) rv = NS_ERROR_FAILURE; } // Call method jvalue retval; if (NS_SUCCEEDED(rv)) { if (!retvalInfo) { env->CallVoidMethodA(javaObject, mid, java_params); } else { switch (retvalInfo->GetType().TagPart()) { case nsXPTType::T_I8: retval.b = env->CallByteMethodA(javaObject, mid, java_params); break; case nsXPTType::T_I16: case nsXPTType::T_U8: retval.s = env->CallShortMethodA(javaObject, mid, java_params); break; case nsXPTType::T_I32: case nsXPTType::T_U16: retval.i = env->CallIntMethodA(javaObject, mid, java_params); break; case nsXPTType::T_I64: case nsXPTType::T_U32: retval.j = env->CallLongMethodA(javaObject, mid, java_params); break; case nsXPTType::T_FLOAT: retval.f = env->CallFloatMethodA(javaObject, mid, java_params); break; case nsXPTType::T_U64: case nsXPTType::T_DOUBLE: retval.d = env->CallDoubleMethodA(javaObject, mid, java_params); break; case nsXPTType::T_BOOL: retval.z = env->CallBooleanMethodA(javaObject, mid, java_params); break; case nsXPTType::T_CHAR: case nsXPTType::T_WCHAR: retval.c = env->CallCharMethodA(javaObject, mid, java_params); break; case nsXPTType::T_CHAR_STR: case nsXPTType::T_WCHAR_STR: case nsXPTType::T_IID: case nsXPTType::T_ASTRING: case nsXPTType::T_DOMSTRING: case nsXPTType::T_UTF8STRING: case nsXPTType::T_CSTRING: case nsXPTType::T_INTERFACE: case nsXPTType::T_INTERFACE_IS: retval.l = env->CallObjectMethodA(javaObject, mid, java_params); break; case nsXPTType::T_VOID: retval.j = env->CallLongMethodA(javaObject, mid, java_params); break; default: NS_WARNING("Unhandled retval type"); break; } } // Check for exception from called Java function jthrowable exp = env->ExceptionOccurred(); if (exp) { // If the exception is an instance of XPCOMException, then get the // nsresult from the exception instance. Else, default to // NS_ERROR_FAILURE. if (env->IsInstanceOf(exp, xpcomExceptionClass)) { jfieldID fid; fid = env->GetFieldID(xpcomExceptionClass, "errorcode", "J"); if (fid) { rv = env->GetLongField(exp, fid); } else { rv = NS_ERROR_FAILURE; } NS_ASSERTION(fid, "Couldn't get 'errorcode' field of XPCOMException"); } else { rv = NS_ERROR_FAILURE; } } } // Handle any 'inout', 'out' and 'retval' params if (NS_SUCCEEDED(rv)) { for (PRUint8 i = 0; i < paramCount; i++) { const nsXPTParamInfo ¶mInfo = aMethodInfo->params[i]; if (paramInfo.IsIn() && !paramInfo.IsOut() && !paramInfo.IsDipper()) // 'in' continue; // If param is null, then caller is not expecting an output value. if (aParams[i].val.p == nsnull) continue; if (!paramInfo.IsRetval()) { rv = FinalizeJavaParams(paramInfo, aMethodInfo, aMethodIndex, aParams, aParams[i], java_params[i]); } else { rv = FinalizeJavaParams(paramInfo, aMethodInfo, aMethodIndex, aParams, aParams[i], retval); } } NS_ASSERTION(NS_SUCCEEDED(rv), "FinalizeJavaParams/SetXPCOMRetval failed"); } if (java_params) delete [] java_params; #ifdef DEBUG if (env->ExceptionCheck()) env->ExceptionDescribe(); #endif env->ExceptionClear(); LOG(("<--- (Java) %s::%s()\n", ifaceName, aMethodInfo->name)); return rv; }
NS_IMETHODIMP WSPPropertyBagWrapper::CallMethod(PRUint16 methodIndex, const XPTMethodDescriptor* info, nsXPTCMiniVariant* params) { if (methodIndex < 3) { NS_ERROR("WSPPropertyBagWrapper: bad method index"); return NS_ERROR_FAILURE; } nsresult rv = NS_OK; nsAutoString propName; rv = WSPFactory::C2XML(nsDependentCString(info->name), propName); if (NS_FAILED(rv)) { return rv; } nsCOMPtr<nsIVariant> val; rv = mPropertyBag->GetProperty(propName, getter_AddRefs(val)); if (NS_FAILED(rv)) { return rv; } nsCOMPtr<nsIInterfaceInfo> iinfo; if (XPT_MD_IS_GETTER(info->flags)) { const nsXPTParamInfo& paramInfo = info->params[0]; const nsXPTType& type = paramInfo.GetType(); uint8 type_tag = type.TagPart(); if (type_tag == nsXPTType::T_INTERFACE) { rv = mInterfaceInfo->GetInfoForParam(methodIndex, ¶mInfo, getter_AddRefs(iinfo)); if (NS_FAILED(rv)) { return rv; } } rv = WSPProxy::VariantToValue(type_tag, params[0].val.p, iinfo, val); } else if (info->num_args == 2) { // If it's not an explicit getter, it has to be an array getter // method. // The first parameter should be the array length out param const nsXPTParamInfo& paramInfo1 = info->params[0]; const nsXPTType& type1 = paramInfo1.GetType(); if (!paramInfo1.IsOut() || (type1.TagPart() != nsXPTType::T_U32)) { NS_ERROR("Unexpected parameter type for getter"); return NS_ERROR_FAILURE; } // The second parameter should be the array out pointer itself. const nsXPTParamInfo& paramInfo2 = info->params[1]; const nsXPTType& type2 = paramInfo2.GetType(); if (!paramInfo2.IsOut() || !type2.IsArray()) { NS_ERROR("Unexpected parameter type for getter"); return NS_ERROR_FAILURE; } nsXPTType arrayType; rv = mInterfaceInfo->GetTypeForParam(methodIndex, ¶mInfo2, 1, &arrayType); if (NS_FAILED(rv)) { return rv; } if (arrayType.IsInterfacePointer()) { rv = mInterfaceInfo->GetInfoForParam(methodIndex, ¶mInfo2, getter_AddRefs(iinfo)); if (NS_FAILED(rv)) { return rv; } } rv = WSPProxy::VariantToArrayValue(arrayType.TagPart(), params, params + 1, iinfo, val); } else { NS_ERROR("Unexpected method signature for property bag wrapper"); return NS_ERROR_FAILURE; } return rv; }