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));
+ }
+ }
}