2004-09-02 20:34:11 +04:00
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Java XPCOM Bindings.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* IBM Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
|
|
|
* IBM Corporation. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Javier Pedemonte (jhpedemonte@gmail.com)
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "nsJavaWrapper.h"
|
|
|
|
#include "nsJavaXPTCStub.h"
|
|
|
|
#include "nsJavaXPCOMBindingUtils.h"
|
|
|
|
#include "jni.h"
|
|
|
|
#include "xptcall.h"
|
|
|
|
#include "nsIInterfaceInfoManager.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "prmem.h"
|
|
|
|
|
2005-02-23 23:19:55 +03:00
|
|
|
#define JAVAPROXY_NATIVE(func) Java_org_mozilla_xpcom_XPCOMJavaProxy_##func
|
|
|
|
|
2004-09-02 20:34:11 +04:00
|
|
|
static nsID nullID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
|
|
|
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
/**
|
|
|
|
* Handle 'in' and 'inout' params.
|
|
|
|
*/
|
2004-09-02 20:34:11 +04:00
|
|
|
nsresult
|
2004-10-07 02:28:50 +04:00
|
|
|
SetupParams(JNIEnv *env, const jobject aParam, const nsXPTParamInfo &aParamInfo,
|
|
|
|
const nsXPTMethodInfo* aMethodInfo, nsIInterfaceInfo* aIInfo,
|
|
|
|
PRUint16 aMethodIndex, nsXPTCVariant* aDispatchParams,
|
|
|
|
nsXPTCVariant &aVariant)
|
2004-09-02 20:34:11 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
const nsXPTType &type = aParamInfo.GetType();
|
|
|
|
|
|
|
|
// defaults
|
|
|
|
aVariant.ptr = nsnull;
|
|
|
|
aVariant.type = type;
|
|
|
|
aVariant.flags = 0;
|
|
|
|
|
|
|
|
PRUint8 tag = type.TagPart();
|
|
|
|
switch (tag)
|
|
|
|
{
|
|
|
|
case nsXPTType::T_I8:
|
|
|
|
case nsXPTType::T_U8:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("byte\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.val.u8 = env->CallByteMethod(aParam, byteValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
env->GetByteArrayRegion((jbyteArray) aParam, 0, 1,
|
|
|
|
(jbyte*) &(aVariant.val.u8));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I16:
|
|
|
|
case nsXPTType::T_U16:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("short\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.val.u16 = env->CallShortMethod(aParam, shortValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
env->GetShortArrayRegion((jshortArray) aParam, 0, 1,
|
|
|
|
(jshort*) &(aVariant.val.u16));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I32:
|
|
|
|
case nsXPTType::T_U32:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("int\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.val.u32 = env->CallIntMethod(aParam, intValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
env->GetIntArrayRegion((jintArray) aParam, 0, 1,
|
|
|
|
(jint*) &(aVariant.val.u32));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I64:
|
|
|
|
case nsXPTType::T_U64:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("long\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.val.u64 = env->CallLongMethod(aParam, longValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
env->GetLongArrayRegion((jlongArray) aParam, 0, 1,
|
|
|
|
(jlong*) &(aVariant.val.u64));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_FLOAT:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("float\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.val.f = env->CallFloatMethod(aParam, floatValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
env->GetFloatArrayRegion((jfloatArray) aParam, 0, 1,
|
|
|
|
(jfloat*) &(aVariant.val.f));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_DOUBLE:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("double\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.val.d = env->CallDoubleMethod(aParam, doubleValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
env->GetDoubleArrayRegion((jdoubleArray) aParam, 0, 1,
|
|
|
|
(jdouble*) &(aVariant.val.d));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_BOOL:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("boolean\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.val.b = env->CallBooleanMethod(aParam, booleanValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
env->GetBooleanArrayRegion((jbooleanArray) aParam, 0, 1,
|
|
|
|
(jboolean*) &(aVariant.val.b));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_CHAR:
|
|
|
|
case nsXPTType::T_WCHAR:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("char\n"));
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (tag == nsXPTType::T_CHAR)
|
|
|
|
aVariant.val.c = env->CallCharMethod(aParam, charValueMID);
|
|
|
|
else
|
|
|
|
aVariant.val.wc = env->CallCharMethod(aParam, charValueMID);
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam) {
|
2005-01-13 19:30:19 +03:00
|
|
|
if (tag == nsXPTType::T_CHAR)
|
|
|
|
env->GetCharArrayRegion((jcharArray) aParam, 0, 1,
|
|
|
|
(jchar*) &(aVariant.val.c));
|
|
|
|
else
|
|
|
|
env->GetCharArrayRegion((jcharArray) aParam, 0, 1,
|
|
|
|
(jchar*) &(aVariant.val.wc));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
} else {
|
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_CHAR_STR:
|
|
|
|
case nsXPTType::T_WCHAR_STR:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("String\n"));
|
2004-09-02 20:34:11 +04:00
|
|
|
jstring data = nsnull;
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
data = (jstring) aParam;
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam)
|
|
|
|
data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam, 0);
|
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
void* buf = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
if (data) {
|
2005-01-13 19:30:19 +03:00
|
|
|
jsize uniLength = env->GetStringLength(data);
|
|
|
|
if (uniLength > 0) {
|
|
|
|
if (tag == nsXPTType::T_CHAR_STR) {
|
|
|
|
jsize utf8Length = env->GetStringUTFLength(data);
|
|
|
|
buf = nsMemory::Alloc(utf8Length + 1);
|
|
|
|
if (!buf) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
env->GetStringUTFRegion(data, 0, uniLength, (char*) buf);
|
|
|
|
((char*)buf)[utf8Length] = '\0';
|
|
|
|
|
|
|
|
} else { // if T_WCHAR_STR
|
|
|
|
buf = nsMemory::Alloc((uniLength + 1) * sizeof(jchar));
|
|
|
|
if (!buf) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
env->GetStringRegion(data, 0, uniLength, (jchar*) buf);
|
|
|
|
((jchar*)buf)[uniLength] = '\0';
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
} else {
|
2005-01-13 19:30:19 +03:00
|
|
|
// create empty string
|
|
|
|
buf = nsMemory::Alloc(2);
|
|
|
|
if (!buf) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
((jchar*)buf)[0] = '\0';
|
2005-01-12 20:59:01 +03:00
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.val.p = buf;
|
|
|
|
if (aParamInfo.IsOut()) { // 'inout'
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_IID:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("String(IID)\n"));
|
2004-09-02 20:34:11 +04:00
|
|
|
jstring data = nsnull;
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
data = (jstring) aParam;
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam)
|
|
|
|
data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsID* iid = new nsID;
|
2005-01-12 20:59:01 +03:00
|
|
|
if (!iid) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
if (data) {
|
2005-01-13 19:30:19 +03:00
|
|
|
// extract IID string from Java string
|
|
|
|
const char* str = env->GetStringUTFChars(data, nsnull);
|
2005-01-12 20:59:01 +03:00
|
|
|
if (!str) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
// parse string into IID object
|
2004-09-02 20:34:11 +04:00
|
|
|
iid->Parse(str);
|
2005-01-13 19:30:19 +03:00
|
|
|
env->ReleaseStringUTFChars(data, str);
|
2004-09-02 20:34:11 +04:00
|
|
|
} else {
|
|
|
|
*iid = nullID;
|
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.val.p = iid;
|
|
|
|
if (aParamInfo.IsOut()) { // 'inout'
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
aVariant.SetPtrIsData();
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_INTERFACE:
|
|
|
|
case nsXPTType::T_INTERFACE_IS:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("nsISupports\n"));
|
2004-10-07 02:28:50 +04:00
|
|
|
jobject java_obj = nsnull;
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-10-07 02:28:50 +04:00
|
|
|
java_obj = (jobject) aParam;
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam)
|
2005-02-23 23:19:55 +03:00
|
|
|
java_obj = (jobject)
|
|
|
|
env->GetObjectArrayElement((jobjectArray) aParam, 0);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
void* xpcom_obj;
|
2004-10-07 02:28:50 +04:00
|
|
|
if (java_obj) {
|
2004-09-02 20:34:11 +04:00
|
|
|
// Check if we already have a corresponding XPCOM object
|
2005-02-23 23:19:55 +03:00
|
|
|
jboolean isProxy = env->CallStaticBooleanMethod(xpcomJavaProxyClass,
|
|
|
|
isXPCOMJavaProxyMID,
|
|
|
|
java_obj);
|
|
|
|
if (env->ExceptionCheck()) {
|
|
|
|
rv = NS_ERROR_FAILURE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* inst;
|
|
|
|
if (isProxy) {
|
|
|
|
rv = GetXPCOMInstFromProxy(env, java_obj, &inst);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
inst = gBindings->GetXPCOMObject(env, java_obj);
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2004-09-16 01:50:41 +04:00
|
|
|
// Get IID for this param
|
|
|
|
nsID iid;
|
|
|
|
rv = GetIIDForMethodParam(aIInfo, aMethodInfo, aParamInfo,
|
|
|
|
aMethodIndex, aDispatchParams, PR_TRUE,
|
|
|
|
iid);
|
|
|
|
if (NS_FAILED(rv))
|
2005-01-12 20:59:01 +03:00
|
|
|
break;
|
2004-09-16 01:50:41 +04:00
|
|
|
|
|
|
|
PRBool isWeakRef = iid.Equals(NS_GET_IID(nsIWeakReference));
|
|
|
|
|
|
|
|
if (inst == nsnull && !isWeakRef) {
|
2004-09-02 20:34:11 +04:00
|
|
|
// If there is not corresponding XPCOM object, then that means that the
|
|
|
|
// parameter is non-generated class (that is, it is not one of our
|
|
|
|
// Java stubs that represent an exising XPCOM object). So we need to
|
|
|
|
// create an XPCOM stub, that can route any method calls to the class.
|
|
|
|
|
|
|
|
// Get interface info for class
|
|
|
|
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
|
|
|
nsCOMPtr<nsIInterfaceInfo> iinfo;
|
2005-01-12 20:59:01 +03:00
|
|
|
rv = iim->GetInfoForIID(&iid, getter_AddRefs(iinfo));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
2004-09-02 20:34:11 +04:00
|
|
|
|
|
|
|
// Create XPCOM stub
|
2004-10-07 02:28:50 +04:00
|
|
|
nsJavaXPTCStub* xpcomStub = new nsJavaXPTCStub(env, java_obj, iinfo);
|
2005-01-12 20:59:01 +03:00
|
|
|
if (!xpcomStub) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
inst = SetAsXPTCStub(xpcomStub);
|
2005-01-14 03:09:49 +03:00
|
|
|
gBindings->AddBinding(env, java_obj, inst);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2004-09-16 01:50:41 +04:00
|
|
|
if (isWeakRef) {
|
|
|
|
// If the function expects an weak reference, then we need to
|
|
|
|
// create it here.
|
2004-10-07 02:28:50 +04:00
|
|
|
nsJavaXPTCStubWeakRef* weakref =
|
|
|
|
new nsJavaXPTCStubWeakRef(env, java_obj);
|
2005-01-12 20:59:01 +03:00
|
|
|
if (!weakref) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-16 01:50:41 +04:00
|
|
|
NS_ADDREF(weakref);
|
2005-01-13 19:30:19 +03:00
|
|
|
xpcom_obj = (void*) weakref;
|
|
|
|
aVariant.SetValIsAllocated();
|
2005-01-12 20:59:01 +03:00
|
|
|
|
2004-09-16 01:50:41 +04:00
|
|
|
} else if (IsXPTCStub(inst)) {
|
2004-09-15 23:21:08 +04:00
|
|
|
nsJavaXPTCStub* xpcomStub = GetXPTCStubAddr(inst);
|
|
|
|
NS_ADDREF(xpcomStub);
|
2005-01-13 19:30:19 +03:00
|
|
|
xpcom_obj = (void*) xpcomStub;
|
|
|
|
aVariant.SetValIsAllocated();
|
2005-01-12 20:59:01 +03:00
|
|
|
|
2004-09-15 23:21:08 +04:00
|
|
|
} else {
|
2004-09-02 20:34:11 +04:00
|
|
|
JavaXPCOMInstance* xpcomInst = (JavaXPCOMInstance*) inst;
|
2005-01-13 19:30:19 +03:00
|
|
|
xpcom_obj = (void*) xpcomInst->GetInstance();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
} else {
|
2005-01-13 19:30:19 +03:00
|
|
|
xpcom_obj = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.val.p = xpcom_obj;
|
2004-09-02 20:34:11 +04:00
|
|
|
aVariant.SetValIsInterface();
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut()) { // 'inout'
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
aVariant.SetPtrIsData();
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_ASTRING:
|
|
|
|
case nsXPTType::T_DOMSTRING:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("String\n"));
|
2004-09-02 20:34:11 +04:00
|
|
|
jstring data = nsnull;
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
data = (jstring) aParam;
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam)
|
|
|
|
data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam, 0);
|
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
nsAString* str;
|
|
|
|
if (data) {
|
|
|
|
str = jstring_to_nsAString(env, data);
|
|
|
|
if (!str) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
str = nsnull;
|
2005-01-12 20:59:01 +03:00
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.val.p = str;
|
|
|
|
aVariant.SetValIsDOMString();
|
|
|
|
if (aParamInfo.IsOut()) { // 'inout'
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
aVariant.SetPtrIsData();
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_UTF8STRING:
|
|
|
|
case nsXPTType::T_CSTRING:
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("StringUTF\n"));
|
2004-09-02 20:34:11 +04:00
|
|
|
jstring data = nsnull;
|
2005-01-13 19:30:19 +03:00
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
2004-09-02 20:34:11 +04:00
|
|
|
data = (jstring) aParam;
|
2005-01-13 19:30:19 +03:00
|
|
|
} else { // 'inout'
|
2004-09-02 20:34:11 +04:00
|
|
|
if (aParam)
|
|
|
|
data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam, 0);
|
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
nsACString* str;
|
|
|
|
if (data) {
|
|
|
|
str = jstring_to_nsACString(env, data);
|
|
|
|
if (!str) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
str = nsnull;
|
2005-01-12 20:59:01 +03:00
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.val.p = str;
|
2004-09-02 20:34:11 +04:00
|
|
|
if (tag == nsXPTType::T_CSTRING) {
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetValIsCString();
|
2004-09-02 20:34:11 +04:00
|
|
|
} else {
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetValIsUTF8String();
|
|
|
|
}
|
|
|
|
if (aParamInfo.IsOut()) { // 'inout'
|
|
|
|
aVariant.ptr = &aVariant.val;
|
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-12-23 20:09:54 +03:00
|
|
|
// handle "void *" as an "int" in Java
|
2004-09-02 20:34:11 +04:00
|
|
|
case nsXPTType::T_VOID:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
LOG(("int (void*)\n"));
|
|
|
|
if (!aParamInfo.IsOut()) { // 'in'
|
|
|
|
aVariant.val.p = (void*) env->CallIntMethod(aParam, intValueMID);
|
|
|
|
} else { // 'inout'
|
|
|
|
if (aParam) {
|
|
|
|
env->GetIntArrayRegion((jintArray) aParam, 0, 1,
|
|
|
|
(jint*) &(aVariant.val.p));
|
|
|
|
aVariant.ptr = &aVariant.val;
|
2004-09-02 20:34:11 +04:00
|
|
|
} else {
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.ptr = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
aVariant.SetPtrIsData();
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_ARRAY:
|
|
|
|
NS_WARNING("array types are not yet supported");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
case nsXPTType::T_PSTRING_SIZE_IS:
|
|
|
|
case nsXPTType::T_PWSTRING_SIZE_IS:
|
|
|
|
default:
|
|
|
|
NS_WARNING("unexpected parameter type");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
/**
|
|
|
|
* Handles 'in', 'out', and 'inout' params.
|
|
|
|
*/
|
2004-09-02 20:34:11 +04:00
|
|
|
nsresult
|
|
|
|
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();
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
PRUint8 tag = type.TagPart();
|
|
|
|
switch (tag)
|
2004-09-02 20:34:11 +04:00
|
|
|
{
|
|
|
|
case nsXPTType::T_I8:
|
|
|
|
case nsXPTType::T_U8:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetByteArrayRegion((jbyteArray) aParam, 0, 1,
|
|
|
|
(jbyte*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I16:
|
|
|
|
case nsXPTType::T_U16:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetShortArrayRegion((jshortArray) aParam, 0, 1,
|
|
|
|
(jshort*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I32:
|
|
|
|
case nsXPTType::T_U32:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetIntArrayRegion((jintArray) aParam, 0, 1,
|
|
|
|
(jint*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I64:
|
|
|
|
case nsXPTType::T_U64:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetLongArrayRegion((jlongArray) aParam, 0, 1,
|
|
|
|
(jlong*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_FLOAT:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetFloatArrayRegion((jfloatArray) aParam, 0, 1,
|
|
|
|
(jfloat*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_DOUBLE:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetDoubleArrayRegion((jdoubleArray) aParam, 0, 1,
|
|
|
|
(jdouble*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_BOOL:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetBooleanArrayRegion((jbooleanArray) aParam, 0, 1,
|
|
|
|
(jboolean*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_CHAR:
|
|
|
|
case nsXPTType::T_WCHAR:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetCharArrayRegion((jcharArray) aParam, 0, 1,
|
|
|
|
(jchar*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_CHAR_STR:
|
|
|
|
case nsXPTType::T_WCHAR_STR:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
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;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
} else {
|
2005-01-13 19:30:19 +03:00
|
|
|
str = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
// put new string into output array
|
2004-09-02 20:34:11 +04:00
|
|
|
env->SetObjectArrayElement((jobjectArray) aParam, 0, str);
|
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
|
|
|
|
// Delete for 'in', 'inout', and 'out'
|
|
|
|
if (aVariant.val.p)
|
|
|
|
nsMemory::Free(aVariant.val.p);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_IID:
|
|
|
|
{
|
|
|
|
nsID* iid = (nsID*) aVariant.val.p;
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
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);
|
2005-01-12 20:59:01 +03:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
|
|
|
|
// put new string into output array
|
2004-09-02 20:34:11 +04:00
|
|
|
env->SetObjectArrayElement((jobjectArray) aParam, 0, str);
|
|
|
|
}
|
|
|
|
|
2004-12-23 20:09:54 +03:00
|
|
|
// Ordinarily, we would delete 'iid' here. But we cannot do that until
|
|
|
|
// we've handled all of the params. See comment in CallXPCOMMethod
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_INTERFACE:
|
|
|
|
case nsXPTType::T_INTERFACE_IS:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
void* xpcom_obj = aVariant.val.p;
|
|
|
|
|
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
jobject java_obj = nsnull;
|
|
|
|
if (xpcom_obj) {
|
2005-01-21 01:07:26 +03:00
|
|
|
nsID iid;
|
|
|
|
rv = GetIIDForMethodParam(aIInfo, aMethodInfo, aParamInfo,
|
|
|
|
aMethodIndex, aDispatchParams, PR_TRUE, iid);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2005-01-21 01:07:26 +03:00
|
|
|
// Get matching Java object for given xpcom object
|
|
|
|
rv = gBindings->GetJavaObject(env, xpcom_obj, iid, PR_TRUE, &java_obj);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
// put new Java object into output array
|
2004-09-02 20:34:11 +04:00
|
|
|
env->SetObjectArrayElement((jobjectArray) aParam, 0, java_obj);
|
|
|
|
}
|
2004-10-27 00:14:53 +04:00
|
|
|
|
|
|
|
// If VAL_IS_ALLOCD is set, that means that an XPCOM object was created
|
|
|
|
// is SetupParams that now needs to be released.
|
2005-01-13 19:30:19 +03:00
|
|
|
if (xpcom_obj && aVariant.IsValAllocated()) {
|
|
|
|
nsISupports* variant = NS_STATIC_CAST(nsISupports*, xpcom_obj);
|
2004-10-27 00:14:53 +04:00
|
|
|
NS_RELEASE(variant);
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_ASTRING:
|
|
|
|
case nsXPTType::T_DOMSTRING:
|
|
|
|
{
|
|
|
|
nsString* str = (nsString*) aVariant.val.p;
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
// Create Java string from returned nsString
|
|
|
|
jstring jstr;
|
|
|
|
if (str) {
|
2005-01-12 20:59:01 +03:00
|
|
|
jstr = env->NewString((const jchar*) str->get(), str->Length());
|
|
|
|
if (!jstr) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
} else {
|
|
|
|
jstr = nsnull;
|
2004-12-18 01:25:12 +03:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
|
|
|
|
// put new Java string into output array
|
|
|
|
env->SetObjectArrayElement((jobjectArray) aParam, 0, jstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str) {
|
2004-12-18 01:25:12 +03:00
|
|
|
delete str;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_UTF8STRING:
|
|
|
|
case nsXPTType::T_CSTRING:
|
|
|
|
{
|
|
|
|
nsCString* str = (nsCString*) aVariant.val.p;
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
// Create Java string from returned nsString
|
|
|
|
jstring jstr;
|
|
|
|
if (str) {
|
|
|
|
jstr = env->NewStringUTF((const char*) str->get());
|
2005-01-12 20:59:01 +03:00
|
|
|
if (!jstr) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
} else {
|
|
|
|
jstr = nsnull;
|
2004-12-18 01:25:12 +03:00
|
|
|
}
|
2005-01-13 19:30:19 +03:00
|
|
|
|
|
|
|
// put new Java string into output array
|
|
|
|
env->SetObjectArrayElement((jobjectArray) aParam, 0, jstr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str) {
|
2004-12-18 01:25:12 +03:00
|
|
|
delete str;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_VOID:
|
|
|
|
{
|
2005-01-13 19:30:19 +03:00
|
|
|
if (aParamInfo.IsOut() && aParam) { // 'inout' & 'out'
|
|
|
|
env->SetIntArrayRegion((jintArray) aParam, 0, 1,
|
|
|
|
(jint*) aVariant.ptr);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2004-10-07 02:28:50 +04:00
|
|
|
SetRetval(JNIEnv *env, const nsXPTParamInfo &aParamInfo,
|
|
|
|
const nsXPTMethodInfo* aMethodInfo, nsIInterfaceInfo* aIInfo,
|
|
|
|
PRUint16 aMethodIndex, nsXPTCVariant* aDispatchParams,
|
2005-02-23 23:19:55 +03:00
|
|
|
nsXPTCVariant &aVariant, jobject* result)
|
2004-09-02 20:34:11 +04:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
const nsXPTType &type = aParamInfo.GetType();
|
|
|
|
|
|
|
|
switch (type.TagPart())
|
|
|
|
{
|
|
|
|
case nsXPTType::T_I8:
|
|
|
|
case nsXPTType::T_U8:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(byteClass, byteInitMID, aVariant.val.u8);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I16:
|
|
|
|
case nsXPTType::T_U16:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(shortClass, shortInitMID, aVariant.val.u16);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I32:
|
|
|
|
case nsXPTType::T_U32:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(intClass, intInitMID, aVariant.val.u32);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_I64:
|
|
|
|
case nsXPTType::T_U64:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(longClass, longInitMID, aVariant.val.u64);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_FLOAT:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(floatClass, floatInitMID, aVariant.val.f);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_DOUBLE:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(doubleClass, doubleInitMID, aVariant.val.d);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_BOOL:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(booleanClass, booleanInitMID, aVariant.val.b);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_CHAR:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(charClass, charInitMID, aVariant.val.c);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_WCHAR:
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(charClass, charInitMID, aVariant.val.wc);
|
2004-09-02 20:34:11 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_CHAR_STR:
|
|
|
|
{
|
2005-01-12 20:59:01 +03:00
|
|
|
if (aVariant.ptr) {
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewStringUTF((const char*) aVariant.ptr);
|
|
|
|
if (*result == nsnull) {
|
2005-01-12 20:59:01 +03:00
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_WCHAR_STR:
|
|
|
|
{
|
|
|
|
if (aVariant.ptr) {
|
|
|
|
PRUint32 length = nsCRT::strlen((const PRUnichar*) aVariant.ptr);
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewString((const jchar*) aVariant.ptr, length);
|
|
|
|
if (*result == nsnull) {
|
2005-01-12 20:59:01 +03:00
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_IID:
|
|
|
|
{
|
|
|
|
if (aVariant.ptr) {
|
|
|
|
nsID* iid = (nsID*) aVariant.ptr;
|
|
|
|
char* iid_str = iid->ToString();
|
2005-01-13 19:30:19 +03:00
|
|
|
if (iid_str) {
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewStringUTF(iid_str);
|
2005-01-13 19:30:19 +03:00
|
|
|
}
|
2005-02-23 23:19:55 +03:00
|
|
|
if (iid_str == nsnull || *result == nsnull) {
|
2005-01-12 20:59:01 +03:00
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
PR_Free(iid_str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_INTERFACE:
|
|
|
|
case nsXPTType::T_INTERFACE_IS:
|
|
|
|
{
|
|
|
|
if (aVariant.val.p) {
|
2005-01-21 01:07:26 +03:00
|
|
|
nsID iid;
|
|
|
|
rv = GetIIDForMethodParam(aIInfo, aMethodInfo, aParamInfo, aMethodIndex,
|
|
|
|
aDispatchParams, PR_TRUE, iid);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2005-01-21 01:07:26 +03:00
|
|
|
// Get matching Java object for given xpcom object
|
|
|
|
jobject java_obj;
|
|
|
|
rv = gBindings->GetJavaObject(env, aVariant.val.p, iid, PR_TRUE,
|
|
|
|
&java_obj);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
break;
|
2004-10-18 21:04:29 +04:00
|
|
|
|
|
|
|
// If returned object is an nsJavaXPTCStub, release it.
|
|
|
|
nsISupports* xpcom_obj = NS_STATIC_CAST(nsISupports*, aVariant.val.p);
|
|
|
|
nsJavaXPTCStub* stub = nsnull;
|
|
|
|
xpcom_obj->QueryInterface(NS_GET_IID(nsJavaXPTCStub), (void**) &stub);
|
|
|
|
if (stub) {
|
|
|
|
NS_RELEASE(xpcom_obj);
|
|
|
|
NS_RELEASE(stub);
|
|
|
|
}
|
|
|
|
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = java_obj;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_ASTRING:
|
|
|
|
case nsXPTType::T_DOMSTRING:
|
|
|
|
{
|
|
|
|
if (aVariant.ptr) {
|
|
|
|
nsString* str = (nsString*) aVariant.ptr;
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewString(str->get(), str->Length());
|
|
|
|
if (*result == nsnull) {
|
2005-01-12 20:59:01 +03:00
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_UTF8STRING:
|
|
|
|
case nsXPTType::T_CSTRING:
|
|
|
|
{
|
|
|
|
if (aVariant.ptr) {
|
|
|
|
nsCString* str = (nsCString*) aVariant.ptr;
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewStringUTF(str->get());
|
|
|
|
if (*result == nsnull) {
|
2005-01-12 20:59:01 +03:00
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_VOID:
|
2004-09-15 20:57:08 +04:00
|
|
|
// handle "void *" as an "int" in Java
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG((" returns int (void*)"));
|
2005-02-23 23:19:55 +03:00
|
|
|
*result = env->NewObject(intClass, intInitMID, aVariant.val.p);
|
2004-09-15 20:57:08 +04:00
|
|
|
break;
|
2004-09-02 20:34:11 +04:00
|
|
|
|
|
|
|
case nsXPTType::T_ARRAY:
|
|
|
|
NS_WARNING("array types are not yet supported");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
default:
|
|
|
|
NS_WARNING("unexpected parameter type");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2005-02-23 23:19:55 +03:00
|
|
|
/**
|
|
|
|
* Given an interface info struct and a method name, returns the method info
|
|
|
|
* and index, if that method exists.
|
|
|
|
*
|
|
|
|
* Most method names are lower case. Unfortunately, the method names of some
|
|
|
|
* interfaces (such as nsIAppShell) start with a capital letter. This function
|
|
|
|
* will try all of the permutations.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
QueryMethodInfo(nsIInterfaceInfo* aIInfo, const char* aMethodName,
|
|
|
|
PRUint16* aMethodIndex, const nsXPTMethodInfo** aMethodInfo)
|
2004-09-02 20:34:11 +04:00
|
|
|
{
|
2005-02-23 23:19:55 +03:00
|
|
|
// The common case is that the method name is lower case, so we check
|
|
|
|
// that first.
|
|
|
|
nsresult rv;
|
|
|
|
rv = aIInfo->GetMethodInfoForName(aMethodName, aMethodIndex, aMethodInfo);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// If there is no method called <aMethodName>, then maybe it is an
|
|
|
|
// 'attribute'. An 'attribute' will start with "get" or "set". But first,
|
|
|
|
// we check the length, in order to skip over method names that match exactly
|
|
|
|
// "get" or "set".
|
|
|
|
if (strlen(aMethodName) > 3) {
|
|
|
|
if (strncmp("get", aMethodName, 3) == 0) {
|
|
|
|
char* getterName = strdup(aMethodName + 3);
|
|
|
|
getterName[0] = tolower(getterName[0]);
|
|
|
|
rv = aIInfo->GetMethodInfoForName(getterName, aMethodIndex, aMethodInfo);
|
|
|
|
free(getterName);
|
|
|
|
} else if (strncmp("set", aMethodName, 3) == 0) {
|
|
|
|
char* setterName = strdup(aMethodName + 3);
|
|
|
|
setterName[0] = tolower(setterName[0]);
|
|
|
|
rv = aIInfo->GetMethodInfoForName(setterName, aMethodIndex, aMethodInfo);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// If this succeeded, GetMethodInfoForName will have returned the
|
|
|
|
// method info for the 'getter'. We want the 'setter', so increase
|
|
|
|
// method index by one ('setter' immediately follows the 'getter'),
|
|
|
|
// and get its method info.
|
|
|
|
(*aMethodIndex)++;
|
|
|
|
rv = aIInfo->GetMethodInfo(*aMethodIndex, aMethodInfo);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// Double check that this methodInfo matches the given method.
|
|
|
|
if (!(*aMethodInfo)->IsSetter() ||
|
|
|
|
strcmp(setterName, (*aMethodInfo)->name) != 0) {
|
|
|
|
rv = NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(setterName);
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
2005-02-23 23:19:55 +03:00
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
return rv;
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2005-02-23 23:19:55 +03:00
|
|
|
// If we get here, then maybe the method name is capitalized.
|
|
|
|
char* methodName = strdup(aMethodName);
|
|
|
|
methodName[0] = toupper(methodName[0]);
|
|
|
|
rv = aIInfo->GetMethodInfoForName(methodName, aMethodIndex, aMethodInfo);
|
|
|
|
free(methodName);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// If there is no method called <aMethodName>, then maybe it is an
|
|
|
|
// 'attribute'.
|
|
|
|
if (strlen(aMethodName) > 3) {
|
|
|
|
if (strncmp("get", aMethodName, 3) == 0) {
|
|
|
|
char* getterName = strdup(aMethodName + 3);
|
|
|
|
rv = aIInfo->GetMethodInfoForName(getterName, aMethodIndex, aMethodInfo);
|
|
|
|
free(getterName);
|
|
|
|
} else if (strncmp("set", aMethodName, 3) == 0) {
|
|
|
|
char* setterName = strdup(aMethodName + 3);
|
|
|
|
rv = aIInfo->GetMethodInfoForName(setterName, aMethodIndex, aMethodInfo);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// If this succeeded, GetMethodInfoForName will have returned the
|
|
|
|
// method info for the 'getter'. We want the 'setter', so increase
|
|
|
|
// method index by one ('setter' immediately follows the 'getter'),
|
|
|
|
// and get its method info.
|
|
|
|
(*aMethodIndex)++;
|
|
|
|
rv = aIInfo->GetMethodInfo(*aMethodIndex, aMethodInfo);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// Double check that this methodInfo matches the given method.
|
|
|
|
if (!(*aMethodInfo)->IsSetter() ||
|
|
|
|
strcmp(setterName, (*aMethodInfo)->name) != 0) {
|
|
|
|
rv = NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(setterName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* org.mozilla.xpcom.XPCOMJavaProxy.callXPCOMMethod
|
|
|
|
*/
|
|
|
|
extern "C" JX_EXPORT jobject JNICALL
|
|
|
|
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);
|
2004-09-02 20:34:11 +04:00
|
|
|
|
|
|
|
// Get method info
|
2005-02-23 23:19:55 +03:00
|
|
|
PRUint16 methodIndex;
|
2004-09-02 20:34:11 +04:00
|
|
|
const nsXPTMethodInfo* methodInfo;
|
|
|
|
nsIInterfaceInfo* iinfo = inst->InterfaceInfo();
|
2005-02-23 23:19:55 +03:00
|
|
|
const char* methodName = env->GetStringUTFChars(aMethodName, nsnull);
|
|
|
|
rv = QueryMethodInfo(iinfo, methodName, &methodIndex, &methodInfo);
|
|
|
|
env->ReleaseStringUTFChars(aMethodName, methodName);
|
|
|
|
|
2004-12-23 20:09:54 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
2005-02-23 23:19:55 +03:00
|
|
|
ThrowException(env, rv, "GetMethodInfoForName failed");
|
|
|
|
return nsnull;
|
2004-12-23 20:09:54 +03:00
|
|
|
}
|
|
|
|
|
2005-02-23 23:19:55 +03:00
|
|
|
#ifdef DEBUG_JAVAXPCOM
|
2004-09-02 20:34:11 +04:00
|
|
|
const char* ifaceName;
|
|
|
|
iinfo->GetNameShared(&ifaceName);
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("=> Calling %s::%s()\n", ifaceName, methodInfo->GetName()));
|
2004-09-02 20:34:11 +04:00
|
|
|
#endif
|
|
|
|
|
2004-12-23 20:09:54 +03:00
|
|
|
// Convert the Java params
|
2004-09-02 20:34:11 +04:00
|
|
|
PRUint8 paramCount = methodInfo->GetParamCount();
|
|
|
|
nsXPTCVariant* params = nsnull;
|
|
|
|
if (paramCount)
|
|
|
|
{
|
|
|
|
params = new nsXPTCVariant[paramCount];
|
2005-01-12 20:59:01 +03:00
|
|
|
if (!params) {
|
|
|
|
ThrowException(env, NS_ERROR_OUT_OF_MEMORY, "Can't create params array");
|
2005-02-23 23:19:55 +03:00
|
|
|
return nsnull;
|
2005-01-12 20:59:01 +03:00
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
|
|
|
|
for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
|
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("\t Param %d: ", i));
|
2004-09-02 20:34:11 +04:00
|
|
|
const nsXPTParamInfo ¶mInfo = methodInfo->GetParam(i);
|
|
|
|
|
2005-01-13 19:30:19 +03:00
|
|
|
if (paramInfo.IsIn() && !paramInfo.IsDipper()) {
|
2004-09-02 20:34:11 +04:00
|
|
|
rv = SetupParams(env, env->GetObjectArrayElement(aParams, i), paramInfo,
|
2005-02-23 23:19:55 +03:00
|
|
|
methodInfo, iinfo, methodIndex, params, params[i]);
|
2004-09-02 20:34:11 +04:00
|
|
|
} else if (paramInfo.IsDipper()) {
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("dipper"));
|
2004-09-02 20:34:11 +04:00
|
|
|
const nsXPTType &type = paramInfo.GetType();
|
|
|
|
switch (type.TagPart())
|
|
|
|
{
|
|
|
|
case nsXPTType::T_ASTRING:
|
|
|
|
case nsXPTType::T_DOMSTRING:
|
|
|
|
params[i].val.p = params[i].ptr = new nsString();
|
2005-01-12 20:59:01 +03:00
|
|
|
if (params[i].val.p == nsnull) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
params[i].type = type;
|
|
|
|
params[i].flags = nsXPTCVariant::PTR_IS_DATA |
|
|
|
|
nsXPTCVariant::VAL_IS_DOMSTR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsXPTType::T_UTF8STRING:
|
|
|
|
case nsXPTType::T_CSTRING:
|
|
|
|
params[i].val.p = params[i].ptr = new nsCString();
|
2005-01-12 20:59:01 +03:00
|
|
|
if (params[i].val.p == nsnull) {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
break;
|
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
params[i].type = type;
|
|
|
|
params[i].flags = nsXPTCVariant::PTR_IS_DATA |
|
|
|
|
nsXPTCVariant::VAL_IS_CSTR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2004-11-23 20:02:21 +03:00
|
|
|
LOG(("unhandled dipper type\n"));
|
2004-09-02 20:34:11 +04:00
|
|
|
rv = NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
} else {
|
2005-01-13 19:30:19 +03:00
|
|
|
LOG(("out/retval\n"));
|
2004-09-02 20:34:11 +04:00
|
|
|
params[i].ptr = &(params[i].val);
|
|
|
|
params[i].type = paramInfo.GetType();
|
|
|
|
params[i].flags = nsXPTCVariant::PTR_IS_DATA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
2005-01-12 20:59:01 +03:00
|
|
|
ThrowException(env, rv, "SetupParams failed");
|
2005-02-23 23:19:55 +03:00
|
|
|
return nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-23 20:09:54 +03:00
|
|
|
// Call the XPCOM method
|
2004-09-02 20:34:11 +04:00
|
|
|
nsresult invokeResult;
|
2005-02-23 23:19:55 +03:00
|
|
|
invokeResult = XPTC_InvokeByIndex(inst->GetInstance(), methodIndex,
|
2004-09-02 20:34:11 +04:00
|
|
|
paramCount, params);
|
|
|
|
|
2004-12-23 20:09:54 +03:00
|
|
|
// Clean up params
|
2005-02-23 23:19:55 +03:00
|
|
|
jobject result = nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
|
|
|
|
{
|
|
|
|
const nsXPTParamInfo ¶mInfo = methodInfo->GetParam(i);
|
|
|
|
|
|
|
|
if (!paramInfo.IsRetval()) {
|
|
|
|
rv = FinalizeParams(env, env->GetObjectArrayElement(aParams, i),
|
2005-02-23 23:19:55 +03:00
|
|
|
paramInfo, methodInfo, iinfo, methodIndex,
|
2004-09-02 20:34:11 +04:00
|
|
|
params, params[i]);
|
|
|
|
} else {
|
2005-02-23 23:19:55 +03:00
|
|
|
rv = SetRetval(env, paramInfo, methodInfo, iinfo, methodIndex, params,
|
|
|
|
params[i], &result);
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NS_FAILED(rv)) {
|
2005-01-12 20:59:01 +03:00
|
|
|
ThrowException(env, rv, "FinalizeParams/SetRetval failed");
|
2005-02-23 23:19:55 +03:00
|
|
|
return nsnull;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2004-12-23 20:09:54 +03:00
|
|
|
// 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.
|
2004-11-23 20:02:21 +03:00
|
|
|
for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++)
|
2004-09-02 20:34:11 +04:00
|
|
|
{
|
2004-11-23 20:02:21 +03:00
|
|
|
const nsXPTParamInfo ¶mInfo = methodInfo->GetParam(j);
|
2004-09-02 20:34:11 +04:00
|
|
|
const nsXPTType &type = paramInfo.GetType();
|
|
|
|
if (type.TagPart() == nsXPTType::T_IID) {
|
2004-11-23 20:02:21 +03:00
|
|
|
nsID* iid = (nsID*) params[j].ptr;
|
2004-09-02 20:34:11 +04:00
|
|
|
delete iid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-27 00:14:53 +04:00
|
|
|
if (params) {
|
2004-09-02 20:34:11 +04:00
|
|
|
delete params;
|
2004-10-27 00:14:53 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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)) {
|
2004-12-23 01:03:50 +03:00
|
|
|
nsCAutoString message("The function \"");
|
2005-01-12 20:36:11 +03:00
|
|
|
message.AppendASCII(methodInfo->GetName());
|
|
|
|
message.AppendLiteral("\" returned an error condition");
|
2005-01-12 20:59:01 +03:00
|
|
|
ThrowException(env, invokeResult, message.get());
|
2004-10-27 00:14:53 +04:00
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2005-02-23 23:19:55 +03:00
|
|
|
return result;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2005-01-21 01:07:26 +03:00
|
|
|
nsresult
|
|
|
|
CreateJavaProxy(JNIEnv* env, nsISupports* aXPCOMObject, const nsIID& aIID,
|
|
|
|
jobject* aResult)
|
2004-09-02 20:34:11 +04:00
|
|
|
{
|
2005-01-21 01:07:26 +03:00
|
|
|
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
|
|
|
if (!aResult)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager();
|
|
|
|
NS_ASSERTION(iim != nsnull, "Failed to get InterfaceInfoManager");
|
|
|
|
if (!iim)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Get interface info for class
|
|
|
|
nsCOMPtr<nsIInterfaceInfo> info;
|
|
|
|
nsresult rv = iim->GetInfoForIID(&aIID, getter_AddRefs(info));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// Wrap XPCOM object
|
|
|
|
JavaXPCOMInstance* inst = new JavaXPCOMInstance(aXPCOMObject, info);
|
|
|
|
if (!inst)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
// Get interface name
|
2005-01-21 02:44:58 +03:00
|
|
|
const char* iface_name;
|
|
|
|
rv = info->GetNameShared(&iface_name);
|
2005-01-21 01:07:26 +03:00
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2005-02-23 23:19:55 +03:00
|
|
|
jobject java_obj = nsnull;
|
|
|
|
|
|
|
|
// Create proper Java interface name
|
|
|
|
nsCAutoString class_name("org/mozilla/xpcom/");
|
2005-01-21 01:07:26 +03:00
|
|
|
class_name.AppendASCII(iface_name);
|
2005-02-23 23:19:55 +03:00
|
|
|
jclass ifaceClass = env->FindClass(class_name.get());
|
|
|
|
|
|
|
|
if (ifaceClass) {
|
|
|
|
java_obj = env->CallStaticObjectMethod(xpcomJavaProxyClass,
|
|
|
|
createProxyMID, ifaceClass,
|
|
|
|
NS_REINTERPRET_CAST(jlong, inst));
|
|
|
|
if (env->ExceptionCheck())
|
|
|
|
java_obj = nsnull;
|
2005-01-21 01:07:26 +03:00
|
|
|
}
|
2004-09-02 20:34:11 +04:00
|
|
|
|
2005-01-21 01:07:26 +03:00
|
|
|
if (java_obj) {
|
|
|
|
// Associate XPCOM object with Java proxy
|
|
|
|
rv = gBindings->AddBinding(env, java_obj, inst);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
*aResult = java_obj;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
rv = NS_ERROR_FAILURE;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-01-21 01:07:26 +03:00
|
|
|
// If there was an error, clean up.
|
|
|
|
delete inst;
|
|
|
|
return rv;
|
2004-09-02 20:34:11 +04:00
|
|
|
}
|
|
|
|
|
2005-02-23 23:19:55 +03:00
|
|
|
nsresult
|
|
|
|
GetXPCOMInstFromProxy(JNIEnv* env, jobject aJavaObject, void** aResult)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
|
|
|
if (!aResult)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
long xpcom_obj = env->CallStaticIntMethod(xpcomJavaProxyClass,
|
|
|
|
getNativeXPCOMInstMID, aJavaObject);
|
|
|
|
|
|
|
|
if (!xpcom_obj || env->ExceptionCheck()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aResult = NS_REINTERPRET_CAST(void*, xpcom_obj);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* org.mozilla.xpcom.XPCOMJavaProxy.finalizeProxy
|
|
|
|
*/
|
|
|
|
extern "C" JX_EXPORT void JNICALL
|
|
|
|
JAVAPROXY_NATIVE(finalizeProxy) (JNIEnv *env, jclass that, jobject aJavaProxy)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_JAVAXPCOM
|
|
|
|
jstring string = nsnull;
|
|
|
|
string = (jstring) env->CallStaticObjectMethod(xpcomJavaProxyClass,
|
|
|
|
proxyToStringMID, aJavaProxy);
|
|
|
|
const char* javaObjectName = env->GetStringUTFChars(string, nsnull);
|
|
|
|
LOG(("*** Finalize(java_obj=%s)\n", javaObjectName));
|
|
|
|
env->ReleaseStringUTFChars(string, javaObjectName);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Due to Java's garbage collection, this finalize statement may get called
|
|
|
|
// after FreeJavaGlobals(). So check to make sure that everything is still
|
|
|
|
// initialized.
|
|
|
|
if (gJavaXPCOMLock) {
|
|
|
|
nsAutoLock lock(gJavaXPCOMLock);
|
|
|
|
|
|
|
|
// Get native XPCOM instance
|
|
|
|
void* xpcom_obj;
|
|
|
|
nsresult rv = GetXPCOMInstFromProxy(env, aJavaProxy, &xpcom_obj);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
JavaXPCOMInstance* inst = NS_STATIC_CAST(JavaXPCOMInstance*, xpcom_obj);
|
|
|
|
gBindings->RemoveBinding(env, aJavaProxy, nsnull);
|
|
|
|
delete inst;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|