CAUSE_METHOD_NAMES: Repurposed CAUSE_METHOD_NAME to be a list of

method names which may yield a wrapped exception.

getCause(Throwable): Now just wraps getCause(Throwable, String[]),
passing in CAUSE_METHOD_NAMES as its list of method names.

getCause(Throwable, String[]): Refactored code extracted from
getCause(Throwable) which looks at a list of method names, plus a
"detail" field.

getCauseUsingMethodName(): Swapped parameter order for consistency.

getCauseUsingFieldName(): New method which introspects fields instead
of methods.


git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk@136967 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Daniel Rall 2002-08-14 23:08:28 +00:00
parent 6fdd16815a
commit 99ba8f14d5
1 changed files with 81 additions and 11 deletions

View File

@ -54,6 +54,7 @@
* <http://www.apache.org/>.
*/
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
@ -69,7 +70,13 @@ public class ExceptionUtils
/**
* The name of the <code>getCause()</code> method.
*/
protected static final String CAUSE_METHOD_NAME = "getCause";
protected static final String[] CAUSE_METHOD_NAMES =
{
"getCause",
"getNextException",
"getTargetException",
"getException"
};
/**
* The parameters of the <code>getCause()</code> method.
@ -86,25 +93,50 @@ protected ExceptionUtils()
/**
* Introspects the specified <code>Throwable</code> for a
* <code>getCause()</code> method which returns a
* <code>getCause()</code>, <code>getNextException()</code>,
* <code>getTargetException()</code>, or
* <code>getException()</code> method which returns a
* <code>Throwable</code> object (standard as of JDK 1.4, and part
* of the {@link
* org.apache.commons.lang.exception.NestableException} API),
* extracting and returning the cause of the exception.
* Otherwise, returns <code>null</code>.
*
* <p>TODO: Examine for a "detail" public member attribute from
* java.rmi.RemoteException.
* extracting and returning the cause of the exception. In the
* absence of any such method, the object is inspected for a
* <code>detail</code> field assignable to a
* <code>Throwable</code>. If none of the above is found, returns
* <code>null</code>.
*
* @param t The exception to introspect for a cause.
* @return The cause of the <code>Throwable</code>.
*/
public static Throwable getCause(Throwable t)
{
return getCause(t, CAUSE_METHOD_NAMES);
}
/**
* Extends the API of {@link #getCause(Throwable)} by
* introspecting for only user-specified method names.
*
* @see #getCause(Throwable)
*/
public static Throwable getCause(Throwable t, String[] methodNames)
{
Throwable cause = getCauseUsingWellKnownTypes(t);
if (cause == null)
{
cause = getCauseUsingMethodName(CAUSE_METHOD_NAME, t);
for (int i = 0; i < methodNames.length; i++)
{
cause = getCauseUsingMethodName(t, methodNames[i]);
if (cause != null)
{
break;
}
}
if (cause == null)
{
cause = getCauseUsingFieldName(t, "detail");
}
}
return cause;
}
@ -165,13 +197,13 @@ else if (t instanceof InvocationTargetException)
}
/**
* @param methodName The name of the method to find and invoke.
* @param t The exception to examine.
* @param methodName The name of the method to find and invoke.
* @return The wrapped exception, or <code>null</code> if not
* found.
*/
private static Throwable getCauseUsingMethodName(String methodName,
Throwable t)
private static Throwable getCauseUsingMethodName(Throwable t,
String methodName)
{
Method method = null;
try
@ -204,4 +236,42 @@ private static Throwable getCauseUsingMethodName(String methodName,
}
return null;
}
/**
* @param t The exception to examine.
* @param fieldName The name of the attribute to examine.
* @return The wrapped exception, or <code>null</code> if not
* found.
*/
private static Throwable getCauseUsingFieldName(Throwable t,
String fieldName)
{
Field field = null;
try
{
field = t.getClass().getField(fieldName);
}
catch (NoSuchFieldException ignored)
{
}
catch (SecurityException ignored)
{
}
if (field != null &&
Throwable.class.isAssignableFrom(field.getType()))
{
try
{
return (Throwable) field.get(t);
}
catch (IllegalAccessException ignored)
{
}
catch (IllegalArgumentException ignored)
{
}
}
return null;
}
}