Author: ggregory Date: Thu Jan 5 09:35:43 2006 New Revision: 366225 URL: http://svn.apache.org/viewcvs?rev=366225&view=rev Log: http://issues.apache.org/bugzilla/show_bug.cgi?id=37574 [lang] [PATCH] new ExceptionUtils.setCause() method
Modified: jakarta/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java jakarta/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java Modified: jakarta/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java?rev=366225&r1=366224&r2=366225&view=diff ============================================================================== --- jakarta/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java (original) +++ jakarta/commons/proper/lang/trunk/src/java/org/apache/commons/lang/exception/ExceptionUtils.java Thu Jan 5 09:35:43 2006 @@ -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 @@ }; /** - * <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(); @@ -130,6 +149,72 @@ } /** + * <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. * @return the given list as a <code>String[]</code>. @@ -768,14 +853,20 @@ } /** - * <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 [EMAIL PROTECTED] SystemUtils#LINE_SEPARATOR}.</p> - * - * <p>Functionality shared between the - * <code>getStackFrames(Throwable)</code> methods of this and the - * [EMAIL PROTECTED] 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 [EMAIL PROTECTED] SystemUtils#LINE_SEPARATOR}. + * </p> + * + * <p> + * Functionality shared between the <code>getStackFrames(Throwable)</code> methods of this and the + * [EMAIL PROTECTED] 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) { Modified: jakarta/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java?rev=366225&r1=366224&r2=366225&view=diff ============================================================================== --- jakarta/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java (original) +++ jakarta/commons/proper/lang/trunk/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java Thu Jan 5 09:35:43 2006 @@ -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 @@ 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,11 +408,15 @@ 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; } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]