[lang] [PATCH] new ExceptionUtils.setCause() method

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk@366225 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gary D. Gregory 2006-01-05 17:35:43 +00:00
parent 3c73a44b34
commit db5f61a647
2 changed files with 133 additions and 17 deletions

View File

@ -31,10 +31,11 @@
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.commons.lang.NullArgumentException;
/**
* <p>Provides utilities for manipulating and examining
* <code>Throwable</code> objects.</p>
<code>Throwable</code> objects.</p>
*
* @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
* @author Dmitri Plotnikov
@ -73,22 +74,40 @@ public class ExceptionUtils {
};
/**
* <p>The Method object for JDK1.4 getCause.</p>
* <p>
* The Method object for Java 1.4 getCause.
* </p>
*/
private static final Method THROWABLE_CAUSE_METHOD;
/**
* <p>
* The Method object for Java 1.4 initCause.
* </p>
*/
private static final Method THROWABLE_INITCAUSE_METHOD;
static {
Method getCauseMethod;
Method causeMethod;
try {
getCauseMethod = Throwable.class.getMethod("getCause", null);
causeMethod = Throwable.class.getMethod("getCause", null);
} catch (Exception e) {
getCauseMethod = null;
causeMethod = null;
}
THROWABLE_CAUSE_METHOD = getCauseMethod;
THROWABLE_CAUSE_METHOD = causeMethod;
try {
causeMethod = Throwable.class.getMethod("initCause", new Class[]{Throwable.class});
} catch (Exception e) {
causeMethod = null;
}
THROWABLE_INITCAUSE_METHOD = causeMethod;
}
/**
* <p>Public constructor allows an instance of <code>ExceptionUtils</code>
* to be created, although that is not normally necessary.</p>
* <p>
* Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
* normally necessary.
* </p>
*/
public ExceptionUtils() {
super();
@ -129,6 +148,72 @@ public static void removeCauseMethodName(String methodName) {
}
}
/**
* <p>
* Sets the cause of a <code>Throwable</code> using introspection, allowing source code compatibility between
* pre-1.4 and post-1.4 Java releases.
* </p>
*
* <p>
* The typical use of this method is inside a constructor as in the following example:
* </p>
*
* <p>
* <pre>
* import org.apache.commons.lang.exception.ExceptionUtils;
*
* public class MyException extends Exception {
*
* public MyException(String msg) {
* super(msg);
* }
*
* public MyException(String msg, Throwable cause) {
* super(msg);
* ExceptionUtils.setCause(this, cause);
* }
*
* }
* </pre>
* </p>
*
* @param target
* the target <code>Throwable</code>
* @param cause
* the <code>Throwable</code> to set in the target
* @return a <code>true</code> if the target has been modified
* @since 2.2
*/
public static boolean setCause(Throwable target, Throwable cause) {
if (target == null) {
throw new NullArgumentException("target");
}
Object[] causeArgs = new Object[]{cause};
boolean modifiedTarget = false;
if (THROWABLE_INITCAUSE_METHOD != null) {
try {
THROWABLE_INITCAUSE_METHOD.invoke(target, causeArgs);
modifiedTarget = true;
} catch (IllegalAccessException ignored) {
// Exception ignored.
} catch (InvocationTargetException ignored) {
// Exception ignored.
}
}
try {
Method setCauseMethod = target.getClass().getMethod("setCause", new Class[]{Throwable.class});
setCauseMethod.invoke(target, causeArgs);
modifiedTarget = true;
} catch (NoSuchMethodException ignored) {
// Exception ignored.
} catch (IllegalAccessException ignored) {
// Exception ignored.
} catch (InvocationTargetException ignored) {
// Exception ignored.
}
return modifiedTarget;
}
/**
* Returns the given list as a <code>String[]</code>.
* @param list a list to transform.
@ -768,14 +853,20 @@ public static String[] getStackFrames(Throwable throwable) {
}
/**
* <p>Returns an array where each element is a line from the argument.</p>
* <p>The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.</p>
*
* <p>Functionality shared between the
* <code>getStackFrames(Throwable)</code> methods of this and the
* {@link org.apache.commons.lang.exception.NestableDelegate}
* classes.</p>
* @param stackTrace A stack trace String.
* <p>
* Returns an array where each element is a line from the argument.
* </p>
* <p>
* The end of line is determined by the value of {@link SystemUtils#LINE_SEPARATOR}.
* </p>
*
* <p>
* Functionality shared between the <code>getStackFrames(Throwable)</code> methods of this and the
* {@link org.apache.commons.lang.exception.NestableDelegate} classes.
* </p>
*
* @param stackTrace
* A stack trace String.
* @return an array where each element is a line from the argument.
*/
static String[] getStackFrames(String stackTrace) {

View File

@ -16,6 +16,7 @@
package org.apache.commons.lang.exception;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
@ -25,6 +26,7 @@
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.lang.SystemUtils;
/**
@ -139,6 +141,25 @@ public void testGetRootCause_Throwable() {
assertSame(withoutCause, ExceptionUtils.getRootCause(withCause));
}
public void testSetCause() {
Exception cause = new ExceptionWithoutCause();
assertEquals(true, ExceptionUtils.setCause(new ExceptionWithCause(null), cause));
if (SystemUtils.isJavaVersionAtLeast(140)) {
assertEquals(true, ExceptionUtils.setCause(new ExceptionWithoutCause(), cause));
}
}
/**
* Tests overriding a cause to <code>null</code>.
*/
public void testSetCauseToNull() {
Exception ex = new ExceptionWithCause(new IOException());
assertEquals(true, ExceptionUtils.setCause(ex, new IllegalStateException()));
assertNotNull(ExceptionUtils.getCause(ex));
assertEquals(true, ExceptionUtils.setCause(ex, null));
assertNull(ExceptionUtils.getCause(ex));
}
//-----------------------------------------------------------------------
public void testIsThrowableNested() {
if (SystemUtils.isJavaVersionAtLeast(140)) {
@ -387,12 +408,16 @@ private static class ExceptionWithCause extends Exception {
private Throwable cause;
public ExceptionWithCause(Throwable cause) {
this.cause = cause;
setCause(cause);
}
public Throwable getCause() {
return cause;
}
public void setCause(Throwable cause) {
this.cause = cause;
}
}
/**