You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ch...@apache.org on 2015/07/13 00:28:51 UTC

[lang] LANG-1149 Added alternative checked exception wrapping/unwrapping methods

Repository: commons-lang
Updated Branches:
  refs/heads/master 59022fb87 -> 03fe88ab7


LANG-1149 Added alternative checked exception wrapping/unwrapping methods


Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/03fe88ab
Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/03fe88ab
Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/03fe88ab

Branch: refs/heads/master
Commit: 03fe88ab71cf2eadaa39654786c3fba713742768
Parents: 59022fb
Author: Chas Honton <ch...@apache.org>
Authored: Sun Jul 12 15:28:41 2015 -0700
Committer: Chas Honton <ch...@apache.org>
Committed: Sun Jul 12 15:28:41 2015 -0700

----------------------------------------------------------------------
 .../commons/lang3/exception/ExceptionUtils.java | 61 +++++++++++++++++++-
 .../lang3/exception/ExceptionUtilsTest.java     | 48 +++++++++++++++
 2 files changed, 108 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/03fe88ab/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java b/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java
index 8f0898f..e49e2ed 100644
--- a/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java
+++ b/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java
@@ -21,6 +21,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.StringTokenizer;
@@ -717,6 +718,10 @@ public class ExceptionUtils {
      *  public int wrapExample { // note that there is no throws clause
      *      try {
      *          return invocation(); // throws IOException
+     *      } catch (Error e) {
+     *          throw e;
+     *      } catch (RuntimeException e) {
+     *          throw e;  // wraps a checked exception
      *      } catch (Exception e) {
      *          throw new UndeclaredThrowableException(e);  // wraps a checked exception
      *      }
@@ -735,13 +740,14 @@ public class ExceptionUtils {
      * exceptions as checked.
      * 
      * @since 3.5
+     * @see {{@link #wrapAndThrow(Throwable)}
      *
      * @param throwable
      *            The throwable to rethrow.
      * @return R Never actually returns, this generic type matches any type
      *         which the calling site requires. "Returning" the results of this
      *         method, as done in the propagateExample above, will satisfy the
-     *         java compiler that all code paths return a value.
+     *         java compiler requirement that all code paths return a value.
      * @throws throwable
      */
     public static <R> R rethrow(Throwable throwable) {
@@ -759,4 +765,57 @@ public class ExceptionUtils {
     private static <R, T extends Throwable> R typeErasure(Throwable throwable) throws T {
         throw (T) throwable;
     }
+
+    /**
+     * Throw a checked exception without adding the exception to the throws
+     * clause of the calling method. For checked exceptions, this method throws
+     * an UndeclaredThrowableException wrapping the checked exception. For
+     * Errors and RuntimeExceptions, the original exception is rethrown.
+     * <p>
+     * The downside to using this approach is that invoking code which needs to
+     * handle specific checked exceptions must sniff up the exception chain to
+     * determine if the caught exception was caused by the checked exception.
+     * 
+     * @since 3.5
+     * @see {{@link #rethrow(Throwable)}, {{@link #hasCause(Throwable, Class)}
+     * 
+     * @param throwable
+     *            The throwable to rethrow.
+     * @return R Never actually returns, this generic type matches any type
+     *         which the calling site requires. "Returning" the results of this
+     *         method, will satisfy the java compiler requirement that all code
+     *         paths return a value.
+     * @throws throwable
+     */
+    public static <R> R wrapAndThrow(Throwable throwable) {
+        if (throwable instanceof RuntimeException) {
+            throw (RuntimeException) throwable;
+        }
+        if (throwable instanceof Error) {
+            throw (Error) throwable;
+        }
+        throw new UndeclaredThrowableException(throwable);
+    }
+
+    /**
+     * Does the throwable's causal chain have an immediate or wrapped exception
+     * of the given type?
+     * 
+     * @since 3.5
+     * @see {{@link #wrapAndThrow(Throwable)}
+     * 
+     * @param chain
+     *            The root of a Throwable causal chain.
+     * @param type
+     *            The exception type to test.
+     * @return true, if chain is an instance of type or is an
+     *         UndeclaredThrowableException wrapping a cause.
+     */
+    public static boolean hasCause(Throwable chain,
+            Class<? extends Throwable> type) {
+        if (chain instanceof UndeclaredThrowableException) {
+            chain = chain.getCause();
+        }
+        return type.isInstance(chain);
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/03fe88ab/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java b/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java
index e7d264d..ec4875b 100644
--- a/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java
@@ -587,4 +587,52 @@ public class ExceptionUtilsTest {
             return ExceptionUtils.rethrow(e);
         }
     }
+
+    public static class TestThrowable extends Throwable {
+        private static final long serialVersionUID = 1L;
+    }
+
+    @Test
+    public void testWrapAndUnwrapError() {
+        try {
+            ExceptionUtils.wrapAndThrow(new OutOfMemoryError());
+            Assert.fail("Error not thrown");
+        }
+        catch(Throwable t) {
+            Assert.assertTrue(ExceptionUtils.hasCause(t, Error.class));
+        }
+    }
+
+    @Test
+    public void testWrapAndUnwrapRuntimeException() {
+        try {
+            ExceptionUtils.wrapAndThrow(new IllegalArgumentException());
+            Assert.fail("RuntimeException not thrown");
+        }
+        catch(Throwable t) {
+            Assert.assertTrue(ExceptionUtils.hasCause(t, RuntimeException.class));
+        }
+    }
+
+    @Test
+    public void testWrapAndUnwrapCheckedException() {
+        try {
+            ExceptionUtils.wrapAndThrow(new IOException());
+            Assert.fail("Checked Exception not thrown");
+        }
+        catch(Throwable t) {
+            Assert.assertTrue(ExceptionUtils.hasCause(t, IOException.class));
+        }
+    }
+
+    @Test
+    public void testWrapAndUnwrapThrowable() {
+        try {
+            ExceptionUtils.wrapAndThrow(new TestThrowable());
+            Assert.fail("Checked Exception not thrown");
+        }
+        catch(Throwable t) {
+            Assert.assertTrue(ExceptionUtils.hasCause(t, TestThrowable.class));
+        }
+    }
 }