gecko/extensions/java/xpcom/glue/nsJavaXPCOMGlue.cpp

399 lines
15 KiB
C++

/* ***** 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) 2006
* 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 "jni.h"
#include "nsXPCOMPrivate.h" // for XPCOM_DLL defines.
#include "nsXPCOMGlue.h"
#include "nsDebug.h"
#include <stdlib.h>
#if defined(XP_WIN) || defined(XP_OS2)
#define JX_EXPORT JNIEXPORT
#else
#define JX_EXPORT JNIEXPORT NS_EXPORT
#endif
/***********************
* JNI Load & Unload
***********************/
extern "C" JX_EXPORT jint JNICALL
JNI_OnLoad(JavaVM* vm, void* reserved)
{
// Let the JVM know that we are using JDK 1.2 JNI features.
return JNI_VERSION_1_2;
}
extern "C" JX_EXPORT void JNICALL
JNI_OnUnload(JavaVM* vm, void* reserved)
{
}
/********************************
* JavaXPCOM JNI interfaces
********************************/
#define JXM_NATIVE(func) Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_##func
enum {
kFunc_Initialize,
kFunc_InitEmbedding,
kFunc_TermEmbedding,
kFunc_LockProfileDirectory,
kFunc_NotifyProfile,
kFunc_InitXPCOM,
kFunc_ShutdownXPCOM,
kFunc_GetComponentManager,
kFunc_GetComponentRegistrar,
kFunc_GetServiceManager,
kFunc_NewLocalFile,
kFunc_CallXPCOMMethod,
kFunc_FinalizeProxy,
kFunc_IsSameXPCOMObject,
kFunc_ReleaseProfileLock,
kFunc_GetNativeHandleFromAWT,
kFunc_WrapJavaObject,
kFunc_WrapXPCOMObject
};
#define JX_NUM_FUNCS 18
// Get path string from java.io.File object.
jstring
GetJavaFilePath(JNIEnv* env, jobject aFile)
{
jclass clazz = env->FindClass("java/io/File");
if (clazz) {
jmethodID pathMID = env->GetMethodID(clazz, "getCanonicalPath",
"()Ljava/lang/String;");
if (pathMID) {
return (jstring) env->CallObjectMethod(aFile, pathMID);
}
}
return nsnull;
}
// Calls XPCOMGlueStartup using the given java.io.File object, and loads
// the JavaXPCOM methods from the XUL shared library.
nsresult
LoadXULMethods(JNIEnv* env, jobject aXPCOMPath, void** aFunctions)
{
jstring pathString = GetJavaFilePath(env, aXPCOMPath);
if (!pathString)
return NS_ERROR_FAILURE;
const char* path = env->GetStringUTFChars(pathString, nsnull);
if (!path)
return NS_ERROR_OUT_OF_MEMORY;
int len = strlen(path);
char* xpcomPath = (char*) malloc(len + sizeof(XPCOM_DLL) +
sizeof(XPCOM_FILE_PATH_SEPARATOR) + 1);
if (!xpcomPath)
return NS_ERROR_OUT_OF_MEMORY;
sprintf(xpcomPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, path);
nsresult rv = XPCOMGlueStartup(xpcomPath);
free(xpcomPath);
if (NS_FAILED(rv))
return rv;
#ifdef XP_WIN32
// The JNICALL calling convention defines to "__stdcall" on Win32, which
// mangles the name.
nsDynamicFunctionLoad funcs[] = {
{ "_Java_org_mozilla_xpcom_internal_MozillaImpl_initialize@8",
(NSFuncPtr*) &aFunctions[kFunc_Initialize] },
{ "_Java_org_mozilla_xpcom_internal_GREImpl_initEmbedding@20",
(NSFuncPtr*) &aFunctions[kFunc_InitEmbedding] },
{ "_Java_org_mozilla_xpcom_internal_GREImpl_termEmbedding@8",
(NSFuncPtr*) &aFunctions[kFunc_TermEmbedding] },
{ "_Java_org_mozilla_xpcom_internal_GREImpl_lockProfileDirectory@12",
(NSFuncPtr*) &aFunctions[kFunc_LockProfileDirectory] },
{ "_Java_org_mozilla_xpcom_internal_GREImpl_notifyProfile@8",
(NSFuncPtr*) &aFunctions[kFunc_NotifyProfile] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMImpl_initXPCOM@16",
(NSFuncPtr*) &aFunctions[kFunc_InitXPCOM] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMImpl_shutdownXPCOM@12",
(NSFuncPtr*) &aFunctions[kFunc_ShutdownXPCOM] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentManager@8",
(NSFuncPtr*) &aFunctions[kFunc_GetComponentManager] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentRegistrar@8",
(NSFuncPtr*) &aFunctions[kFunc_GetComponentRegistrar] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getServiceManager@8",
(NSFuncPtr*) &aFunctions[kFunc_GetServiceManager] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMImpl_newLocalFile@16",
(NSFuncPtr*) &aFunctions[kFunc_NewLocalFile] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_callXPCOMMethod@20",
(NSFuncPtr*) &aFunctions[kFunc_CallXPCOMMethod] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_finalizeProxy@12",
(NSFuncPtr*) &aFunctions[kFunc_FinalizeProxy] },
{ "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_isSameXPCOMObject@16",
(NSFuncPtr*) &aFunctions[kFunc_IsSameXPCOMObject] },
{ "_Java_org_mozilla_xpcom_ProfileLock_release@16",
(NSFuncPtr*) &aFunctions[kFunc_ReleaseProfileLock] },
{ "_Java_org_mozilla_xpcom_internal_MozillaImpl_getNativeHandleFromAWT@12",
(NSFuncPtr*) &aFunctions[kFunc_GetNativeHandleFromAWT] },
{ "_Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapJavaObject@16",
(NSFuncPtr*) &aFunctions[kFunc_WrapJavaObject] },
{ "_Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapXPCOMObject@20",
(NSFuncPtr*) &aFunctions[kFunc_WrapXPCOMObject] },
{ nsnull, nsnull }
};
#else
nsDynamicFunctionLoad funcs[] = {
{ "Java_org_mozilla_xpcom_internal_MozillaImpl_initialize",
(NSFuncPtr*) &aFunctions[kFunc_Initialize] },
{ "Java_org_mozilla_xpcom_internal_GREImpl_initEmbedding",
(NSFuncPtr*) &aFunctions[kFunc_InitEmbedding] },
{ "Java_org_mozilla_xpcom_internal_GREImpl_termEmbedding",
(NSFuncPtr*) &aFunctions[kFunc_TermEmbedding] },
{ "Java_org_mozilla_xpcom_internal_GREImpl_lockProfileDirectory",
(NSFuncPtr*) &aFunctions[kFunc_LockProfileDirectory] },
{ "Java_org_mozilla_xpcom_internal_GREImpl_notifyProfile",
(NSFuncPtr*) &aFunctions[kFunc_NotifyProfile] },
{ "Java_org_mozilla_xpcom_internal_XPCOMImpl_initXPCOM",
(NSFuncPtr*) &aFunctions[kFunc_InitXPCOM] },
{ "Java_org_mozilla_xpcom_internal_XPCOMImpl_shutdownXPCOM",
(NSFuncPtr*) &aFunctions[kFunc_ShutdownXPCOM] },
{ "Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentManager",
(NSFuncPtr*) &aFunctions[kFunc_GetComponentManager] },
{ "Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentRegistrar",
(NSFuncPtr*) &aFunctions[kFunc_GetComponentRegistrar] },
{ "Java_org_mozilla_xpcom_internal_XPCOMImpl_getServiceManager",
(NSFuncPtr*) &aFunctions[kFunc_GetServiceManager] },
{ "Java_org_mozilla_xpcom_internal_XPCOMImpl_newLocalFile",
(NSFuncPtr*) &aFunctions[kFunc_NewLocalFile] },
{ "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_callXPCOMMethod",
(NSFuncPtr*) &aFunctions[kFunc_CallXPCOMMethod] },
{ "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_finalizeProxy",
(NSFuncPtr*) &aFunctions[kFunc_FinalizeProxy] },
{ "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_isSameXPCOMObject",
(NSFuncPtr*) &aFunctions[kFunc_IsSameXPCOMObject] },
{ "Java_org_mozilla_xpcom_ProfileLock_release",
(NSFuncPtr*) &aFunctions[kFunc_ReleaseProfileLock] },
{ "Java_org_mozilla_xpcom_internal_MozillaImpl_getNativeHandleFromAWT",
(NSFuncPtr*) &aFunctions[kFunc_GetNativeHandleFromAWT] },
{ "Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapJavaObject",
(NSFuncPtr*) &aFunctions[kFunc_WrapJavaObject] },
{ "Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapXPCOMObject",
(NSFuncPtr*) &aFunctions[kFunc_WrapXPCOMObject] },
{ nsnull, nsnull }
};
#endif
rv = XPCOMGlueLoadXULFunctions(funcs);
if (NS_FAILED(rv))
return rv;
return NS_OK;
}
void
ThrowException(JNIEnv* env, const nsresult aErrorCode, const char* aMessage)
{
// Only throw this exception if one hasn't already been thrown, so we don't
// mask a previous exception/error.
if (env->ExceptionCheck())
return;
// If the error code we get is for an Out Of Memory error, try to throw an
// OutOfMemoryError. The JVM may have enough memory to create this error.
if (aErrorCode == NS_ERROR_OUT_OF_MEMORY) {
jclass clazz = env->FindClass("java/lang/OutOfMemoryError");
if (clazz) {
env->ThrowNew(clazz, aMessage);
}
env->DeleteLocalRef(clazz);
return;
}
// If the error was not handled above, then create an XPCOMException with the
// given error code.
jthrowable throwObj = nsnull;
jclass exceptionClass = env->FindClass("org/mozilla/xpcom/XPCOMException");
if (exceptionClass) {
jmethodID mid = env->GetMethodID(exceptionClass, "<init>",
"(JLjava/lang/String;)V");
if (mid) {
throwObj = (jthrowable) env->NewObject(exceptionClass, mid,
(PRInt64) aErrorCode,
env->NewStringUTF(aMessage));
}
}
NS_ASSERTION(throwObj, "Failed to create XPCOMException object");
// throw exception
if (throwObj) {
env->Throw(throwObj);
}
}
// Register the JavaXPCOM native methods. This associates a native Java
// method with its C implementation.
nsresult
RegisterNativeMethods(JNIEnv* env, void** aFunctions)
{
JNINativeMethod mozilla_methods[] = {
{ "initializeNative", "()V",
(void*) aFunctions[kFunc_Initialize] },
{ "getNativeHandleFromAWT", "(Ljava/lang/Object;)J",
(void*) aFunctions[kFunc_GetNativeHandleFromAWT] }
};
JNINativeMethod gre_methods[] = {
{ "initEmbeddingNative",
"(Ljava/io/File;Ljava/io/File;Lorg/mozilla/xpcom/IAppFileLocProvider;)V",
(void*) aFunctions[kFunc_InitEmbedding] },
{ "termEmbedding", "()V",
(void*) aFunctions[kFunc_TermEmbedding] },
{ "lockProfileDirectory", "(Ljava/io/File;)Lorg/mozilla/xpcom/ProfileLock;",
(void*) aFunctions[kFunc_LockProfileDirectory] },
{ "notifyProfile", "()V",
(void*) aFunctions[kFunc_NotifyProfile] },
};
JNINativeMethod xpcom_methods[] = {
{ "initXPCOMNative",
"(Ljava/io/File;Lorg/mozilla/xpcom/IAppFileLocProvider;)Lorg/mozilla/interfaces/nsIServiceManager;",
(void*) aFunctions[kFunc_InitXPCOM] },
{ "shutdownXPCOM", "(Lorg/mozilla/interfaces/nsIServiceManager;)V",
(void*) aFunctions[kFunc_ShutdownXPCOM] },
{ "getComponentManager", "()Lorg/mozilla/interfaces/nsIComponentManager;",
(void*) aFunctions[kFunc_GetComponentManager] },
{ "getComponentRegistrar", "()Lorg/mozilla/interfaces/nsIComponentRegistrar;",
(void*) aFunctions[kFunc_GetComponentRegistrar] },
{ "getServiceManager", "()Lorg/mozilla/interfaces/nsIServiceManager;",
(void*) aFunctions[kFunc_GetServiceManager] },
{ "newLocalFile", "(Ljava/lang/String;Z)Lorg/mozilla/interfaces/nsILocalFile;",
(void*) aFunctions[kFunc_NewLocalFile] }
};
JNINativeMethod proxy_methods[] = {
{ "callXPCOMMethod",
"(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;",
(void*) aFunctions[kFunc_CallXPCOMMethod] },
{ "finalizeProxyNative", "(Ljava/lang/Object;)V",
(void*) aFunctions[kFunc_FinalizeProxy] },
{ "isSameXPCOMObject", "(Ljava/lang/Object;Ljava/lang/Object;)Z",
(void*) aFunctions[kFunc_IsSameXPCOMObject] }
};
JNINativeMethod lockProxy_methods[] = {
{ "releaseNative", "(J)V",
(void*) aFunctions[kFunc_ReleaseProfileLock] }
};
JNINativeMethod util_methods[] = {
{ "wrapJavaObject", "(Ljava/lang/Object;Ljava/lang/String;)J",
(void*) aFunctions[kFunc_WrapJavaObject] },
{ "wrapXPCOMObject", "(JLjava/lang/String;)Ljava/lang/Object;",
(void*) aFunctions[kFunc_WrapXPCOMObject] }
};
jint rc = -1;
jclass clazz = env->FindClass("org/mozilla/xpcom/internal/MozillaImpl");
if (clazz) {
rc = env->RegisterNatives(clazz, mozilla_methods,
sizeof(mozilla_methods) / sizeof(mozilla_methods[0]));
}
NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
rc = -1;
clazz = env->FindClass("org/mozilla/xpcom/internal/GREImpl");
if (clazz) {
rc = env->RegisterNatives(clazz, gre_methods,
sizeof(gre_methods) / sizeof(gre_methods[0]));
}
NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
rc = -1;
clazz = env->FindClass("org/mozilla/xpcom/internal/XPCOMImpl");
if (clazz) {
rc = env->RegisterNatives(clazz, xpcom_methods,
sizeof(xpcom_methods) / sizeof(xpcom_methods[0]));
}
NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
rc = -1;
clazz = env->FindClass("org/mozilla/xpcom/internal/XPCOMJavaProxy");
if (clazz) {
rc = env->RegisterNatives(clazz, proxy_methods,
sizeof(proxy_methods) / sizeof(proxy_methods[0]));
}
NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
rc = -1;
clazz = env->FindClass("org/mozilla/xpcom/ProfileLock");
if (clazz) {
rc = env->RegisterNatives(clazz, lockProxy_methods,
sizeof(lockProxy_methods) / sizeof(lockProxy_methods[0]));
}
NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
rc = -1;
clazz = env->FindClass("org/mozilla/xpcom/internal/JavaXPCOMMethods");
if (clazz) {
rc = env->RegisterNatives(clazz, util_methods,
sizeof(util_methods) / sizeof(util_methods[0]));
}
NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
return NS_OK;
}
// Load the JavaXPCOM methods from the XUL shared library, and registers them
// as Java native methods.
extern "C" JX_EXPORT void JNICALL
JXM_NATIVE(registerJavaXPCOMMethodsNative) (JNIEnv *env, jclass that,
jobject aXPCOMPath)
{
void* functions[JX_NUM_FUNCS];
memset(functions, 0, JX_NUM_FUNCS * sizeof(void*));
nsresult rv = LoadXULMethods(env, aXPCOMPath, functions);
if (NS_SUCCEEDED(rv)) {
rv = RegisterNativeMethods(env, functions);
}
if (NS_FAILED(rv)) {
ThrowException(env, rv, "Failed to register JavaXPCOM methods");
}
}