Modularize code (somewhat), general cleanup. Proxy-related code has
been moved to xpj_proxy.c, code used only for testing has been copied into xptest.cpp, and each "module" now has its own header (for internal use only).
This commit is contained in:
Родитель
4ac35ad444
Коммит
1f877c97be
|
@ -31,6 +31,7 @@ LIBRARY_NAME = xpjava
|
|||
|
||||
CPPSRCS = \
|
||||
xpjava.cpp \
|
||||
xpj_proxy.cpp \
|
||||
xpj_XPCMethod.cpp \
|
||||
xpj_ComUtilities.cpp \
|
||||
xpj_nsID.cpp \
|
||||
|
|
|
@ -36,39 +36,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Because not all platforms convert jlong to "long long"
|
||||
*
|
||||
* NOTE: this code was cut&pasted from xpj_XPCMethod.cpp, with tweaks.
|
||||
* Normally I wouldn't do this, but my reasons are:
|
||||
*
|
||||
* 1. My alternatives were to put it in xpjava.h or xpjava.cpp
|
||||
* I'd like to take stuff *out* of xpjava.h, and putting it
|
||||
* in xpjava.cpp would preclude inlining.
|
||||
*
|
||||
* 2. How we map proxies to XPCOM objects is an implementation
|
||||
* detail, which may change in the future (e.g. an index
|
||||
* into a proxy table). Thus ToPtr/ToJLong is only of
|
||||
* interest to those objects that stuff pointers into jlongs.
|
||||
*
|
||||
* 3. This allows adaptations to each implementation, for
|
||||
* type safety (e.g. ToPtr returning nsISupports*).
|
||||
*
|
||||
* -- frankm, 99.09.09
|
||||
*/
|
||||
static inline nsISupports* ToPtr(jlong l) {
|
||||
int result;
|
||||
jlong_L2I(result, l);
|
||||
return (nsISupports *)result;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_org_mozilla_xpcom_XPComUtilities_initialize(JNIEnv *env, jclass cls)
|
||||
{
|
||||
nsresult res = InitXPCOM();
|
||||
nsresult res = xpj_InitXPCOM();
|
||||
if (NS_FAILED(res)) return JNI_FALSE;
|
||||
|
||||
return InitJavaCaches(env);
|
||||
return xpjd_InitJavaCaches(env); // XXX: remove; do in dispatch
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -88,7 +62,10 @@ JNIEXPORT jobject JNICALL Java_org_mozilla_xpcom_XPComUtilities_CreateInstance
|
|||
nsISupports *delegate = NULL;
|
||||
|
||||
if (jdelegate != NULL) {
|
||||
delegate = This(env, jdelegate);
|
||||
xpjp_QueryInterfaceToXPCOM(env,
|
||||
jdelegate,
|
||||
NS_GET_IID(nsISupports),
|
||||
(void **)&delegate);
|
||||
}
|
||||
|
||||
assert(classID != NULL && interfaceID != NULL);
|
||||
|
@ -117,7 +94,7 @@ JNIEXPORT jobject JNICALL Java_org_mozilla_xpcom_XPComUtilities_CreateInstance
|
|||
// cerr << "Wrapping " << sample << " in new ComObject" << endl;
|
||||
|
||||
// Wrap it in an ComObject
|
||||
result = NewComObject(env, xpcobj, interfaceID);
|
||||
result = xpjp_QueryInterfaceToJava(env, xpcobj, *interfaceID);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -171,7 +148,7 @@ JNIEXPORT void JNICALL Java_org_mozilla_xpcom_XPComUtilities_RegisterComponent
|
|||
JNIEXPORT void JNICALL Java_org_mozilla_xpcom_XPComUtilities_AddRef
|
||||
(JNIEnv *env, jclass cls, jlong ref)
|
||||
{
|
||||
(ToPtr(ref))->AddRef();
|
||||
xpjp_SafeAddRefProxyID(ref);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -182,7 +159,7 @@ JNIEXPORT void JNICALL Java_org_mozilla_xpcom_XPComUtilities_AddRef
|
|||
JNIEXPORT void JNICALL Java_org_mozilla_xpcom_XPComUtilities_Release
|
||||
(JNIEnv *env, jclass cls, jlong ref)
|
||||
{
|
||||
(ToPtr(ref))->Release();
|
||||
xpjp_SafeReleaseProxyID(ref);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -197,51 +174,20 @@ JNIEXPORT void JNICALL
|
|||
jlong ref,
|
||||
jint index,
|
||||
jobjectArray args) {
|
||||
nsXPTCVariant variantArray[12];
|
||||
nsXPTCVariant *variantPtr = variantArray;
|
||||
int paramcount;
|
||||
nsID *nativeIID = ID_GetNative(env, iid);
|
||||
nsIInterfaceInfo *info = nsnull;
|
||||
nsISupports *target;
|
||||
|
||||
// PENDING: Get real IID
|
||||
paramcount =
|
||||
BuildParamsForOffset(nativeIID, index, &variantPtr);
|
||||
// XXX: check for success
|
||||
xpjd_GetInterfaceInfo(env, iid, &info);
|
||||
|
||||
if (paramcount < 0) {
|
||||
// PENDING: throw an exception
|
||||
}
|
||||
else {
|
||||
nsresult res;
|
||||
// XXX: s.b. just |xpjp_UnwrapProxy(env, self);|
|
||||
nsIID *nativeIID = ID_GetNative(env, iid);
|
||||
xpjp_QueryInterfaceForProxyID(ref, *nativeIID, (void**)&target);
|
||||
|
||||
res = JArrayToVariant(env, paramcount, variantPtr, args);
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Array and parameter list mismatch" << endl;
|
||||
return;
|
||||
}
|
||||
xpjd_InvokeMethod(env, target, info, index, args);
|
||||
|
||||
nsISupports* true_this = ToPtr(ref);
|
||||
|
||||
//true_this->AddRef();
|
||||
res = XPTC_InvokeByIndex(true_this,
|
||||
(PRUint32)index,
|
||||
(PRUint32)paramcount,
|
||||
variantPtr);
|
||||
|
||||
//true_this->Release();
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Invocation failed, status: " << res << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
res = VariantToJArray(env, args, paramcount, variantPtr);
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Array and parameter list mismatch" << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// XXX: remove when ref not QueryInterface'd
|
||||
xpjp_SafeReleaseProxyID(ref);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -39,7 +39,7 @@ static jfieldID XPCMethod_count_ID = NULL;
|
|||
|
||||
jclass classXPCMethod = NULL;
|
||||
|
||||
#define USE_PARAM_TEMPLATE
|
||||
#undef USE_PARAM_TEMPLATE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -89,10 +89,18 @@ JNIEXPORT jint JNICALL
|
|||
const char *tmpstr;
|
||||
nsresult res;
|
||||
|
||||
// Get method info
|
||||
tmpstr = env->GetStringUTFChars(methodName, NULL);
|
||||
res = GetMethodInfoByName(iidPtr, tmpstr, PR_FALSE, &mi, &offset);
|
||||
// Get interface info
|
||||
nsIInterfaceInfo *info = nsnull;
|
||||
|
||||
res = (XPTI_GetInterfaceInfoManager())->GetInfoForIID(iidPtr, &info);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find info for " << iidPtr->ToString() << endl;
|
||||
return res;
|
||||
}
|
||||
|
||||
tmpstr = env->GetStringUTFChars(methodName, NULL);
|
||||
res = xpj_GetMethodInfoByName(iidPtr, tmpstr, PR_FALSE, &mi, &offset);
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Cannot find method for: " << (char *)tmpstr << endl;
|
||||
return -1;
|
||||
|
@ -147,7 +155,7 @@ JNIEXPORT jint JNICALL
|
|||
|
||||
env->SetLongField(self,
|
||||
XPCMethod_infoptr_ID,
|
||||
ToJLong(mi));
|
||||
ToJLong(info));
|
||||
|
||||
env->SetIntField(self,
|
||||
XPCMethod_count_ID,
|
||||
|
@ -155,8 +163,8 @@ JNIEXPORT jint JNICALL
|
|||
|
||||
#ifdef USE_PARAM_TEMPLATE
|
||||
// Build parameter array
|
||||
nsXPTCVariant *variantPtr = new nsXPTCVariant[mi->GetParamCount()];
|
||||
BuildParamsForMethodInfo(mi, variantPtr);
|
||||
nsXPTCVariant *variantPtr = NULL;
|
||||
xpjd_BuildParamsForOffset(info, offset, 0, &variantPtr);
|
||||
|
||||
env->SetLongField(self,
|
||||
XPCMethod_frameptr_ID,
|
||||
|
@ -181,7 +189,9 @@ JNIEXPORT void JNICALL
|
|||
jobject self, jlong peer) {
|
||||
|
||||
nsXPTCVariant *variantPtr = (nsXPTCVariant *)ToPtr(peer);
|
||||
delete [] variantPtr;
|
||||
if (variantPtr != NULL) {
|
||||
nsAllocator::Free(variantPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -199,9 +209,13 @@ JNIEXPORT jint JNICALL Java_org_mozilla_xpcom_XPCMethod_getParameterType
|
|||
return -1;
|
||||
}
|
||||
else {
|
||||
jint offset = env->GetIntField(self, XPCMethod_offset_ID);
|
||||
jlong ptrval = env->GetLongField(self, XPCMethod_infoptr_ID);
|
||||
const nsXPTMethodInfo *mi =
|
||||
(const nsXPTMethodInfo *)ToPtr(ptrval);
|
||||
|
||||
const nsXPTMethodInfo *mi;
|
||||
nsIInterfaceInfo *info = (nsIInterfaceInfo *)ToPtr(ptrval);
|
||||
|
||||
info->GetMethodInfo(offset, &mi);
|
||||
return mi->GetParam(index).GetType().TagPart();
|
||||
}
|
||||
}
|
||||
|
@ -232,14 +246,18 @@ JNIEXPORT void JNICALL Java_org_mozilla_xpcom_XPCMethod_invoke
|
|||
}
|
||||
|
||||
jint offset = env->GetIntField(self, XPCMethod_offset_ID);
|
||||
jint paramcount = env->GetIntField(self, XPCMethod_count_ID);
|
||||
|
||||
nsXPTCVariant variantArray[paramcount];
|
||||
jlong infoptr = env->GetLongField(self, XPCMethod_infoptr_ID);
|
||||
nsIInterfaceInfo *info =
|
||||
(nsIInterfaceInfo *)ToPtr(infoptr);
|
||||
|
||||
#ifdef USE_PARAM_TEMPLATE
|
||||
jlong ptrval = env->GetLongField(self, XPCMethod_frameptr_ID);
|
||||
jint paramcount = env->GetIntField(self, XPCMethod_count_ID);
|
||||
|
||||
nsXPTCVariant *paramTemplate =
|
||||
(nsXPTCVariant *)ToPtr(ptrval);
|
||||
(nsXPTCVariant *)ToPtr(env->GetLongField(self, XPCMethod_frameptr_ID));
|
||||
|
||||
nsXPTCVariant variantArray[paramcount];
|
||||
|
||||
memcpy(variantArray, paramTemplate, paramcount * sizeof(nsXPTCVariant));
|
||||
// Fix pointers
|
||||
|
@ -249,42 +267,20 @@ JNIEXPORT void JNICALL Java_org_mozilla_xpcom_XPCMethod_invoke
|
|||
current->ptr = ¤t->val;
|
||||
}
|
||||
}
|
||||
#else
|
||||
jlong ptrval = env->GetLongField(self, XPCMethod_infoptr_ID);
|
||||
const nsXPTMethodInfo *mi =
|
||||
(const nsXPTMethodInfo *)ToPtr(ptrval);
|
||||
BuildParamsForMethodInfo(mi, variantArray);
|
||||
#endif
|
||||
nsIID* iid = nsnull;
|
||||
nsISupports *true_target = nsnull;
|
||||
|
||||
res = JArrayToVariant(env, paramcount, variantArray, params);
|
||||
// XXX: check for success
|
||||
info->GetIID(&iid);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "JArrayToVariant failed, status: " << res << endl;
|
||||
return;
|
||||
}
|
||||
// XXX: check for success
|
||||
xpjp_QueryInterfaceToXPCOM(env, target, *iid, (void**)&true_target);
|
||||
|
||||
nsISupports* true_target = This(env, target);
|
||||
|
||||
res = XPTC_InvokeByIndex(true_target,
|
||||
(PRUint32)offset,
|
||||
(PRUint32)paramcount,
|
||||
variantArray);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Method failed, status: " << res << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
res = VariantToJArray(env, params, paramcount, variantArray);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "VariantToJArray failed, status: " << res << endl;
|
||||
return;
|
||||
}
|
||||
xpjd_InvokeMethod(env, true_target, info, offset, params);
|
||||
|
||||
xpjp_SafeRelease(true_target);
|
||||
nsAllocator::Free(iid);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (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.
|
||||
*
|
||||
* Contributors:
|
||||
* Frank Mitchell (frank.mitchell@sun.com)
|
||||
*/
|
||||
#include <jni.h>
|
||||
#include "nsISupports.h"
|
||||
#include "xptcall.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize caches for often-used Java classes (all in java.lang).
|
||||
* Will return JNI_FALSE if those classes, or their fields
|
||||
* and methods, aren't found.
|
||||
* @deprecated
|
||||
*/
|
||||
/* XXX: should be hidden in first call to xpjd_InvokeMethod */
|
||||
jboolean xpjd_InitJavaCaches(JNIEnv *env);
|
||||
|
||||
/**
|
||||
* Uncaches often-used Java classes (e.g. during unload).
|
||||
*/
|
||||
/* XXX: should be part of general unloading mechanism */
|
||||
void xpjd_FlushJavaCaches(JNIEnv *env);
|
||||
|
||||
/**
|
||||
* Convenience method to get the nsIInterfaceInfo for an
|
||||
* interface denoted by the Java IID object `iid'.
|
||||
* Will return JNI_FALSE if `iid' isn't a org.mozilla.xpcom.nsID
|
||||
* or no info object exists.
|
||||
*/
|
||||
jboolean xpjd_GetInterfaceInfo(JNIEnv *env,
|
||||
jobject iid,
|
||||
nsIInterfaceInfo **info);
|
||||
|
||||
/**
|
||||
* Convenience method to get the nsIInterfaceInfo for an
|
||||
* interface denoted by the C++ struct `iid'.
|
||||
* Will return JNI_FALSE if `iid' isn't a org.mozilla.xpcom.nsID
|
||||
* or no info object exists.
|
||||
*/
|
||||
jboolean xpjd_GetInterfaceInfoNative(REFNSIID iid,
|
||||
nsIInterfaceInfo **info);
|
||||
|
||||
/**
|
||||
* Invoke a method on 'target' indicated by the 'methodIndex'-th
|
||||
* method in `info', with arguments `args'.
|
||||
* Throws a Java exception if `target' can't receive the method,
|
||||
* `methodIndex' is out of bounds, `args' contains too few arguments,
|
||||
* or any of the pointer arguments is NULL.
|
||||
*/
|
||||
void xpjd_InvokeMethod(JNIEnv *env,
|
||||
nsISupports *target,
|
||||
nsIInterfaceInfo *info,
|
||||
jint methodIndex,
|
||||
jobjectArray args);
|
||||
|
||||
#if 0 /* not implemented yet */
|
||||
|
||||
/**
|
||||
* Optimized version of `xpjd_InvokeMethod' to get attributes, or
|
||||
* methods with only one in parameter and no outs or inouts.
|
||||
*/
|
||||
jobject xpjd_GetAttribute(JNIEnv *env,
|
||||
nsISupports *target,
|
||||
nsIInterfaceInfo *info,
|
||||
jint getMethodIndex);
|
||||
|
||||
/**
|
||||
* Optimized version of `xpjd_InvokeMethod' to set attributes, or
|
||||
* methods with only one out parameter and no ins or inouts.
|
||||
*/
|
||||
void xpjd_SetAttribute(JNIEnv *env,
|
||||
nsISupports *target,
|
||||
nsIInterfaceInfo *info,
|
||||
jint setMethodIndex,
|
||||
jobject value);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (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.
|
||||
*
|
||||
* Contributors:
|
||||
* Frank Mitchell (frank.mitchell@sun.com)
|
||||
*/
|
||||
#include "xpjava.h"
|
||||
|
||||
#define JAVA_XPCOBJECT_CLASS "org/mozilla/xpcom/ComObject"
|
||||
|
||||
static jclass classComObject = NULL;
|
||||
static jfieldID ComObject_objptr_ID = NULL;
|
||||
|
||||
/* --------- SUPPORT FUNCTIONS ------------- */
|
||||
|
||||
/* Because not all platforms convert jlong to "long long"
|
||||
*
|
||||
* NOTE: this code was cut&pasted from xpj_XPCMethod.cpp, with tweaks.
|
||||
* Normally I wouldn't do this, but my reasons are:
|
||||
*
|
||||
* 1. My alternatives were to put it in xpjava.h or xpjava.cpp
|
||||
* I'd like to take stuff *out* of xpjava.h, and putting it
|
||||
* in xpjava.cpp would preclude inlining.
|
||||
*
|
||||
* 2. How we map proxies to XPCOM objects is an implementation
|
||||
* detail, which may change in the future (e.g. an index
|
||||
* into a proxy table). Thus ToPtr/ToJLong is only of
|
||||
* interest to those objects that stuff pointers into jlongs.
|
||||
*
|
||||
* 3. This allows adaptations to each implementation, for
|
||||
* type safety (e.g. taking and returning nsISupports*).
|
||||
*
|
||||
* -- frankm, 99.09.09
|
||||
*/
|
||||
static inline jlong ToJLong(nsISupports *p) {
|
||||
jlong result;
|
||||
jlong_I2L(result, (int)p);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline nsISupports* ToPtr(jlong l) {
|
||||
int result;
|
||||
jlong_L2I(result, l);
|
||||
return (nsISupports *)result;
|
||||
}
|
||||
|
||||
static inline jboolean xpjp_QueryInterface(nsISupports *object,
|
||||
REFNSIID iid,
|
||||
void **instance) {
|
||||
assert(object != NULL && instance != NULL);
|
||||
|
||||
if (NS_SUCCEEDED(object->QueryInterface(iid, instance))) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean xpjp_InitJavaCaches(JNIEnv *env) {
|
||||
if (ComObject_objptr_ID == NULL) {
|
||||
classComObject = env->FindClass(JAVA_XPCOBJECT_CLASS);
|
||||
if (classComObject == NULL) return JNI_FALSE;
|
||||
|
||||
classComObject = (jclass)env->NewGlobalRef(classComObject);
|
||||
if (classComObject == NULL) return JNI_FALSE;
|
||||
|
||||
ComObject_objptr_ID = env->GetFieldID(classComObject, "objptr", "J");
|
||||
if (ComObject_objptr_ID == NULL) return JNI_FALSE;
|
||||
}
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static jclass xpjp_ClassForInterface(JNIEnv *env, REFNSIID iid) {
|
||||
#if 0
|
||||
// Get info
|
||||
jclass result = classComObject; // null?
|
||||
nsIInterfaceInfo *info = nsnull;
|
||||
char *interface_name;
|
||||
char *name_space;
|
||||
char *full_classname;
|
||||
char *ch;
|
||||
nsresult res;
|
||||
|
||||
res = interfaceInfoManager->GetInfoForIID(&iid, &info);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find info for " << iid.ToString() << endl;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// XXX: PENDING: find name_space somehow
|
||||
name_space = "org.mozilla.xpcom";
|
||||
|
||||
res = info->GetName(&interface_name);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find name for " << iid.ToString() << endl;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Construct class name
|
||||
full_classname =
|
||||
(char*)nsAllocator::Alloc(strlen(interface_name) + strlen(name_space) + 2);
|
||||
|
||||
strcpy(full_classname, name_space);
|
||||
ch = full_classname;
|
||||
while (ch != '\0') {
|
||||
if (*ch == '.') {
|
||||
*ch = '/';
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
strcat(full_classname, "/");
|
||||
strcat(full_classname, interface_name);
|
||||
|
||||
cerr << "Looking for " << full_classname << endl;
|
||||
|
||||
result = env->FindClass(full_classname);
|
||||
// XXX: PENDING: If no such class found, make it
|
||||
|
||||
// XXX: PENDING: Cache result
|
||||
end:
|
||||
// Cleanup
|
||||
nsAllocator::Free(interface_name);
|
||||
nsAllocator::Free(full_classname);
|
||||
//nsAllocator::Free(name_space);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return classComObject;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* --------- PROXY API FUNCTIONS ------------- */
|
||||
|
||||
jobject xpjp_QueryInterfaceToJava(JNIEnv *env,
|
||||
nsISupports *obj,
|
||||
REFNSIID iid) {
|
||||
if (!xpjp_InitJavaCaches(env)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// XXX: Bad implementation; returns a new proxy every time
|
||||
jobject result = 0;
|
||||
jmethodID initID = 0;
|
||||
jclass proxyClass = xpjp_ClassForInterface(env, iid);
|
||||
jobject jiid = ID_NewJavaID(env, &iid);
|
||||
|
||||
assert(proxyClass != 0);
|
||||
|
||||
initID = env->GetMethodID(proxyClass, "<init>", "(J)V");
|
||||
|
||||
if (initID != NULL) {
|
||||
result = env->NewObject(proxyClass, initID, ToJLong(obj), jiid);
|
||||
}
|
||||
else {
|
||||
initID = env->GetMethodID(proxyClass, "<init>", "()V");
|
||||
|
||||
result = env->NewObject(proxyClass, initID);
|
||||
env->SetLongField(result, ComObject_objptr_ID, ToJLong(obj));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
jboolean xpjp_QueryInterfaceToXPCOM(JNIEnv *env,
|
||||
jobject proxy,
|
||||
REFNSIID iid,
|
||||
void **instance) {
|
||||
nsISupports* xpcobj = xpjp_UnwrapProxy(env, proxy);
|
||||
if (xpcobj != NULL) {
|
||||
return xpjp_QueryInterface(xpcobj, iid, instance);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsISupports* xpjp_UnwrapProxy(JNIEnv *env, jobject proxy) {
|
||||
if (!xpjp_InitJavaCaches(env)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
return ToPtr(env->GetLongField(proxy, ComObject_objptr_ID));
|
||||
}
|
||||
|
||||
void xpjp_SafeAddRef(nsISupports *object) {
|
||||
/* XXX: NOT "SAFE" */
|
||||
NS_ADDREF(object);
|
||||
}
|
||||
|
||||
void xpjp_SafeRelease(nsISupports *object) {
|
||||
/* XXX: NOT "SAFE" */
|
||||
NS_RELEASE(object);
|
||||
}
|
||||
|
||||
void xpjp_SafeAddRefProxy(JNIEnv *env, jobject proxy) {
|
||||
nsISupports* xpcobj = xpjp_UnwrapProxy(env, proxy);
|
||||
if (xpcobj != NULL) {
|
||||
xpjp_SafeAddRef(xpcobj);
|
||||
}
|
||||
}
|
||||
|
||||
void xpjp_SafeReleaseProxy(JNIEnv *env, jobject proxy) {
|
||||
nsISupports* xpcobj = xpjp_UnwrapProxy(env, proxy);
|
||||
if (xpcobj != NULL) {
|
||||
xpjp_SafeRelease(xpcobj);
|
||||
}
|
||||
}
|
||||
|
||||
/* deprecated */
|
||||
jboolean xpjp_QueryInterfaceForProxyID(jlong ref,
|
||||
REFNSIID iid,
|
||||
void **instance) {
|
||||
nsISupports *xpcobj = ToPtr(ref);
|
||||
|
||||
if (xpcobj != NULL) {
|
||||
return xpjp_QueryInterface(xpcobj, iid, instance);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* deprecated */
|
||||
void xpjp_SafeReleaseProxyID(jlong ref) {
|
||||
xpjp_SafeRelease(ToPtr(ref));
|
||||
}
|
||||
|
||||
/* deprecated */
|
||||
void xpjp_SafeAddRefProxyID(jlong ref) {
|
||||
xpjp_SafeAddRef(ToPtr(ref));
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (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.
|
||||
*
|
||||
* Contributors:
|
||||
* Frank Mitchell (frank.mitchell@sun.com)
|
||||
*/
|
||||
#include <jni.h>
|
||||
#include "nsISupports.h"
|
||||
#include "xptcall.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns a jobject implementing the interface indicated by `iid',
|
||||
* or NULL if `ptr' does not implement that interface.
|
||||
* The function wraps the XPCOM object in a Java proxy, unless it
|
||||
* is itself a proxy to a Java object; in that case, it unwraps the
|
||||
* proxy before testing.
|
||||
* The refcount of `ptr' will be incremented if it is wrapped.
|
||||
*/
|
||||
/* XXX: should we skip actual QueryInterface if not a proxy? */
|
||||
jobject xpjp_QueryInterfaceToJava(JNIEnv *env,
|
||||
nsISupports *ptr,
|
||||
REFNSIID iid);
|
||||
|
||||
/**
|
||||
* Sets `instance' to an instance of the interface indicated by `iid'.
|
||||
* If the Java object is a proxy, the function unwraps it and performs
|
||||
* QueryInterface(); otherwise, it performs QueryInterface() on
|
||||
* `object' and, if that succeeds, wraps it in a C++ proxy.
|
||||
* The refcount of `object' will be incremented if it is unwrapped.
|
||||
*/
|
||||
jboolean xpjp_QueryInterfaceToXPCOM(JNIEnv *env,
|
||||
jobject object,
|
||||
REFNSIID iid,
|
||||
void **instance);
|
||||
|
||||
/**
|
||||
* If `proxy' is a proxy to a nsISupports, returns the
|
||||
* contained pointer and returns true; otherwise, return NULL.
|
||||
* Used mainly for proxy implementation; others should
|
||||
* use QueryInterfaceToXPCOM().
|
||||
* The refcount of the return value is unchanged.
|
||||
*/
|
||||
nsISupports* xpjp_UnwrapProxy(JNIEnv *env, jobject proxy);
|
||||
|
||||
/**
|
||||
* Perform ptr->AddRef() in a thread-safe manner.
|
||||
*/
|
||||
void xpjp_SafeAddRef(nsISupports *ptr);
|
||||
|
||||
/**
|
||||
* Perform ptr->Release() in a thread-safe manner.
|
||||
*/
|
||||
void xpjp_SafeRelease(nsISupports *ptr);
|
||||
|
||||
/**
|
||||
* Perform AddRef() on `proxy''s underlying object in a
|
||||
* thread-safe manner.
|
||||
* Has no effect if proxy is not a proxy to a ref-counted object.
|
||||
*/
|
||||
void xpjp_SafeAddRefProxy(JNIEnv *env, jobject proxy);
|
||||
|
||||
/**
|
||||
* Perform Release() on `proxy''s underlying object in a
|
||||
* thread-safe manner.
|
||||
* Has no effect if proxy is not a proxy to a ref-counted object.
|
||||
*/
|
||||
void xpjp_SafeReleaseProxy(JNIEnv *env, jobject proxy);
|
||||
|
||||
|
||||
/* deprecated API */
|
||||
|
||||
jboolean xpjp_QueryInterfaceForProxyID(jlong ref,
|
||||
REFNSIID iid,
|
||||
void **instance);
|
||||
|
||||
void xpjp_SafeAddRefProxyID(jlong ref);
|
||||
|
||||
void xpjp_SafeReleaseProxyID(jlong ref);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.0 (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.
|
||||
*
|
||||
* Contributors:
|
||||
* Frank Mitchell (frank.mitchell@sun.com)
|
||||
*/
|
||||
#include <jni.h>
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "xptinfo.h"
|
||||
|
||||
/*
|
||||
* Macros defined in some, but not all, jni_md.h, for
|
||||
* compilers that don't have 64 bit ints.
|
||||
*/
|
||||
#ifndef jlong_L2I
|
||||
# define jlong_L2I(_i, _l) ((_i) = (_l))
|
||||
# define jlong_I2L(_l, _i) ((_l) = (_i))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Start up XPCOM
|
||||
* @deprecated
|
||||
*/
|
||||
/* XXX: should move into test directory */
|
||||
nsresult xpj_InitXPCOM();
|
||||
|
||||
/**
|
||||
* Find the method info for method or attribute `methodname'.
|
||||
* If an attribute, do not prefix with "get" or "set"; set
|
||||
* `wantsSetter' to select the getter or setter.
|
||||
* The contents of `indexPtr' are set to the method's index.
|
||||
*/
|
||||
nsresult xpj_GetMethodInfoByName(const nsID *iid,
|
||||
const char *methodname,
|
||||
PRBool wantSetter,
|
||||
const nsXPTMethodInfo **miptr,
|
||||
int *indexPtr);
|
||||
|
||||
/* Defined in xpj_nsID.cpp */
|
||||
|
||||
/** Create a new Java wrapper for `id' */
|
||||
jobject ID_NewJavaID(JNIEnv *env, const nsID* id);
|
||||
|
||||
/** Unwrap an nsID; returns the internal struct, *not a copy* */
|
||||
nsID* ID_GetNative(JNIEnv *env, jobject self);
|
||||
|
||||
/** Copies `id' to a Java wrapper */
|
||||
void ID_SetNative(JNIEnv *env, jobject self, nsID* id);
|
||||
|
||||
/** Compares two Java wrappers for an nsID */
|
||||
jboolean ID_IsEqual(JNIEnv *env, jobject self, jobject other);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -42,8 +42,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define JAVA_XPCOBJECT_CLASS "org/mozilla/xpcom/ComObject"
|
||||
|
||||
|
||||
/* Global references to frequently used classes and objects */
|
||||
static jclass classString;
|
||||
|
@ -55,7 +53,6 @@ static jclass classFloat;
|
|||
static jclass classDouble;
|
||||
static jclass classBoolean;
|
||||
static jclass classCharacter;
|
||||
static jclass classComObject;
|
||||
|
||||
/* Cached field and method IDs */
|
||||
static jfieldID Byte_value_ID;
|
||||
|
@ -67,8 +64,6 @@ static jfieldID Double_value_ID;
|
|||
static jfieldID Boolean_value_ID;
|
||||
static jfieldID Character_value_ID;
|
||||
|
||||
static jfieldID ComObject_objptr_ID;
|
||||
|
||||
static jmethodID Byte_init_ID;
|
||||
static jmethodID Short_init_ID;
|
||||
static jmethodID Integer_init_ID;
|
||||
|
@ -81,137 +76,35 @@ static jmethodID Character_init_ID;
|
|||
/* Global references to frequently used XPCOM objects */
|
||||
static nsIInterfaceInfoManager *interfaceInfoManager;
|
||||
|
||||
static NS_DEFINE_IID(kAllocatorCID, NS_ALLOCATOR_CID);
|
||||
/* Flag to indicate caches filled */
|
||||
static jboolean cache_initialized = JNI_FALSE;
|
||||
|
||||
/* ---------- SUPPORT FUNCTIONS ------------ */
|
||||
|
||||
nsISupports *This(JNIEnv *env, jobject self) {
|
||||
jlong objptr = env->GetLongField(self, ComObject_objptr_ID);
|
||||
/* ---------- GENERAL API FUNCTIONS ------------ */
|
||||
|
||||
nsISupports *result = (nsISupports *)objptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
jclass ClassForInterface(JNIEnv *env, const nsIID *iid) {
|
||||
#if 0
|
||||
// Get info
|
||||
jclass result = classComObject; // null?
|
||||
nsIInterfaceInfo *info = nsnull;
|
||||
char *interface_name;
|
||||
char *name_space;
|
||||
char *full_classname;
|
||||
char *ch;
|
||||
nsresult xpj_InitXPCOM() {
|
||||
nsresult res;
|
||||
|
||||
res = interfaceInfoManager->GetInfoForIID(iid, &info);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find info for " << iid->ToString() << endl;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// XXX: PENDING: find name_space somehow
|
||||
name_space = "org.mozilla.xpcom";
|
||||
|
||||
res = info->GetName(&interface_name);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find name for " << iid->ToString() << endl;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Construct class name
|
||||
full_classname =
|
||||
(char*)nsAllocator::Alloc(strlen(interface_name) + strlen(name_space) + 2);
|
||||
|
||||
strcpy(full_classname, name_space);
|
||||
ch = full_classname;
|
||||
while (ch != '\0') {
|
||||
if (*ch == '.') {
|
||||
*ch = '/';
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
strcat(full_classname, "/");
|
||||
strcat(full_classname, interface_name);
|
||||
|
||||
cerr << "Looking for " << full_classname << endl;
|
||||
|
||||
result = env->FindClass(full_classname);
|
||||
// XXX: PENDING: If no such class found, make it
|
||||
|
||||
// XXX: PENDING: Cache result
|
||||
end:
|
||||
// Cleanup
|
||||
nsAllocator::Free(interface_name);
|
||||
nsAllocator::Free(full_classname);
|
||||
//nsAllocator::Free(name_space);
|
||||
|
||||
return result;
|
||||
#else
|
||||
return classComObject;
|
||||
#ifdef DEBUG_frankm
|
||||
cerr << "Initializing XPCOM" << endl;
|
||||
#endif
|
||||
|
||||
// Autoregistration magic. Boogeda boogeda.
|
||||
res = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
|
||||
nsnull);
|
||||
|
||||
#ifdef DEBUG_frankm
|
||||
cerr << "XPCOM Initialized" << endl;
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
jobject NewComObject(JNIEnv *env, nsISupports *xpcobj, const nsIID *iid) {
|
||||
jobject result = 0;
|
||||
jmethodID initID = 0;
|
||||
jclass proxyClass = ClassForInterface(env, iid);
|
||||
jobject jiid = ID_NewJavaID(env, iid);
|
||||
|
||||
assert(proxyClass != 0);
|
||||
|
||||
initID = env->GetMethodID(proxyClass, "<init>", "(J)V");
|
||||
|
||||
if (initID != NULL) {
|
||||
result = env->NewObject(proxyClass, initID, (jlong)xpcobj, jiid);
|
||||
}
|
||||
else {
|
||||
initID = env->GetMethodID(proxyClass, "<init>", "()V");
|
||||
|
||||
result = env->NewObject(proxyClass, initID);
|
||||
env->SetLongField(result, ComObject_objptr_ID, (jlong)xpcobj);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult GetMethodInfo(const nsID *iid, jint offset,
|
||||
const nsXPTMethodInfo **_retval) {
|
||||
nsresult res;
|
||||
|
||||
// Get info
|
||||
nsIInterfaceInfo *info = nsnull;
|
||||
|
||||
res = interfaceInfoManager->GetInfoForIID(iid, &info);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find info for " << iid->ToString() << endl;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Find info for command
|
||||
uint16 methodcount;
|
||||
|
||||
info->GetMethodCount(&methodcount);
|
||||
|
||||
if (offset < methodcount) {
|
||||
info->GetMethodInfo(offset, _retval);
|
||||
}
|
||||
else {
|
||||
cerr << "Offset " << offset << " out of range for IID "
|
||||
<< iid->ToString() << endl;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetMethodInfoByName(const nsID *iid,
|
||||
const char *methodname,
|
||||
PRBool wantSetter,
|
||||
const nsXPTMethodInfo **miptr,
|
||||
int *_retval) {
|
||||
nsresult xpj_GetMethodInfoByName(const nsID *iid,
|
||||
const char *methodname,
|
||||
PRBool wantSetter,
|
||||
const nsXPTMethodInfo **miptr,
|
||||
int *_retval) {
|
||||
nsresult res;
|
||||
|
||||
// Get info
|
||||
|
@ -256,11 +149,44 @@ nsresult GetMethodInfoByName(const nsID *iid,
|
|||
return res;
|
||||
}
|
||||
|
||||
void BuildParamsForMethodInfo(const nsXPTMethodInfo *mi,
|
||||
nsXPTCVariant variantArray[]) {
|
||||
/* ---------- DISPATCH SUPPORT FUNCTIONS ------------ */
|
||||
|
||||
static
|
||||
int xpjd_BuildParamsForOffset(nsIInterfaceInfo *info,
|
||||
jint offset,
|
||||
jint arraysize,
|
||||
nsXPTCVariant **_retval) {
|
||||
const nsXPTMethodInfo *mi;
|
||||
nsresult res;
|
||||
|
||||
// Find info for command
|
||||
uint16 methodcount;
|
||||
|
||||
info->GetMethodCount(&methodcount);
|
||||
|
||||
if (offset < methodcount) {
|
||||
info->GetMethodInfo(offset, &mi);
|
||||
}
|
||||
else {
|
||||
cerr << "Offset " << offset << " should be < " << methodcount << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Make sure the array is large enough, and alloc more if
|
||||
// necessary.
|
||||
int paramcount = mi->GetParamCount();
|
||||
|
||||
nsXPTCVariant *current = variantArray;
|
||||
if (paramcount > arraysize || *_retval == NULL) {
|
||||
*_retval = (nsXPTCVariant *)
|
||||
nsAllocator::Alloc(sizeof(nsXPTCVariant) * paramcount);
|
||||
}
|
||||
|
||||
// Set flags, pointers, and types for array elements
|
||||
nsXPTCVariant *current = *_retval;
|
||||
|
||||
for (int i = 0; i < paramcount; i++) {
|
||||
nsXPTParamInfo param = mi->GetParam(i);
|
||||
|
@ -292,140 +218,13 @@ void BuildParamsForMethodInfo(const nsXPTMethodInfo *mi,
|
|||
}
|
||||
current++;
|
||||
}
|
||||
return paramcount;
|
||||
}
|
||||
|
||||
int BuildParamsForOffset(const nsID *iid, jint offset,
|
||||
nsXPTCVariant **_retval) {
|
||||
const nsXPTMethodInfo *mi;
|
||||
|
||||
nsresult res = GetMethodInfo(iid, offset, &mi);
|
||||
if (NS_FAILED(res)) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
int paramcount = mi->GetParamCount();
|
||||
|
||||
// Build result based on number and types of parameters
|
||||
if (*_retval == NULL) {
|
||||
*_retval = new nsXPTCVariant[paramcount];
|
||||
}
|
||||
|
||||
BuildParamsForMethodInfo(mi, *_retval);
|
||||
return paramcount;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintParams(const nsXPTCVariant params[], int paramcount) {
|
||||
for (int i = 0; i < paramcount; i++) {
|
||||
|
||||
cerr << i << ") ";
|
||||
|
||||
switch(params[i].type) {
|
||||
case nsXPTType::T_I8:
|
||||
cerr << params[i].val.i8;
|
||||
break;
|
||||
case nsXPTType::T_I16:
|
||||
cerr << params[i].val.i16;
|
||||
break;
|
||||
case nsXPTType::T_I32:
|
||||
cerr << params[i].val.i32;
|
||||
break;
|
||||
case nsXPTType::T_I64:
|
||||
cerr << params[i].val.i64;
|
||||
break;
|
||||
case nsXPTType::T_U8:
|
||||
cerr << params[i].val.u8;
|
||||
break;
|
||||
case nsXPTType::T_U16:
|
||||
cerr << params[i].val.u16;
|
||||
break;
|
||||
case nsXPTType::T_U32:
|
||||
cerr << params[i].val.u32;
|
||||
break;
|
||||
case nsXPTType::T_U64:
|
||||
cerr << params[i].val.u64;
|
||||
break;
|
||||
case nsXPTType::T_FLOAT:
|
||||
cerr << params[i].val.f;
|
||||
break;
|
||||
case nsXPTType::T_DOUBLE:
|
||||
cerr << params[i].val.d;
|
||||
break;
|
||||
case nsXPTType::T_BOOL:
|
||||
cerr << (params[i].val.b ? "true" : "false");
|
||||
break;
|
||||
case nsXPTType::T_CHAR:
|
||||
cerr << "'" << params[i].val.c << "'";
|
||||
break;
|
||||
case nsXPTType::T_WCHAR:
|
||||
cerr << "'" << params[i].val.wc << "'";
|
||||
break;
|
||||
case nsXPTType::T_CHAR_STR:
|
||||
cerr << params[i].val.p << ' '
|
||||
<< '"' << (char *)params[i].val.p << '"';
|
||||
break;
|
||||
default:
|
||||
// Ignore for now
|
||||
break;
|
||||
}
|
||||
cerr << " : type " << (int)(params[i].type)
|
||||
<< ", ptr=" << params[i].ptr
|
||||
<< (params[i].IsPtrData() ? ", data" : "")
|
||||
<< (params[i].IsValOwned() ? ", owned" : "")
|
||||
<< (params[i].IsValInterface() ? ", interface" : "")
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult JArrayToVariant(JNIEnv *env,
|
||||
int paramcount,
|
||||
nsXPTCVariant *params,
|
||||
const jobjectArray jarray) {
|
||||
/*
|
||||
* Match the array elements to the expected parameters;
|
||||
*
|
||||
* Match:
|
||||
* T_BOOL : Boolean
|
||||
* T_I8: Byte
|
||||
* T_I16: Short
|
||||
* T_I32: Integer
|
||||
* T_I64: Long
|
||||
* -- we may want to support widening casts
|
||||
* T_U<n>: T_I<2n> type (T_U64 not supported)
|
||||
* -- we may allow T_I<n> if actual value in range
|
||||
* -- negative values are disallowed.
|
||||
* T_FLOAT: Float
|
||||
* T_DOUBLE: Double (or Float?)
|
||||
* T_CHAR: Character if value is an ASCII value
|
||||
* T_WCHAR: Character
|
||||
* T_CHAR_STRING: String as UTF-8 chars
|
||||
* T_WCHAR_STRING: String as Unicode chars
|
||||
* T_BSTR: String as UTF-8 chars
|
||||
* T_INTERFACE(_IS): XPCOM pointer for an ComObject, if nsID matches
|
||||
*/
|
||||
|
||||
nsXPTCVariant *current = params;
|
||||
|
||||
for (jsize i = 0; i < paramcount; i++, current++) {
|
||||
jobject elem = env->GetObjectArrayElement(jarray, i);
|
||||
|
||||
if (elem == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JObjectToVariant(env, current, elem) == JNI_FALSE) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Argument " << i << " is not of the correct type" << endl;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
jboolean JObjectToVariant(JNIEnv *env,
|
||||
nsXPTCVariant *current,
|
||||
const jobject elem) {
|
||||
static jboolean JObjectToVariant(JNIEnv *env,
|
||||
nsXPTCVariant *current,
|
||||
const jobject elem,
|
||||
REFNSIID iid) {
|
||||
jboolean result = JNI_FALSE;
|
||||
/*
|
||||
* Match:
|
||||
|
@ -548,7 +347,6 @@ jboolean JObjectToVariant(JNIEnv *env,
|
|||
tmpstr[jstrlen] = '\0';
|
||||
|
||||
current->val.p = tmpstr;
|
||||
current->flags |= nsXPTCVariant::VAL_IS_OWNED;
|
||||
|
||||
env->ReleaseStringChars(string, wstr);
|
||||
result = JNI_TRUE;
|
||||
|
@ -562,7 +360,13 @@ jboolean JObjectToVariant(JNIEnv *env,
|
|||
break;
|
||||
case nsXPTType::T_INTERFACE:
|
||||
case nsXPTType::T_INTERFACE_IS:
|
||||
// PENDING: unwrap the ComObject, or wrap Java object in stub
|
||||
if (elem == NULL) {
|
||||
current->val.p = NULL;
|
||||
}
|
||||
else {
|
||||
xpjp_QueryInterfaceToXPCOM(env, elem, iid, &(current->val.p));
|
||||
}
|
||||
current->flags |= nsXPTCVariant::VAL_IS_IFACE;
|
||||
break;
|
||||
case nsXPTType::T_BSTR:
|
||||
// Ignore for now
|
||||
|
@ -573,51 +377,31 @@ jboolean JObjectToVariant(JNIEnv *env,
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult VariantToJArray(JNIEnv *env,
|
||||
jobjectArray jarray,
|
||||
int paramcount,
|
||||
nsXPTCVariant *params) {
|
||||
static nsresult JArrayToVariant(JNIEnv *env,
|
||||
int paramcount,
|
||||
nsXPTCVariant *params,
|
||||
const jobjectArray jarray) {
|
||||
nsXPTCVariant *current = params;
|
||||
|
||||
for (jsize i = 0; i < paramcount; i++, current++) {
|
||||
jobject elem = NULL; // env->GetObjectArrayElement(jarray, i);
|
||||
jboolean isequal = JNI_FALSE;
|
||||
nsXPTCVariant currValue;
|
||||
jobject elem = env->GetObjectArrayElement(jarray, i);
|
||||
nsIID iid = NS_GET_IID(nsISupports);
|
||||
// PENDING: get the iid of the object
|
||||
|
||||
if (!(current->flags & nsXPTCVariant::PTR_IS_DATA)) {
|
||||
if (elem == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (elem != NULL) {
|
||||
memcpy(&currValue, current, sizeof(nsXPTCVariant));
|
||||
if (JObjectToVariant(env, &currValue, elem) != JNI_FALSE) {
|
||||
isequal =
|
||||
(memcmp(&currValue, current, sizeof(nsXPTCVariant)) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (isequal) {
|
||||
// PENDING: what about casting to more specific interfaces?
|
||||
continue;
|
||||
}
|
||||
|
||||
elem = VariantToJObject(env, current);
|
||||
|
||||
env->SetObjectArrayElement(jarray, i, elem);
|
||||
|
||||
if (current->flags & nsXPTCVariant::VAL_IS_IFACE) {
|
||||
((nsISupports*)current->val.p)->Release();
|
||||
}
|
||||
|
||||
if (current->flags & nsXPTCVariant::VAL_IS_OWNED) {
|
||||
delete [] current->val.p;
|
||||
current->val.p = 0; // for cleanliness sake
|
||||
if (JObjectToVariant(env, current, elem, iid) == JNI_FALSE) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Argument " << i << " is not of the correct type" << endl;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
extern jobject VariantToJObject(JNIEnv *env, const nsXPTCVariant *current) {
|
||||
|
||||
static jobject VariantToJObject(JNIEnv *env, const nsXPTCVariant *current) {
|
||||
jobject result = NULL;
|
||||
|
||||
// Integer code assumes that current->val.i# == current->val.u#
|
||||
|
@ -717,64 +501,61 @@ extern jobject VariantToJObject(JNIEnv *env, const nsXPTCVariant *current) {
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult InitXPCOM() {
|
||||
nsresult res;
|
||||
|
||||
#ifdef DEBUG_frankm
|
||||
cerr << "Initializing XPCOM" << endl;
|
||||
#endif
|
||||
static nsresult VariantToJArray(JNIEnv *env,
|
||||
jobjectArray jarray,
|
||||
int paramcount,
|
||||
nsXPTCVariant *params) {
|
||||
nsXPTCVariant *current = params;
|
||||
|
||||
// Autoregistration magic. Boogeda boogeda.
|
||||
for (jsize i = 0; i < paramcount; i++, current++) {
|
||||
jobject elem = NULL; // env->GetObjectArrayElement(jarray, i);
|
||||
jboolean isequal = JNI_FALSE;
|
||||
nsXPTCVariant currValue;
|
||||
|
||||
nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, nsnull);
|
||||
if (!(current->flags & nsXPTCVariant::PTR_IS_DATA)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// XXX Remove when allocator autoregisters
|
||||
cerr << "Registering Allocator" << endl;
|
||||
if (elem != NULL) {
|
||||
nsIID iid = NS_GET_IID(nsISupports);
|
||||
// PENDING: get the iid of the object
|
||||
|
||||
res = nsComponentManager::RegisterComponent(kAllocatorCID,
|
||||
"nsAllocator",
|
||||
"allocator",
|
||||
XPCOM_DLL,
|
||||
PR_TRUE,
|
||||
PR_TRUE);
|
||||
memcpy(&currValue, current, sizeof(nsXPTCVariant));
|
||||
if (JObjectToVariant(env, &currValue, elem, iid) != JNI_FALSE) {
|
||||
isequal =
|
||||
(memcmp(&currValue, current, sizeof(nsXPTCVariant)) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to register allocator, res = " << res << endl;
|
||||
return res;
|
||||
if (isequal) {
|
||||
// PENDING: what about casting to more specific interfaces?
|
||||
continue;
|
||||
}
|
||||
|
||||
elem = VariantToJObject(env, current);
|
||||
|
||||
env->SetObjectArrayElement(jarray, i, elem);
|
||||
|
||||
if (current->flags & nsXPTCVariant::VAL_IS_IFACE) {
|
||||
xpjp_SafeRelease((nsISupports*)current->val.p);
|
||||
}
|
||||
|
||||
if (current->flags & nsXPTCVariant::VAL_IS_OWNED) {
|
||||
delete [] current->val.p;
|
||||
current->val.p = 0; // for cleanliness sake
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get InterfaceInfoManager
|
||||
|
||||
#ifdef DEBUG_frankm
|
||||
cerr << "Getting InterfaceInfoManager" << endl;
|
||||
#endif
|
||||
|
||||
interfaceInfoManager = XPTI_GetInterfaceInfoManager();
|
||||
|
||||
if (!interfaceInfoManager) {
|
||||
cerr << "Failed to find InterfaceInfoManager" << endl;
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_frankm
|
||||
cerr << "XPCOM Initialized" << endl;
|
||||
#endif
|
||||
|
||||
return res;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
jboolean InitJavaCaches(JNIEnv *env) {
|
||||
/* ---------- DISPATCH API FUNCTIONS ------------ */
|
||||
|
||||
// PENDING: move to ComObject, for better locality?
|
||||
classComObject = env->FindClass(JAVA_XPCOBJECT_CLASS);
|
||||
if (classComObject == NULL) return JNI_FALSE;
|
||||
classComObject = (jclass)env->NewGlobalRef(classComObject);
|
||||
if (classComObject == NULL) return JNI_FALSE;
|
||||
jboolean xpjd_InitJavaCaches(JNIEnv *env) {
|
||||
|
||||
ComObject_objptr_ID = env->GetFieldID(classComObject, "objptr", "J");
|
||||
if (ComObject_objptr_ID == NULL) return JNI_FALSE;
|
||||
if (cache_initialized) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
// For basic types
|
||||
|
||||
|
@ -871,6 +652,159 @@ jboolean InitJavaCaches(JNIEnv *env) {
|
|||
Character_value_ID = env->GetFieldID(classCharacter, "value", "C");
|
||||
if (Character_value_ID == NULL) return JNI_FALSE;
|
||||
|
||||
return JNI_TRUE;
|
||||
// Get InterfaceInfoManager
|
||||
|
||||
#ifdef DEBUG_frankm
|
||||
cerr << "Getting InterfaceInfoManager" << endl;
|
||||
#endif
|
||||
|
||||
interfaceInfoManager = XPTI_GetInterfaceInfoManager();
|
||||
|
||||
if (!interfaceInfoManager) {
|
||||
// XXX: throw exception or something
|
||||
cerr << "Failed to find InterfaceInfoManager" << endl;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_frankm
|
||||
cerr << "InterfaceInfoManager found!" << endl;
|
||||
#endif
|
||||
|
||||
cache_initialized = JNI_TRUE;
|
||||
|
||||
return cache_initialized;
|
||||
}
|
||||
|
||||
void xpjd_FlushJavaCaches(JNIEnv *env) {
|
||||
|
||||
cache_initialized = JNI_FALSE;
|
||||
|
||||
// For basic types
|
||||
|
||||
env->DeleteGlobalRef(classString);
|
||||
classString = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classByte);
|
||||
classByte = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classShort);
|
||||
classShort = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classInteger);
|
||||
classInteger = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classLong);
|
||||
classLong = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classFloat);
|
||||
classFloat = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classDouble);
|
||||
classDouble = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classBoolean);
|
||||
classBoolean = NULL;
|
||||
|
||||
env->DeleteGlobalRef(classCharacter);
|
||||
classCharacter = NULL;
|
||||
|
||||
Byte_init_ID = NULL;
|
||||
Byte_value_ID = NULL;
|
||||
Short_init_ID = NULL;
|
||||
Short_value_ID = NULL;
|
||||
Integer_init_ID = NULL;
|
||||
Integer_value_ID = NULL;
|
||||
Long_init_ID = NULL;
|
||||
Long_value_ID = NULL;
|
||||
Float_init_ID = NULL;
|
||||
Float_value_ID = NULL;
|
||||
Double_init_ID = NULL;
|
||||
Double_value_ID = NULL;
|
||||
Boolean_init_ID = NULL;
|
||||
Boolean_value_ID = NULL;
|
||||
Character_init_ID = NULL;
|
||||
Character_value_ID = NULL;
|
||||
}
|
||||
|
||||
jboolean xpjd_GetInterfaceInfo(JNIEnv *env,
|
||||
jobject iid,
|
||||
nsIInterfaceInfo **info) {
|
||||
nsID *nativeIID = ID_GetNative(env, iid);
|
||||
|
||||
return xpjd_GetInterfaceInfoNative(*nativeIID, info);
|
||||
}
|
||||
|
||||
jboolean xpjd_GetInterfaceInfoNative(REFNSIID iid,
|
||||
nsIInterfaceInfo **info) {
|
||||
nsresult res;
|
||||
|
||||
// Get info
|
||||
*info = nsnull;
|
||||
|
||||
res = interfaceInfoManager->GetInfoForIID(&iid, info);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find info for " << iid.ToString() << endl;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
void xpjd_InvokeMethod(JNIEnv *env,
|
||||
nsISupports *target,
|
||||
nsIInterfaceInfo *info,
|
||||
jint methodIndex,
|
||||
jobjectArray jargs) {
|
||||
|
||||
nsresult res = NS_OK;
|
||||
nsXPTCVariant paramArray[32];
|
||||
nsXPTCVariant *params = paramArray;
|
||||
int nparams = 0;
|
||||
const int capacity = sizeof(paramArray)/sizeof(paramArray[0]);
|
||||
|
||||
// XXX: check info != NULL, target != null, jargs != null, env != null
|
||||
|
||||
// XXX: check bounds of methodIndex
|
||||
|
||||
nparams = xpjd_BuildParamsForOffset(info,
|
||||
methodIndex,
|
||||
capacity,
|
||||
¶ms);
|
||||
if (nparams < 0) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Couldn't initialize parameter array" << endl;
|
||||
goto finally;
|
||||
}
|
||||
|
||||
res = JArrayToVariant(env, nparams, params, jargs);
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Array and parameter list mismatch" << endl;
|
||||
goto finally;
|
||||
}
|
||||
|
||||
//xpjp_SafeAddRef(target);
|
||||
|
||||
res = XPTC_InvokeByIndex(target, methodIndex, nparams, params);
|
||||
|
||||
//xpjp_SafeRelease(target);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Invocation failed, status: " << res << endl;
|
||||
goto finally;
|
||||
}
|
||||
|
||||
res = VariantToJArray(env, jargs, nparams, params);
|
||||
if (NS_FAILED(res)) {
|
||||
// PENDING: throw an exception
|
||||
cerr << "Array and parameter list mismatch" << endl;
|
||||
goto finally;
|
||||
}
|
||||
|
||||
finally:
|
||||
if (params != paramArray) {
|
||||
nsAllocator::Free(params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -11,72 +11,7 @@
|
|||
* Contributors:
|
||||
* Frank Mitchell (frank.mitchell@sun.com)
|
||||
*/
|
||||
#include <jni.h>
|
||||
#include "nsISupports.h"
|
||||
#include "xptcall.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern nsresult InitXPCOM();
|
||||
|
||||
extern jboolean InitJavaCaches(JNIEnv *env);
|
||||
|
||||
extern nsISupports *This(JNIEnv *env, jobject self);
|
||||
|
||||
extern nsID *This_IID(JNIEnv *env, jobject self);
|
||||
|
||||
extern jobject NewComObject(JNIEnv *env,
|
||||
nsISupports *xpcobj, const nsIID *iid);
|
||||
|
||||
extern int BuildParamsForOffset(const nsID *iid, jint offset,
|
||||
nsXPTCVariant **_retval);
|
||||
|
||||
extern void BuildParamsForMethodInfo(const nsXPTMethodInfo *mi,
|
||||
nsXPTCVariant variantArray[]);
|
||||
|
||||
extern nsresult GetMethodInfo(const nsID *iid, jint offset,
|
||||
const nsXPTMethodInfo **_retval);
|
||||
|
||||
extern nsresult GetMethodInfoByName(const nsID *iid,
|
||||
const char *methodname,
|
||||
PRBool wantSetter,
|
||||
const nsXPTMethodInfo **miptr,
|
||||
int *_retval);
|
||||
|
||||
extern void PrintParams(const nsXPTCVariant params[], int paramcount);
|
||||
|
||||
extern nsresult JArrayToVariant(JNIEnv *env,
|
||||
int paramcount,
|
||||
nsXPTCVariant *params,
|
||||
const jobjectArray jarray);
|
||||
|
||||
extern jboolean JObjectToVariant(JNIEnv *env,
|
||||
nsXPTCVariant *param,
|
||||
const jobject obj);
|
||||
|
||||
extern nsresult VariantToJArray(JNIEnv *env,
|
||||
jobjectArray jarray,
|
||||
int paramcount,
|
||||
nsXPTCVariant *params);
|
||||
|
||||
extern jobject VariantToJObject(JNIEnv *env,
|
||||
const nsXPTCVariant *param);
|
||||
|
||||
|
||||
/* Defined in nsID.cpp */
|
||||
extern jobject ID_NewJavaID(JNIEnv *env, const nsID* id);
|
||||
extern nsID* ID_GetNative(JNIEnv *env, jobject self);
|
||||
extern void ID_SetNative(JNIEnv *env, jobject self, nsID* id);
|
||||
extern jboolean ID_IsEqual(JNIEnv *env, jobject self, jobject other);
|
||||
|
||||
#ifndef jlong_L2I
|
||||
# define jlong_L2I(_i, _l) ((_i) = (_l))
|
||||
# define jlong_I2L(_l, _i) ((_l) = (_i))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "xpj_dispatch.h"
|
||||
#include "xpj_proxy.h"
|
||||
#include "xpj_utils.h"
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
# Makefile
|
||||
|
||||
MOZILLA=../../..
|
||||
|
||||
CC=gcc
|
||||
CPP=g++
|
||||
|
||||
CFLAGS=-Wall -g -fno-rtti -fno-handle-exceptions -pipe
|
||||
SHLIB_FLAGS=-fpic
|
||||
SHLIB_LDFLAGS=-shared
|
||||
DEFINES=-DXP_UNIX
|
||||
INCLUDE=-I$(MOZILLA)/dist/include -I$(MOZILLA)/xpcom/public -I../src -I$(JDKHOME)/include -I$(JDKHOME)/include/solaris -I$(JDKHOME)/include/linux
|
||||
LIBS=-L$(MOZILLA)/dist/lib -lxptinfo -lxptcmd -lxptcall -lxpt -lxpcom -lplds3 -lplc3 -lnspr3
|
||||
|
||||
COMPDIR=$(MOZILLA)/dist/bin/components
|
||||
|
||||
XPIDL=$(MOZILLA)/dist/bin/xpidl
|
||||
|
||||
GENPROXY=$(MOZILLA)/dist/bin/genproxy
|
||||
|
||||
JAVAC=$(JDKHOME)/bin/javac
|
||||
|
||||
CLASSDIR=$(MOZILLA)/dist/classes
|
||||
|
||||
|
||||
TEST_CLASSES=XPCTest.class
|
||||
|
||||
PROXY_JAR=sample.jar
|
||||
PROXY_DIR=_genproxy
|
||||
|
||||
|
||||
.SUFFIXES: .java .class .cpp .o
|
||||
|
||||
all: sample xptest $(TEST_CLASSES) $(PROXY_JAR)
|
||||
|
||||
#
|
||||
# Build class files.
|
||||
#
|
||||
.java.class:
|
||||
$(JAVAC) -g -d . -classpath $(CLASSDIR):. $<
|
||||
|
||||
|
||||
#
|
||||
# Compile C++.
|
||||
#
|
||||
.cpp.o:
|
||||
$(CPP) $(CFLAGS) $(DEFINES) $(INCLUDE) $(SHLIB_FLAGS) -c $<
|
||||
|
||||
#
|
||||
# Sample XPCOM module.
|
||||
#
|
||||
sample: JSISample.h $(COMPDIR)/libxpjtest.so $(COMPDIR)/xpjtest.xpt
|
||||
|
||||
#
|
||||
# Build sample header & typelib
|
||||
#
|
||||
JSISample.cpp: JSISample.h
|
||||
|
||||
JSISample.h: JSISample.idl
|
||||
$(XPIDL) -w -v -m header -I $(MOZILLA)/dist/idl JSISample.idl
|
||||
|
||||
$(COMPDIR)/xpjtest.xpt: JSISample.idl
|
||||
$(XPIDL) -w -v -m typelib -o $(COMPDIR)/xpjtest -I $(MOZILLA)/dist/idl JSISample.idl
|
||||
|
||||
#
|
||||
# Sample object shared library
|
||||
#
|
||||
libxpjtest.so: JSISample.h JSSample.o
|
||||
$(CPP) $(SHLIB_LDFLAGS) -L$(MOZILLA)/dist/lib -lxpcom -o libxpjtest.so JSSample.o
|
||||
chmod +x libxpjtest.so
|
||||
|
||||
$(COMPDIR)/libxpjtest.so: libxpjtest.so
|
||||
../../../config/nsinstall -R -m 555 libxpjtest.so $(COMPDIR)
|
||||
|
||||
#
|
||||
# C++ test program
|
||||
#
|
||||
xptest: xptest.o ../src/libxpjava.so
|
||||
$(CPP) -g -Wall -o xptest $(LIBS) -L ../src -lxpjava xptest.o
|
||||
|
||||
xptest.cpp: ../src/xpjava.h
|
||||
|
||||
$(PROXY_JAR): $(GENPROXY) $(COMPDIR)/xpjtest.xpt
|
||||
- mkdir $(PROXY_DIR)
|
||||
$(GENPROXY) -d $(PROXY_DIR) $(COMPDIR)/xpjtest.xpt
|
||||
$(GENPROXY) -i -d $(PROXY_DIR) $(COMPDIR)/xpjtest.xpt
|
||||
$(JAVAC) -g -d $(PROXY_DIR) -classpath $(CLASSDIR):. $(PROXY_DIR)/*.java
|
||||
(cd $(PROXY_DIR); jar cf ../$(PROXY_JAR) org)
|
||||
|
||||
clean:
|
||||
$(RM) -r *.o *.so core xptest $(COMPDIR)/libxpjtest.so $(COMPDIR)/xpjtest.xpt JSISample.h $(TEST_CLASSES) $(PROXY_JAR) $(PROXY_DIR)
|
|
@ -29,31 +29,24 @@
|
|||
|
||||
#include "nsSpecialSystemDirectory.h"
|
||||
|
||||
#include "xpjava.h"
|
||||
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kISampleIID, JSISAMPLE_IID);
|
||||
static NS_DEFINE_CID(kSampleCID, JS_SAMPLE_CID);
|
||||
|
||||
static NS_DEFINE_IID(kAllocatorCID, NS_ALLOCATOR_CID);
|
||||
|
||||
#ifdef XP_PC
|
||||
#define XPCOM_DLL "xpcom.dll"
|
||||
#define SAMPLE_DLL "xpjtest.dll"
|
||||
#else
|
||||
#ifdef XP_MAC
|
||||
#define XPCOM_DLL "XPCOM_DLL"
|
||||
#define SAMPLE_DLL "XPJTEST_DLL"
|
||||
#else
|
||||
#define XPCOM_DLL "libxpcom.so"
|
||||
#define SAMPLE_DLL "libxpjtest.so"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void ParamsFromArgv(nsXPTCVariant *result,
|
||||
const nsXPTMethodInfo *mi,
|
||||
int argi, int argc, char **argv) {
|
||||
static void ParamsFromArgv(nsXPTCVariant *result,
|
||||
const nsXPTMethodInfo *mi,
|
||||
int argi, int argc, char **argv) {
|
||||
uint8 paramcount = mi->GetParamCount();
|
||||
|
||||
memset(result, 0, sizeof(nsXPTCVariant) * paramcount);
|
||||
|
@ -194,7 +187,126 @@ void ParamsFromArgv(nsXPTCVariant *result,
|
|||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void xpjd_PrintParams(const nsXPTCVariant params[], int paramcount) {
|
||||
for (int i = 0; i < paramcount; i++) {
|
||||
|
||||
cerr << i << ") ";
|
||||
|
||||
switch(params[i].type) {
|
||||
case nsXPTType::T_I8:
|
||||
cerr << params[i].val.i8;
|
||||
break;
|
||||
case nsXPTType::T_I16:
|
||||
cerr << params[i].val.i16;
|
||||
break;
|
||||
case nsXPTType::T_I32:
|
||||
cerr << params[i].val.i32;
|
||||
break;
|
||||
case nsXPTType::T_I64:
|
||||
cerr << params[i].val.i64;
|
||||
break;
|
||||
case nsXPTType::T_U8:
|
||||
cerr << params[i].val.u8;
|
||||
break;
|
||||
case nsXPTType::T_U16:
|
||||
cerr << params[i].val.u16;
|
||||
break;
|
||||
case nsXPTType::T_U32:
|
||||
cerr << params[i].val.u32;
|
||||
break;
|
||||
case nsXPTType::T_U64:
|
||||
cerr << params[i].val.u64;
|
||||
break;
|
||||
case nsXPTType::T_FLOAT:
|
||||
cerr << params[i].val.f;
|
||||
break;
|
||||
case nsXPTType::T_DOUBLE:
|
||||
cerr << params[i].val.d;
|
||||
break;
|
||||
case nsXPTType::T_BOOL:
|
||||
cerr << (params[i].val.b ? "true" : "false");
|
||||
break;
|
||||
case nsXPTType::T_CHAR:
|
||||
cerr << "'" << params[i].val.c << "'";
|
||||
break;
|
||||
case nsXPTType::T_WCHAR:
|
||||
cerr << "'" << params[i].val.wc << "'";
|
||||
break;
|
||||
case nsXPTType::T_CHAR_STR:
|
||||
cerr << params[i].val.p << ' '
|
||||
<< '"' << (char *)params[i].val.p << '"';
|
||||
break;
|
||||
default:
|
||||
// Ignore for now
|
||||
break;
|
||||
}
|
||||
cerr << " : type " << (int)(params[i].type)
|
||||
<< ", ptr=" << params[i].ptr
|
||||
<< (params[i].IsPtrData() ? ", data" : "")
|
||||
<< (params[i].IsValOwned() ? ", owned" : "")
|
||||
<< (params[i].IsValInterface() ? ", interface" : "")
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static nsresult GetMethodInfoByName(const nsID *iid,
|
||||
const char *methodname,
|
||||
PRBool wantSetter,
|
||||
const nsXPTMethodInfo **miptr,
|
||||
int *_retval) {
|
||||
nsresult res;
|
||||
nsIInterfaceInfoManager *iim;
|
||||
nsIInterfaceInfo *info = nsnull;
|
||||
|
||||
// Get info
|
||||
iim = XPTI_GetInterfaceInfoManager();
|
||||
|
||||
if (!iim) {
|
||||
cerr << "Failed to find InterfaceInfoManager" << endl;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
res = iim->GetInfoForIID(iid, &info);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
cerr << "Failed to find info for " << iid->ToString() << endl;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Find info for command
|
||||
uint16 methodcount;
|
||||
|
||||
info->GetMethodCount(&methodcount);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < methodcount; i++) {
|
||||
const nsXPTMethodInfo *mi;
|
||||
|
||||
info->GetMethodInfo(i, &mi);
|
||||
// PENDING(frankm): match against name, get/set, *AND* param types
|
||||
if (strcmp(methodname, mi->GetName()) == 0) {
|
||||
PRBool setter = mi->IsSetter();
|
||||
PRBool getter = mi->IsGetter();
|
||||
if ((!getter && !setter)
|
||||
|| (setter && wantSetter)
|
||||
|| (getter && !wantSetter)) {
|
||||
*miptr = mi;
|
||||
*_retval = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i >= methodcount) {
|
||||
cerr << "Failed to find " << methodname << endl;
|
||||
*miptr = NULL;
|
||||
*_retval = -1;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -217,7 +329,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
// Initialize XPCOM
|
||||
InitXPCOM();
|
||||
nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, nsnull);
|
||||
|
||||
// Create Instance
|
||||
res = nsComponentManager::CreateInstance(kSampleCID,
|
||||
|
@ -275,7 +387,7 @@ int main(int argc, char **argv)
|
|||
|
||||
cerr << "Arguments are: " << endl;
|
||||
|
||||
PrintParams(params, paramcount);
|
||||
xpjd_PrintParams(params, paramcount);
|
||||
|
||||
// Invoke command
|
||||
|
||||
|
@ -294,9 +406,7 @@ int main(int argc, char **argv)
|
|||
|
||||
cerr << "Results are: " << endl;
|
||||
|
||||
PrintParams(params, paramcount);
|
||||
|
||||
delete [] params;
|
||||
xpjd_PrintParams(params, paramcount);
|
||||
|
||||
// Release Instance
|
||||
NS_RELEASE(sample);
|
||||
|
|
Загрузка…
Ссылка в новой задаче