Bug 452317 - FeedConverter.js: QueryInterface should throw NS_ERROR_NO_INTERFACE...
[wine-gecko.git] / extensions / java / xpcom / glue / nsJavaXPCOMGlue.cpp
blob113375bed8a878ac6e2f98949d3d972c18c95eab
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is Java XPCOM Bindings.
16 * The Initial Developer of the Original Code is IBM Corporation.
17 * Portions created by the Initial Developer are Copyright (C) 2006
18 * IBM Corporation. All Rights Reserved.
20 * Contributor(s):
21 * Javier Pedemonte (jhpedemonte@gmail.com)
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include "jni.h"
38 #include "nsXPCOMPrivate.h" // for XPCOM_DLL defines.
39 #include "nsXPCOMGlue.h"
40 #include "nsDebug.h"
41 #include <stdlib.h>
43 #if defined(XP_WIN) || defined(XP_OS2)
44 #define JX_EXPORT JNIEXPORT
45 #else
46 #define JX_EXPORT JNIEXPORT NS_EXPORT
47 #endif
50 /***********************
51 * JNI Load & Unload
52 ***********************/
54 extern "C" JX_EXPORT jint JNICALL
55 JNI_OnLoad(JavaVM* vm, void* reserved)
57 // Let the JVM know that we are using JDK 1.2 JNI features.
58 return JNI_VERSION_1_2;
61 extern "C" JX_EXPORT void JNICALL
62 JNI_OnUnload(JavaVM* vm, void* reserved)
66 /********************************
67 * JavaXPCOM JNI interfaces
68 ********************************/
70 #define JXM_NATIVE(func) Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_##func
72 enum {
73 kFunc_Initialize,
74 kFunc_InitEmbedding,
75 kFunc_TermEmbedding,
76 kFunc_LockProfileDirectory,
77 kFunc_NotifyProfile,
78 kFunc_InitXPCOM,
79 kFunc_ShutdownXPCOM,
80 kFunc_GetComponentManager,
81 kFunc_GetComponentRegistrar,
82 kFunc_GetServiceManager,
83 kFunc_NewLocalFile,
84 kFunc_CallXPCOMMethod,
85 kFunc_FinalizeProxy,
86 kFunc_IsSameXPCOMObject,
87 kFunc_ReleaseProfileLock,
88 kFunc_GetNativeHandleFromAWT,
89 kFunc_WrapJavaObject,
90 kFunc_WrapXPCOMObject
93 #define JX_NUM_FUNCS 18
96 // Get path string from java.io.File object.
97 jstring
98 GetJavaFilePath(JNIEnv* env, jobject aFile)
100 jclass clazz = env->FindClass("java/io/File");
101 if (clazz) {
102 jmethodID pathMID = env->GetMethodID(clazz, "getCanonicalPath",
103 "()Ljava/lang/String;");
104 if (pathMID) {
105 return (jstring) env->CallObjectMethod(aFile, pathMID);
109 return nsnull;
112 // Calls XPCOMGlueStartup using the given java.io.File object, and loads
113 // the JavaXPCOM methods from the XUL shared library.
114 nsresult
115 LoadXULMethods(JNIEnv* env, jobject aXPCOMPath, void** aFunctions)
117 jstring pathString = GetJavaFilePath(env, aXPCOMPath);
118 if (!pathString)
119 return NS_ERROR_FAILURE;
120 const char* path = env->GetStringUTFChars(pathString, nsnull);
121 if (!path)
122 return NS_ERROR_OUT_OF_MEMORY;
124 int len = strlen(path);
125 char* xpcomPath = (char*) malloc(len + sizeof(XPCOM_DLL) +
126 sizeof(XPCOM_FILE_PATH_SEPARATOR) + 1);
127 if (!xpcomPath)
128 return NS_ERROR_OUT_OF_MEMORY;
129 sprintf(xpcomPath, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DLL, path);
131 nsresult rv = XPCOMGlueStartup(xpcomPath);
132 free(xpcomPath);
133 if (NS_FAILED(rv))
134 return rv;
136 #ifdef XP_WIN32
137 // The JNICALL calling convention defines to "__stdcall" on Win32, which
138 // mangles the name.
139 nsDynamicFunctionLoad funcs[] = {
140 { "_Java_org_mozilla_xpcom_internal_MozillaImpl_initialize@8",
141 (NSFuncPtr*) &aFunctions[kFunc_Initialize] },
142 { "_Java_org_mozilla_xpcom_internal_GREImpl_initEmbedding@20",
143 (NSFuncPtr*) &aFunctions[kFunc_InitEmbedding] },
144 { "_Java_org_mozilla_xpcom_internal_GREImpl_termEmbedding@8",
145 (NSFuncPtr*) &aFunctions[kFunc_TermEmbedding] },
146 { "_Java_org_mozilla_xpcom_internal_GREImpl_lockProfileDirectory@12",
147 (NSFuncPtr*) &aFunctions[kFunc_LockProfileDirectory] },
148 { "_Java_org_mozilla_xpcom_internal_GREImpl_notifyProfile@8",
149 (NSFuncPtr*) &aFunctions[kFunc_NotifyProfile] },
150 { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_initXPCOM@16",
151 (NSFuncPtr*) &aFunctions[kFunc_InitXPCOM] },
152 { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_shutdownXPCOM@12",
153 (NSFuncPtr*) &aFunctions[kFunc_ShutdownXPCOM] },
154 { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentManager@8",
155 (NSFuncPtr*) &aFunctions[kFunc_GetComponentManager] },
156 { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentRegistrar@8",
157 (NSFuncPtr*) &aFunctions[kFunc_GetComponentRegistrar] },
158 { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_getServiceManager@8",
159 (NSFuncPtr*) &aFunctions[kFunc_GetServiceManager] },
160 { "_Java_org_mozilla_xpcom_internal_XPCOMImpl_newLocalFile@16",
161 (NSFuncPtr*) &aFunctions[kFunc_NewLocalFile] },
162 { "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_callXPCOMMethod@20",
163 (NSFuncPtr*) &aFunctions[kFunc_CallXPCOMMethod] },
164 { "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_finalizeProxy@12",
165 (NSFuncPtr*) &aFunctions[kFunc_FinalizeProxy] },
166 { "_Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_isSameXPCOMObject@16",
167 (NSFuncPtr*) &aFunctions[kFunc_IsSameXPCOMObject] },
168 { "_Java_org_mozilla_xpcom_ProfileLock_release@16",
169 (NSFuncPtr*) &aFunctions[kFunc_ReleaseProfileLock] },
170 { "_Java_org_mozilla_xpcom_internal_MozillaImpl_getNativeHandleFromAWT@12",
171 (NSFuncPtr*) &aFunctions[kFunc_GetNativeHandleFromAWT] },
172 { "_Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapJavaObject@16",
173 (NSFuncPtr*) &aFunctions[kFunc_WrapJavaObject] },
174 { "_Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapXPCOMObject@20",
175 (NSFuncPtr*) &aFunctions[kFunc_WrapXPCOMObject] },
176 { nsnull, nsnull }
178 #else
179 nsDynamicFunctionLoad funcs[] = {
180 { "Java_org_mozilla_xpcom_internal_MozillaImpl_initialize",
181 (NSFuncPtr*) &aFunctions[kFunc_Initialize] },
182 { "Java_org_mozilla_xpcom_internal_GREImpl_initEmbedding",
183 (NSFuncPtr*) &aFunctions[kFunc_InitEmbedding] },
184 { "Java_org_mozilla_xpcom_internal_GREImpl_termEmbedding",
185 (NSFuncPtr*) &aFunctions[kFunc_TermEmbedding] },
186 { "Java_org_mozilla_xpcom_internal_GREImpl_lockProfileDirectory",
187 (NSFuncPtr*) &aFunctions[kFunc_LockProfileDirectory] },
188 { "Java_org_mozilla_xpcom_internal_GREImpl_notifyProfile",
189 (NSFuncPtr*) &aFunctions[kFunc_NotifyProfile] },
190 { "Java_org_mozilla_xpcom_internal_XPCOMImpl_initXPCOM",
191 (NSFuncPtr*) &aFunctions[kFunc_InitXPCOM] },
192 { "Java_org_mozilla_xpcom_internal_XPCOMImpl_shutdownXPCOM",
193 (NSFuncPtr*) &aFunctions[kFunc_ShutdownXPCOM] },
194 { "Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentManager",
195 (NSFuncPtr*) &aFunctions[kFunc_GetComponentManager] },
196 { "Java_org_mozilla_xpcom_internal_XPCOMImpl_getComponentRegistrar",
197 (NSFuncPtr*) &aFunctions[kFunc_GetComponentRegistrar] },
198 { "Java_org_mozilla_xpcom_internal_XPCOMImpl_getServiceManager",
199 (NSFuncPtr*) &aFunctions[kFunc_GetServiceManager] },
200 { "Java_org_mozilla_xpcom_internal_XPCOMImpl_newLocalFile",
201 (NSFuncPtr*) &aFunctions[kFunc_NewLocalFile] },
202 { "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_callXPCOMMethod",
203 (NSFuncPtr*) &aFunctions[kFunc_CallXPCOMMethod] },
204 { "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_finalizeProxy",
205 (NSFuncPtr*) &aFunctions[kFunc_FinalizeProxy] },
206 { "Java_org_mozilla_xpcom_internal_XPCOMJavaProxy_isSameXPCOMObject",
207 (NSFuncPtr*) &aFunctions[kFunc_IsSameXPCOMObject] },
208 { "Java_org_mozilla_xpcom_ProfileLock_release",
209 (NSFuncPtr*) &aFunctions[kFunc_ReleaseProfileLock] },
210 { "Java_org_mozilla_xpcom_internal_MozillaImpl_getNativeHandleFromAWT",
211 (NSFuncPtr*) &aFunctions[kFunc_GetNativeHandleFromAWT] },
212 { "Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapJavaObject",
213 (NSFuncPtr*) &aFunctions[kFunc_WrapJavaObject] },
214 { "Java_org_mozilla_xpcom_internal_JavaXPCOMMethods_wrapXPCOMObject",
215 (NSFuncPtr*) &aFunctions[kFunc_WrapXPCOMObject] },
216 { nsnull, nsnull }
218 #endif
220 rv = XPCOMGlueLoadXULFunctions(funcs);
221 if (NS_FAILED(rv))
222 return rv;
224 return NS_OK;
227 void
228 ThrowException(JNIEnv* env, const nsresult aErrorCode, const char* aMessage)
230 // Only throw this exception if one hasn't already been thrown, so we don't
231 // mask a previous exception/error.
232 if (env->ExceptionCheck())
233 return;
235 // If the error code we get is for an Out Of Memory error, try to throw an
236 // OutOfMemoryError. The JVM may have enough memory to create this error.
237 if (aErrorCode == NS_ERROR_OUT_OF_MEMORY) {
238 jclass clazz = env->FindClass("java/lang/OutOfMemoryError");
239 if (clazz) {
240 env->ThrowNew(clazz, aMessage);
242 env->DeleteLocalRef(clazz);
243 return;
246 // If the error was not handled above, then create an XPCOMException with the
247 // given error code.
248 jthrowable throwObj = nsnull;
249 jclass exceptionClass = env->FindClass("org/mozilla/xpcom/XPCOMException");
250 if (exceptionClass) {
251 jmethodID mid = env->GetMethodID(exceptionClass, "<init>",
252 "(JLjava/lang/String;)V");
253 if (mid) {
254 throwObj = (jthrowable) env->NewObject(exceptionClass, mid,
255 (PRInt64) aErrorCode,
256 env->NewStringUTF(aMessage));
259 NS_ASSERTION(throwObj, "Failed to create XPCOMException object");
261 // throw exception
262 if (throwObj) {
263 env->Throw(throwObj);
267 // Register the JavaXPCOM native methods. This associates a native Java
268 // method with its C implementation.
269 nsresult
270 RegisterNativeMethods(JNIEnv* env, void** aFunctions)
272 JNINativeMethod mozilla_methods[] = {
273 { "initializeNative", "()V",
274 (void*) aFunctions[kFunc_Initialize] },
275 { "getNativeHandleFromAWT", "(Ljava/lang/Object;)J",
276 (void*) aFunctions[kFunc_GetNativeHandleFromAWT] }
279 JNINativeMethod gre_methods[] = {
280 { "initEmbeddingNative",
281 "(Ljava/io/File;Ljava/io/File;Lorg/mozilla/xpcom/IAppFileLocProvider;)V",
282 (void*) aFunctions[kFunc_InitEmbedding] },
283 { "termEmbedding", "()V",
284 (void*) aFunctions[kFunc_TermEmbedding] },
285 { "lockProfileDirectory", "(Ljava/io/File;)Lorg/mozilla/xpcom/ProfileLock;",
286 (void*) aFunctions[kFunc_LockProfileDirectory] },
287 { "notifyProfile", "()V",
288 (void*) aFunctions[kFunc_NotifyProfile] },
291 JNINativeMethod xpcom_methods[] = {
292 { "initXPCOMNative",
293 "(Ljava/io/File;Lorg/mozilla/xpcom/IAppFileLocProvider;)Lorg/mozilla/interfaces/nsIServiceManager;",
294 (void*) aFunctions[kFunc_InitXPCOM] },
295 { "shutdownXPCOM", "(Lorg/mozilla/interfaces/nsIServiceManager;)V",
296 (void*) aFunctions[kFunc_ShutdownXPCOM] },
297 { "getComponentManager", "()Lorg/mozilla/interfaces/nsIComponentManager;",
298 (void*) aFunctions[kFunc_GetComponentManager] },
299 { "getComponentRegistrar", "()Lorg/mozilla/interfaces/nsIComponentRegistrar;",
300 (void*) aFunctions[kFunc_GetComponentRegistrar] },
301 { "getServiceManager", "()Lorg/mozilla/interfaces/nsIServiceManager;",
302 (void*) aFunctions[kFunc_GetServiceManager] },
303 { "newLocalFile", "(Ljava/lang/String;Z)Lorg/mozilla/interfaces/nsILocalFile;",
304 (void*) aFunctions[kFunc_NewLocalFile] }
307 JNINativeMethod proxy_methods[] = {
308 { "callXPCOMMethod",
309 "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;",
310 (void*) aFunctions[kFunc_CallXPCOMMethod] },
311 { "finalizeProxyNative", "(Ljava/lang/Object;)V",
312 (void*) aFunctions[kFunc_FinalizeProxy] },
313 { "isSameXPCOMObject", "(Ljava/lang/Object;Ljava/lang/Object;)Z",
314 (void*) aFunctions[kFunc_IsSameXPCOMObject] }
317 JNINativeMethod lockProxy_methods[] = {
318 { "releaseNative", "(J)V",
319 (void*) aFunctions[kFunc_ReleaseProfileLock] }
322 JNINativeMethod util_methods[] = {
323 { "wrapJavaObject", "(Ljava/lang/Object;Ljava/lang/String;)J",
324 (void*) aFunctions[kFunc_WrapJavaObject] },
325 { "wrapXPCOMObject", "(JLjava/lang/String;)Ljava/lang/Object;",
326 (void*) aFunctions[kFunc_WrapXPCOMObject] }
329 jint rc = -1;
330 jclass clazz = env->FindClass("org/mozilla/xpcom/internal/MozillaImpl");
331 if (clazz) {
332 rc = env->RegisterNatives(clazz, mozilla_methods,
333 sizeof(mozilla_methods) / sizeof(mozilla_methods[0]));
335 NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
337 rc = -1;
338 clazz = env->FindClass("org/mozilla/xpcom/internal/GREImpl");
339 if (clazz) {
340 rc = env->RegisterNatives(clazz, gre_methods,
341 sizeof(gre_methods) / sizeof(gre_methods[0]));
343 NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
345 rc = -1;
346 clazz = env->FindClass("org/mozilla/xpcom/internal/XPCOMImpl");
347 if (clazz) {
348 rc = env->RegisterNatives(clazz, xpcom_methods,
349 sizeof(xpcom_methods) / sizeof(xpcom_methods[0]));
351 NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
353 rc = -1;
354 clazz = env->FindClass("org/mozilla/xpcom/internal/XPCOMJavaProxy");
355 if (clazz) {
356 rc = env->RegisterNatives(clazz, proxy_methods,
357 sizeof(proxy_methods) / sizeof(proxy_methods[0]));
359 NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
361 rc = -1;
362 clazz = env->FindClass("org/mozilla/xpcom/ProfileLock");
363 if (clazz) {
364 rc = env->RegisterNatives(clazz, lockProxy_methods,
365 sizeof(lockProxy_methods) / sizeof(lockProxy_methods[0]));
367 NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
369 rc = -1;
370 clazz = env->FindClass("org/mozilla/xpcom/internal/JavaXPCOMMethods");
371 if (clazz) {
372 rc = env->RegisterNatives(clazz, util_methods,
373 sizeof(util_methods) / sizeof(util_methods[0]));
375 NS_ENSURE_TRUE(rc == 0, NS_ERROR_FAILURE);
377 return NS_OK;
380 // Load the JavaXPCOM methods from the XUL shared library, and registers them
381 // as Java native methods.
382 extern "C" JX_EXPORT void JNICALL
383 JXM_NATIVE(registerJavaXPCOMMethodsNative) (JNIEnv *env, jclass that,
384 jobject aXPCOMPath)
386 void* functions[JX_NUM_FUNCS];
387 memset(functions, 0, JX_NUM_FUNCS * sizeof(void*));
389 nsresult rv = LoadXULMethods(env, aXPCOMPath, functions);
390 if (NS_SUCCEEDED(rv)) {
391 rv = RegisterNativeMethods(env, functions);
394 if (NS_FAILED(rv)) {
395 ThrowException(env, rv, "Failed to register JavaXPCOM methods");