From 08de0b256bad9277ebbc7dc5bcdf18fbf9889c27 Mon Sep 17 00:00:00 2001 From: "pedemont%us.ibm.com" Date: Wed, 22 Dec 2004 22:03:50 +0000 Subject: [PATCH] Rework XPCOMException --- extensions/java/xpcom/XPCOMException.java | 43 ++++++++++++-- extensions/java/xpcom/nsJavaInterfaces.cpp | 19 ++++--- extensions/java/xpcom/nsJavaWrapper.cpp | 14 ++--- .../java/xpcom/nsJavaXPCOMBindingUtils.cpp | 57 ++++++++++++++----- .../java/xpcom/nsJavaXPCOMBindingUtils.h | 17 +++++- 5 files changed, 112 insertions(+), 38 deletions(-) diff --git a/extensions/java/xpcom/XPCOMException.java b/extensions/java/xpcom/XPCOMException.java index e29be6554978..0a824f81f59a 100644 --- a/extensions/java/xpcom/XPCOMException.java +++ b/extensions/java/xpcom/XPCOMException.java @@ -37,27 +37,58 @@ package org.mozilla.xpcom; +import java.lang.*; + /** * This exception is thrown whenever an internal XPCOM/Gecko error occurs. - * The internal Mozilla error ID is contained in the message. + * You can query the error ID returned by XPCOM by checking + * errorcode field. */ public final class XPCOMException extends RuntimeException { /** - * Constructs a new XPCOMException instance. + * The XPCOM error value. + */ + public long errorcode; + + /** + * Constructs a new XPCOMException instance, with a default error + * (NS_ERROR_FAILURE) and message. */ public XPCOMException() { - super(); + this(0x80004005L, "Unspecified internal XPCOM error"); } /** - * Constructs a new XPCOMException instance. + * Constructs a new XPCOMException instance with the given message, passing + * NS_ERROR_FAILURE as the error code. * - * @param message detailed message of exception + * @param message detailed message of exception */ public XPCOMException(String message) { - super(message); + this(0x80004005L, message); + } + + /** + * Constructs a new XPCOMException instance with the given code, passing + * a default message. + * + * @param code internal XPCOM error ID + */ + public XPCOMException(long code) { + this(code, "Internal XPCOM error"); + } + + /** + * Constructs a new XPCOMException instance with an error code and message. + * + * @param code internal XPCOM error ID + * @param message detailed message of exception + */ + public XPCOMException(long code, String message) { + super(message + " (0x" + Long.toHexString(code) + ")"); + this.errorcode = code; } } diff --git a/extensions/java/xpcom/nsJavaInterfaces.cpp b/extensions/java/xpcom/nsJavaInterfaces.cpp index d8c42334cb38..824d2447d9a6 100644 --- a/extensions/java/xpcom/nsJavaInterfaces.cpp +++ b/extensions/java/xpcom/nsJavaInterfaces.cpp @@ -82,7 +82,7 @@ GECKO_NATIVE(initEmbedding) (JNIEnv* env, jclass, jobject aMozBinDirectory, } } - ThrowXPCOMException(env, NS_FAILED(rv) ? rv : NS_ERROR_FAILURE); + ThrowXPCOMException(env, rv, "Failure in initEmbedding"); FreeJavaGlobals(env); } @@ -91,7 +91,7 @@ GECKO_NATIVE(termEmbedding) (JNIEnv *env, jclass) { nsresult rv = NS_TermEmbedding(); if (NS_FAILED(rv)) - ThrowXPCOMException(env, rv); + ThrowXPCOMException(env, rv, "NS_TermEmbedding failed"); FreeJavaGlobals(env); } @@ -142,7 +142,7 @@ XPCOM_NATIVE(initXPCOM) (JNIEnv* env, jclass, jobject aMozBinDirectory, } } - ThrowXPCOMException(env, NS_FAILED(rv) ? rv : NS_ERROR_FAILURE); + ThrowXPCOMException(env, rv, "Failure in initXPCOM"); FreeJavaGlobals(env); return nsnull; } @@ -156,7 +156,8 @@ XPCOM_NATIVE(shutdownXPCOM) (JNIEnv *env, jclass, jobject aServMgr) void* xpcomObj = GetMatchingXPCOMObject(env, aServMgr); NS_ASSERTION(xpcomObj != nsnull, "Failed to get matching XPCOM object"); if (xpcomObj == nsnull) { - ThrowXPCOMException(env, NS_ERROR_FAILURE); + ThrowXPCOMException(env, 0, + "No matching XPCOM obj for service manager proxy"); return; } @@ -167,7 +168,7 @@ XPCOM_NATIVE(shutdownXPCOM) (JNIEnv *env, jclass, jobject aServMgr) nsresult rv = NS_ShutdownXPCOM(servMgr); if (NS_FAILED(rv)) - ThrowXPCOMException(env, rv); + ThrowXPCOMException(env, rv, "NS_ShutdownXPCOM failed"); FreeJavaGlobals(env); } @@ -212,7 +213,7 @@ XPCOM_NATIVE(newLocalFile) (JNIEnv *env, jclass, jstring aPath, } if (java_stub == nsnull) - ThrowXPCOMException(env, 0); + ThrowXPCOMException(env, rv, "Failure in newLocalFile"); return java_stub; } @@ -244,7 +245,7 @@ XPCOM_NATIVE(getComponentManager) (JNIEnv *env, jclass) } if (java_stub == nsnull) - ThrowXPCOMException(env, 0); + ThrowXPCOMException(env, rv, "Failure in getComponentManager"); return java_stub; } @@ -276,7 +277,7 @@ XPCOM_NATIVE(getComponentRegistrar) (JNIEnv *env, jclass) } if (java_stub == nsnull) - ThrowXPCOMException(env, 0); + ThrowXPCOMException(env, rv, "Failure in getComponentRegistrar"); return java_stub; } @@ -308,7 +309,7 @@ XPCOM_NATIVE(getServiceManager) (JNIEnv *env, jclass) } if (java_stub == nsnull) - ThrowXPCOMException(env, 0); + ThrowXPCOMException(env, rv, "Failure in getServiceManager"); return java_stub; } diff --git a/extensions/java/xpcom/nsJavaWrapper.cpp b/extensions/java/xpcom/nsJavaWrapper.cpp index 72b06a1fc373..2d7aa148f1a2 100644 --- a/extensions/java/xpcom/nsJavaWrapper.cpp +++ b/extensions/java/xpcom/nsJavaWrapper.cpp @@ -883,9 +883,8 @@ CallXPCOMMethod(JNIEnv *env, jclass that, jobject aJavaObject, { // Find corresponding XPCOM object void* xpcomObj = GetMatchingXPCOMObject(env, aJavaObject); - NS_ASSERTION(xpcomObj != nsnull, "Failed to get matching XPCOM object"); if (xpcomObj == nsnull) { - ThrowXPCOMException(env, 0); + ThrowXPCOMException(env, 0, "Failed to get matching XPCOM object"); return; } @@ -951,8 +950,7 @@ CallXPCOMMethod(JNIEnv *env, jclass that, jobject aJavaObject, } } if (NS_FAILED(rv)) { - NS_WARNING("SetupParams failed"); - ThrowXPCOMException(env, rv); + ThrowXPCOMException(env, rv, "SetupParams failed"); return; } } @@ -975,8 +973,7 @@ CallXPCOMMethod(JNIEnv *env, jclass that, jobject aJavaObject, } } if (NS_FAILED(rv)) { - NS_WARNING("FinalizeParams failed"); - ThrowXPCOMException(env, rv); + ThrowXPCOMException(env, rv, "FinalizeParams failed"); return; } @@ -1001,7 +998,10 @@ CallXPCOMMethod(JNIEnv *env, jclass that, jobject aJavaObject, // 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)) { - ThrowXPCOMException(env, invokeResult); + nsCAutoString message("The function \""); + message.Append(methodInfo->GetName()); + message.Append("\" returned an error condition"); + ThrowXPCOMException(env, invokeResult, message.get()); } return; diff --git a/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp b/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp index 7b7971b88d93..18e258d996df 100644 --- a/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp +++ b/extensions/java/xpcom/nsJavaXPCOMBindingUtils.cpp @@ -454,20 +454,6 @@ CreateJavaXPCOMInstance(nsISupports* aXPCOMObject, const nsIID* aIID) } -void -ThrowXPCOMException(JNIEnv* env, int aFailureCode) -{ - // Only throw this exception if one hasn't already been thrown, so we don't - // mask a previous exception/error. - jthrowable throwObj = env->ExceptionOccurred(); - if (throwObj == nsnull) { - char exp_msg[40]; - sprintf(exp_msg, "\nInternal XPCOM Error: %x", aFailureCode); - jint rc = env->ThrowNew(xpcomExceptionClass, exp_msg); - NS_ASSERTION(rc == 0, "Failed to throw XPCOMException"); - } -} - nsresult GetIIDForMethodParam(nsIInterfaceInfo *iinfo, const nsXPTMethodInfo *methodInfo, @@ -522,6 +508,49 @@ GetIIDForMethodParam(nsIInterfaceInfo *iinfo, /******************************* * JNI helper functions *******************************/ + +void +ThrowXPCOMException(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. + jthrowable throwObj = env->ExceptionOccurred(); + if (throwObj != nsnull) + return; + + // Create parameters and method signature. Max of 2 params. The error code + // comes before the message string. + PRUint32 index = 0; + jvalue* args = new jvalue[2]; + nsCAutoString methodSig("("); + if (aErrorCode) { + args[index++].j = aErrorCode; + methodSig.Append("J"); + } + if (aMessage) { + args[index].l = env->NewStringUTF(aMessage); + methodSig.Append("Ljava/lang/String;"); + } + methodSig.Append(")V"); + + // create exception object + jmethodID mid = env->GetMethodID(xpcomExceptionClass, "", + methodSig.get()); + if (mid) { + throwObj = (jthrowable) env->NewObjectA(xpcomExceptionClass, mid, args); + } + NS_ASSERTION(throwObj, "Failed to create XPCOMException object"); + + // throw exception + if (throwObj) { + env->Throw(throwObj); + } + + // cleanup + delete[] args; +} + nsAString* jstring_to_nsAString(JNIEnv* env, jstring aString) { diff --git a/extensions/java/xpcom/nsJavaXPCOMBindingUtils.h b/extensions/java/xpcom/nsJavaXPCOMBindingUtils.h index a4638eee0587..cde71d0a74ad 100644 --- a/extensions/java/xpcom/nsJavaXPCOMBindingUtils.h +++ b/extensions/java/xpcom/nsJavaXPCOMBindingUtils.h @@ -109,8 +109,6 @@ void* GetMatchingXPCOMObject(JNIEnv* env, jobject aJavaObject); jobject GetMatchingJavaObject(JNIEnv* env, void* aXPCOMObject); -void ThrowXPCOMException(JNIEnv* env, int aFailureCode); - nsresult GetIIDForMethodParam(nsIInterfaceInfo *iinfo, const nsXPTMethodInfo *methodInfo, const nsXPTParamInfo ¶mInfo, @@ -119,9 +117,24 @@ nsresult GetIIDForMethodParam(nsIInterfaceInfo *iinfo, PRBool isFullVariantArray, nsID &result); + /******************************* * JNI helper functions *******************************/ + +/** + * Constructs and throws an XPCOMException. + * + * @param env Java environment pointer + * @param aErrorCode The error code returned by an XPCOM/Gecko function. Pass + * zero for the default behaviour. + * @param aMessage A string that provides details for throwing this + * exception. Pass in nsnull for the default + * behaviour. + */ +void ThrowXPCOMException(JNIEnv* env, const nsresult aErrorCode, + const char* aMessage); + // java.lang.String to nsAString/nsACString nsAString* jstring_to_nsAString(JNIEnv* env, jstring aString); nsACString* jstring_to_nsACString(JNIEnv* env, jstring aString);