[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:
parent
3c73a44b34
commit
db5f61a647
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue