You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2019/05/05 21:23:52 UTC
[commons-lang] branch master updated: Sort by method name.
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push:
new f698f9e Sort by method name.
f698f9e is described below
commit f698f9e64e4305b3aa2f3ae75b747acab4de773d
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun May 5 17:23:43 2019 -0400
Sort by method name.
---
.../commons/lang3/exception/ExceptionUtils.java | 972 ++++++++++-----------
.../lang3/exception/ExceptionUtilsTest.java | 606 ++++++-------
2 files changed, 789 insertions(+), 789 deletions(-)
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 4d0f040..7dfe4ad 100644
--- a/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java
+++ b/src/main/java/org/apache/commons/lang3/exception/ExceptionUtils.java
@@ -66,31 +66,6 @@ public class ExceptionUtils {
"getThrowable",
};
- /**
- * <p>
- * Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
- * normally necessary.
- * </p>
- */
- public ExceptionUtils() {
- super();
- }
-
- //-----------------------------------------------------------------------
- /**
- * <p>Returns the default names used when searching for the cause of an exception.</p>
- *
- * <p>This may be modified and used in the overloaded getCause(Throwable, String[]) method.</p>
- *
- * @return cloned array of the default method names
- * @since 3.0
- * @deprecated This feature will be removed in Lang 4.0
- */
- @Deprecated
- public static String[] getDefaultCauseMethodNames() {
- return ArrayUtils.clone(CAUSE_METHOD_NAMES);
- }
-
//-----------------------------------------------------------------------
/**
* <p>Introspects the <code>Throwable</code> to obtain the cause.</p>
@@ -165,28 +140,6 @@ public class ExceptionUtils {
}
/**
- * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
- *
- * <p>This method walks through the exception chain to the last element,
- * "root" of the tree, using {@link Throwable#getCause()}, and
- * returns that exception.</p>
- *
- * <p>From version 2.2, this method handles recursive cause structures
- * that might otherwise cause infinite loops. If the throwable parameter
- * has a cause of itself, then null will be returned. If the throwable
- * parameter cause chain loops, the last element in the chain before the
- * loop is returned.</p>
- *
- * @param throwable the throwable to get the root cause for, may be null
- * @return the root cause of the <code>Throwable</code>,
- * <code>null</code> if null throwable input
- */
- public static Throwable getRootCause(final Throwable throwable) {
- final List<Throwable> list = getThrowableList(throwable);
- return list.isEmpty() ? null : list.get(list.size() - 1);
- }
-
- /**
* <p>Finds a <code>Throwable</code> by method name.</p>
*
* @param throwable the exception to examine
@@ -214,249 +167,299 @@ public class ExceptionUtils {
//-----------------------------------------------------------------------
/**
- * <p>Counts the number of <code>Throwable</code> objects in the
- * exception chain.</p>
+ * <p>Returns the default names used when searching for the cause of an exception.</p>
*
- * <p>A throwable without cause will return <code>1</code>.
- * A throwable with one cause will return <code>2</code> and so on.
- * A <code>null</code> throwable will return <code>0</code>.</p>
+ * <p>This may be modified and used in the overloaded getCause(Throwable, String[]) method.</p>
*
- * <p>From version 2.2, this method handles recursive cause structures
- * that might otherwise cause infinite loops. The cause chain is
- * processed until the end is reached, or until the next item in the
- * chain is already in the result set.</p>
+ * @return cloned array of the default method names
+ * @since 3.0
+ * @deprecated This feature will be removed in Lang 4.0
+ */
+ @Deprecated
+ public static String[] getDefaultCauseMethodNames() {
+ return ArrayUtils.clone(CAUSE_METHOD_NAMES);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Gets a short message summarising the exception.
+ * <p>
+ * The message returned is of the form
+ * {ClassNameWithoutPackage}: {ThrowableMessage}
*
- * @param throwable the throwable to inspect, may be null
- * @return the count of throwables, zero if null input
+ * @param th the throwable to get a message for, null returns empty string
+ * @return the message, non-null
+ * @since 2.2
*/
- public static int getThrowableCount(final Throwable throwable) {
- return getThrowableList(throwable).size();
+ public static String getMessage(final Throwable th) {
+ if (th == null) {
+ return StringUtils.EMPTY;
+ }
+ final String clsName = ClassUtils.getShortClassName(th, null);
+ final String msg = th.getMessage();
+ return clsName + ": " + StringUtils.defaultString(msg);
}
/**
- * <p>Returns the list of <code>Throwable</code> objects in the
- * exception chain.</p>
+ * <p>Introspects the <code>Throwable</code> to obtain the root cause.</p>
*
- * <p>A throwable without cause will return an array containing
- * one element - the input throwable.
- * A throwable with one cause will return an array containing
- * two elements. - the input throwable and the cause throwable.
- * A <code>null</code> throwable will return an array of size zero.</p>
+ * <p>This method walks through the exception chain to the last element,
+ * "root" of the tree, using {@link Throwable#getCause()}, and
+ * returns that exception.</p>
*
* <p>From version 2.2, this method handles recursive cause structures
- * that might otherwise cause infinite loops. The cause chain is
- * processed until the end is reached, or until the next item in the
- * chain is already in the result set.</p>
+ * that might otherwise cause infinite loops. If the throwable parameter
+ * has a cause of itself, then null will be returned. If the throwable
+ * parameter cause chain loops, the last element in the chain before the
+ * loop is returned.</p>
*
- * @see #getThrowableList(Throwable)
- * @param throwable the throwable to inspect, may be null
- * @return the array of throwables, never null
+ * @param throwable the throwable to get the root cause for, may be null
+ * @return the root cause of the <code>Throwable</code>,
+ * <code>null</code> if null throwable input
*/
- public static Throwable[] getThrowables(final Throwable throwable) {
+ public static Throwable getRootCause(final Throwable throwable) {
final List<Throwable> list = getThrowableList(throwable);
- return list.toArray(new Throwable[list.size()]);
+ return list.isEmpty() ? null : list.get(list.size() - 1);
}
+ //-----------------------------------------------------------------------
/**
- * <p>Returns the list of <code>Throwable</code> objects in the
- * exception chain.</p>
- *
- * <p>A throwable without cause will return a list containing
- * one element - the input throwable.
- * A throwable with one cause will return a list containing
- * two elements. - the input throwable and the cause throwable.
- * A <code>null</code> throwable will return a list of size zero.</p>
- *
- * <p>This method handles recursive cause structures that might
- * otherwise cause infinite loops. The cause chain is processed until
- * the end is reached, or until the next item in the chain is already
- * in the result set.</p>
+ * Gets a short message summarising the root cause exception.
+ * <p>
+ * The message returned is of the form
+ * {ClassNameWithoutPackage}: {ThrowableMessage}
*
- * @param throwable the throwable to inspect, may be null
- * @return the list of throwables, never null
+ * @param th the throwable to get a message for, null returns empty string
+ * @return the message, non-null
* @since 2.2
*/
- public static List<Throwable> getThrowableList(Throwable throwable) {
- final List<Throwable> list = new ArrayList<>();
- while (throwable != null && !list.contains(throwable)) {
- list.add(throwable);
- throwable = throwable.getCause();
- }
- return list;
+ public static String getRootCauseMessage(final Throwable th) {
+ Throwable root = getRootCause(th);
+ root = root == null ? th : root;
+ return getMessage(root);
}
+ //-----------------------------------------------------------------------
/**
- * <p>Returns the (zero-based) index of the first <code>Throwable</code>
- * that matches the specified class (exactly) in the exception chain.
- * Subclasses of the specified class do not match - see
- * {@link #indexOfType(Throwable, Class)} for the opposite.</p>
+ * <p>Creates a compact stack trace for the root cause of the supplied
+ * <code>Throwable</code>.</p>
*
- * <p>A <code>null</code> throwable returns <code>-1</code>.
- * A <code>null</code> type returns <code>-1</code>.
- * No match in the chain returns <code>-1</code>.</p>
+ * <p>The output of this method is consistent across JDK versions.
+ * It consists of the root exception followed by each of its wrapping
+ * exceptions separated by '[wrapped]'. Note that this is the opposite
+ * order to the JDK1.4 display.</p>
*
- * @param throwable the throwable to inspect, may be null
- * @param clazz the class to search for, subclasses do not match, null returns -1
- * @return the index into the throwable chain, -1 if no match or null input
+ * @param throwable the throwable to examine, may be null
+ * @return an array of stack trace frames, never null
+ * @since 2.0
*/
- public static int indexOfThrowable(final Throwable throwable, final Class<?> clazz) {
- return indexOf(throwable, clazz, 0, false);
+ public static String[] getRootCauseStackTrace(final Throwable throwable) {
+ if (throwable == null) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ final Throwable throwables[] = getThrowables(throwable);
+ final int count = throwables.length;
+ final List<String> frames = new ArrayList<>();
+ List<String> nextTrace = getStackFrameList(throwables[count - 1]);
+ for (int i = count; --i >= 0;) {
+ final List<String> trace = nextTrace;
+ if (i != 0) {
+ nextTrace = getStackFrameList(throwables[i - 1]);
+ removeCommonFrames(trace, nextTrace);
+ }
+ if (i == count - 1) {
+ frames.add(throwables[i].toString());
+ } else {
+ frames.add(WRAPPED_MARKER + throwables[i].toString());
+ }
+ frames.addAll(trace);
+ }
+ return frames.toArray(new String[frames.size()]);
}
/**
- * <p>Returns the first <code>Throwable</code>
- * that matches the specified class (exactly) in the exception chain.
- * Subclasses of the specified class do not match - see
- * {@link #throwableOfType(Throwable, Class)} for the opposite.</p>
+ * <p>Produces a <code>List</code> of stack frames - the message
+ * is not included. Only the trace of the specified exception is
+ * returned, any caused by trace is stripped.</p>
*
- * <p>A <code>null</code> throwable returns <code>null</code>.
- * A <code>null</code> type returns <code>null</code>.
- * No match in the chain returns <code>null</code>.</p>
+ * <p>This works in most cases - it will only fail if the exception
+ * message contains a line that starts with:
+ * <code>" at".</code></p>
*
- * @param <T> the type of Throwable you are searching.
- * @param throwable the throwable to inspect, may be null
- * @param clazz the class to search for, subclasses do not match, null returns null
- * @return the index into the throwable chain, null if no match or null input
- * @since 3.10
+ * @param t is any throwable
+ * @return List of stack frames
*/
- public static <T extends Throwable> T throwableOfThrowable(final Throwable throwable, final Class<T> clazz) {
- return throwableOf(throwable, clazz, 0, false);
+ static List<String> getStackFrameList(final Throwable t) {
+ final String stackTrace = getStackTrace(t);
+ final String linebreak = System.lineSeparator();
+ final StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+ final List<String> list = new ArrayList<>();
+ boolean traceStarted = false;
+ while (frames.hasMoreTokens()) {
+ final String token = frames.nextToken();
+ // Determine if the line starts with <whitespace>at
+ final int at = token.indexOf("at");
+ if (at != -1 && token.substring(0, at).trim().isEmpty()) {
+ traceStarted = true;
+ list.add(token);
+ } else if (traceStarted) {
+ break;
+ }
+ }
+ return list;
}
+ //-----------------------------------------------------------------------
/**
- * <p>Returns the (zero-based) index of the first <code>Throwable</code>
- * that matches the specified type in the exception chain from
- * a specified index.
- * Subclasses of the specified class do not match - see
- * {@link #indexOfType(Throwable, Class, int)} for the opposite.</p>
+ * <p>Returns an array where each element is a line from the argument.</p>
*
- * <p>A <code>null</code> throwable returns <code>-1</code>.
- * A <code>null</code> type returns <code>-1</code>.
- * No match in the chain returns <code>-1</code>.
- * A negative start index is treated as zero.
- * A start index greater than the number of throwables returns <code>-1</code>.</p>
+ * <p>The end of line is determined by the value of {@link System#lineSeparator()}.</p>
*
- * @param throwable the throwable to inspect, may be null
- * @param clazz the class to search for, subclasses do not match, null returns -1
- * @param fromIndex the (zero-based) index of the starting position,
- * negative treated as zero, larger than chain size returns -1
- * @return the index into the throwable chain, -1 if no match or null input
+ * @param stackTrace a stack trace String
+ * @return an array where each element is a line from the argument
*/
- public static int indexOfThrowable(final Throwable throwable, final Class<?> clazz, final int fromIndex) {
- return indexOf(throwable, clazz, fromIndex, false);
- }
-
+ static String[] getStackFrames(final String stackTrace) {
+ final String linebreak = System.lineSeparator();
+ final StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+ final List<String> list = new ArrayList<>();
+ while (frames.hasMoreTokens()) {
+ list.add(frames.nextToken());
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
/**
- * <p>Returns the first <code>Throwable</code>
- * that matches the specified type in the exception chain from
- * a specified index.
- * Subclasses of the specified class do not match - see
- * {@link #throwableOfType(Throwable, Class, int)} for the opposite.</p>
+ * <p>Captures the stack trace associated with the specified
+ * <code>Throwable</code> object, decomposing it into a list of
+ * stack frames.</p>
*
- * <p>A <code>null</code> throwable returns <code>null</code>.
- * A <code>null</code> type returns <code>null</code>.
- * No match in the chain returns <code>null</code>.
- * A negative start index is treated as zero.
- * A start index greater than the number of throwables returns <code>null</code>.</p>
+ * <p>The result of this method vary by JDK version as this method
+ * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
+ * On JDK1.3 and earlier, the cause exception will not be shown
+ * unless the specified throwable alters printStackTrace.</p>
*
- * @param <T> the type of Throwable you are searching.
- * @param throwable the throwable to inspect, may be null
- * @param clazz the class to search for, subclasses do not match, null returns null
- * @param fromIndex the (zero-based) index of the starting position,
- * negative treated as zero, larger than chain size returns null
- * @return the index into the throwable chain, null if no match or null input
- * @since 3.10
+ * @param throwable the <code>Throwable</code> to examine, may be null
+ * @return an array of strings describing each stack frame, never null
*/
- public static <T extends Throwable> T throwableOfThrowable(final Throwable throwable, final Class<T> clazz, final int fromIndex) {
- return throwableOf(throwable, clazz, fromIndex, false);
+ public static String[] getStackFrames(final Throwable throwable) {
+ if (throwable == null) {
+ return ArrayUtils.EMPTY_STRING_ARRAY;
+ }
+ return getStackFrames(getStackTrace(throwable));
}
-
+
+ //-----------------------------------------------------------------------
/**
- * <p>Returns the (zero-based) index of the first <code>Throwable</code>
- * that matches the specified class or subclass in the exception chain.
- * Subclasses of the specified class do match - see
- * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
+ * <p>Gets the stack trace from a Throwable as a String.</p>
*
- * <p>A <code>null</code> throwable returns <code>-1</code>.
- * A <code>null</code> type returns <code>-1</code>.
- * No match in the chain returns <code>-1</code>.</p>
+ * <p>The result of this method vary by JDK version as this method
+ * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
+ * On JDK1.3 and earlier, the cause exception will not be shown
+ * unless the specified throwable alters printStackTrace.</p>
*
- * @param throwable the throwable to inspect, may be null
- * @param type the type to search for, subclasses match, null returns -1
- * @return the index into the throwable chain, -1 if no match or null input
- * @since 2.1
+ * @param throwable the <code>Throwable</code> to be examined
+ * @return the stack trace as generated by the exception's
+ * <code>printStackTrace(PrintWriter)</code> method
*/
- public static int indexOfType(final Throwable throwable, final Class<?> type) {
- return indexOf(throwable, type, 0, true);
+ public static String getStackTrace(final Throwable throwable) {
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw, true);
+ throwable.printStackTrace(pw);
+ return sw.getBuffer().toString();
}
+ //-----------------------------------------------------------------------
/**
- * <p>Returns the throwable of the first <code>Throwable</code>
- * that matches the specified class or subclass in the exception chain.
- * Subclasses of the specified class do match - see
- * {@link #throwableOfThrowable(Throwable, Class)} for the opposite..</p>
+ * <p>Counts the number of <code>Throwable</code> objects in the
+ * exception chain.</p>
*
- * <p>A <code>null</code> throwable returns <code>null</code>.
- * A <code>null</code> type returns <code>null</code>.
- * No match in the chain returns <code>null</code>.</p>
+ * <p>A throwable without cause will return <code>1</code>.
+ * A throwable with one cause will return <code>2</code> and so on.
+ * A <code>null</code> throwable will return <code>0</code>.</p>
+ *
+ * <p>From version 2.2, this method handles recursive cause structures
+ * that might otherwise cause infinite loops. The cause chain is
+ * processed until the end is reached, or until the next item in the
+ * chain is already in the result set.</p>
*
- * @param <T> the type of Throwable you are searching.
* @param throwable the throwable to inspect, may be null
- * @param type the type to search for, subclasses match, null returns null
- * @return the index into the throwable chain, null if no match or null input
- * @since 3.10
+ * @return the count of throwables, zero if null input
*/
- public static <T extends Throwable> T throwableOfType(final Throwable throwable, final Class<T> type) {
- return throwableOf(throwable, type, 0, true);
+ public static int getThrowableCount(final Throwable throwable) {
+ return getThrowableList(throwable).size();
}
-
+
/**
- * <p>Returns the first <code>Throwable</code>
- * that matches the specified type in the exception chain from
- * a specified index.
- * Subclasses of the specified class do match - see
- * {@link #throwableOfThrowable(Throwable, Class)} for the opposite.</p>
+ * <p>Returns the list of <code>Throwable</code> objects in the
+ * exception chain.</p>
*
- * <p>A <code>null</code> throwable returns <code>null</code>.
- * A <code>null</code> type returns <code>null</code>.
- * No match in the chain returns <code>null</code>.
- * A negative start index is treated as zero.
- * A start index greater than the number of throwables returns <code>null</code>.</p>
+ * <p>A throwable without cause will return a list containing
+ * one element - the input throwable.
+ * A throwable with one cause will return a list containing
+ * two elements. - the input throwable and the cause throwable.
+ * A <code>null</code> throwable will return a list of size zero.</p>
+ *
+ * <p>This method handles recursive cause structures that might
+ * otherwise cause infinite loops. The cause chain is processed until
+ * the end is reached, or until the next item in the chain is already
+ * in the result set.</p>
*
- * @param <T> the type of Throwable you are searching.
* @param throwable the throwable to inspect, may be null
- * @param type the type to search for, subclasses match, null returns null
- * @param fromIndex the (zero-based) index of the starting position,
- * negative treated as zero, larger than chain size returns null
- * @return the index into the throwable chain, null if no match or null input
- * @since 3.10
+ * @return the list of throwables, never null
+ * @since 2.2
*/
- public static <T extends Throwable> T throwableOfType(final Throwable throwable, final Class<T> type, final int fromIndex) {
- return throwableOf(throwable, type, fromIndex, true);
+ public static List<Throwable> getThrowableList(Throwable throwable) {
+ final List<Throwable> list = new ArrayList<>();
+ while (throwable != null && !list.contains(throwable)) {
+ list.add(throwable);
+ throwable = throwable.getCause();
+ }
+ return list;
}
/**
- * <p>Returns the (zero-based) index of the first <code>Throwable</code>
- * that matches the specified type in the exception chain from
- * a specified index.
- * Subclasses of the specified class do match - see
- * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
+ * <p>Returns the list of <code>Throwable</code> objects in the
+ * exception chain.</p>
*
- * <p>A <code>null</code> throwable returns <code>-1</code>.
- * A <code>null</code> type returns <code>-1</code>.
- * No match in the chain returns <code>-1</code>.
- * A negative start index is treated as zero.
- * A start index greater than the number of throwables returns <code>-1</code>.</p>
+ * <p>A throwable without cause will return an array containing
+ * one element - the input throwable.
+ * A throwable with one cause will return an array containing
+ * two elements. - the input throwable and the cause throwable.
+ * A <code>null</code> throwable will return an array of size zero.</p>
*
+ * <p>From version 2.2, this method handles recursive cause structures
+ * that might otherwise cause infinite loops. The cause chain is
+ * processed until the end is reached, or until the next item in the
+ * chain is already in the result set.</p>
+ *
+ * @see #getThrowableList(Throwable)
* @param throwable the throwable to inspect, may be null
- * @param type the type to search for, subclasses match, null returns -1
- * @param fromIndex the (zero-based) index of the starting position,
- * negative treated as zero, larger than chain size returns -1
- * @return the index into the throwable chain, -1 if no match or null input
- * @since 2.1
+ * @return the array of throwables, never null
*/
- public static int indexOfType(final Throwable throwable, final Class<?> type, final int fromIndex) {
- return indexOf(throwable, type, fromIndex, true);
+ public static Throwable[] getThrowables(final Throwable throwable) {
+ final List<Throwable> list = getThrowableList(throwable);
+ return list.toArray(new Throwable[list.size()]);
+ }
+
+ /**
+ * Does the throwable's causal chain have an immediate or wrapped exception
+ * of the given type?
+ *
+ * @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.
+ * @since 3.5
+ * @see #wrapAndThrow(Throwable)
+ */
+ public static boolean hasCause(Throwable chain,
+ final Class<? extends Throwable> type) {
+ if (chain instanceof UndeclaredThrowableException) {
+ chain = chain.getCause();
+ }
+ return type.isInstance(chain);
}
/**
@@ -498,42 +501,87 @@ public class ExceptionUtils {
}
/**
- * <p>Worker method for the <code>throwableOfType</code> methods.</p>
+ * <p>Returns the (zero-based) index of the first <code>Throwable</code>
+ * that matches the specified class (exactly) in the exception chain.
+ * Subclasses of the specified class do not match - see
+ * {@link #indexOfType(Throwable, Class)} for the opposite.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>-1</code>.
+ * A <code>null</code> type returns <code>-1</code>.
+ * No match in the chain returns <code>-1</code>.</p>
*
- * @param <T> the type of Throwable you are searching.
* @param throwable the throwable to inspect, may be null
- * @param type the type to search, subclasses match, null returns null
+ * @param clazz the class to search for, subclasses do not match, null returns -1
+ * @return the index into the throwable chain, -1 if no match or null input
+ */
+ public static int indexOfThrowable(final Throwable throwable, final Class<?> clazz) {
+ return indexOf(throwable, clazz, 0, false);
+ }
+
+ /**
+ * <p>Returns the (zero-based) index of the first <code>Throwable</code>
+ * that matches the specified type in the exception chain from
+ * a specified index.
+ * Subclasses of the specified class do not match - see
+ * {@link #indexOfType(Throwable, Class, int)} for the opposite.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>-1</code>.
+ * A <code>null</code> type returns <code>-1</code>.
+ * No match in the chain returns <code>-1</code>.
+ * A negative start index is treated as zero.
+ * A start index greater than the number of throwables returns <code>-1</code>.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param clazz the class to search for, subclasses do not match, null returns -1
* @param fromIndex the (zero-based) index of the starting position,
- * negative treated as zero, larger than chain size returns null
- * @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
- * using references
- * @return throwable of the <code>type</code> within throwables nested within the specified <code>throwable</code>
+ * negative treated as zero, larger than chain size returns -1
+ * @return the index into the throwable chain, -1 if no match or null input
*/
- private static <T extends Throwable> T throwableOf(final Throwable throwable, final Class<T> type, int fromIndex, final boolean subclass) {
- if (throwable == null || type == null) {
- return null;
- }
- if (fromIndex < 0) {
- fromIndex = 0;
- }
- final Throwable[] throwables = getThrowables(throwable);
- if (fromIndex >= throwables.length) {
- return null;
- }
- if (subclass) {
- for (int i = fromIndex; i < throwables.length; i++) {
- if (type.isAssignableFrom(throwables[i].getClass())) {
- return type.cast(throwables[i]);
- }
- }
- } else {
- for (int i = fromIndex; i < throwables.length; i++) {
- if (type.equals(throwables[i].getClass())) {
- return type.cast(throwables[i]);
- }
- }
- }
- return null;
+ public static int indexOfThrowable(final Throwable throwable, final Class<?> clazz, final int fromIndex) {
+ return indexOf(throwable, clazz, fromIndex, false);
+ }
+
+ /**
+ * <p>Returns the (zero-based) index of the first <code>Throwable</code>
+ * that matches the specified class or subclass in the exception chain.
+ * Subclasses of the specified class do match - see
+ * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>-1</code>.
+ * A <code>null</code> type returns <code>-1</code>.
+ * No match in the chain returns <code>-1</code>.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, subclasses match, null returns -1
+ * @return the index into the throwable chain, -1 if no match or null input
+ * @since 2.1
+ */
+ public static int indexOfType(final Throwable throwable, final Class<?> type) {
+ return indexOf(throwable, type, 0, true);
+ }
+
+ /**
+ * <p>Returns the (zero-based) index of the first <code>Throwable</code>
+ * that matches the specified type in the exception chain from
+ * a specified index.
+ * Subclasses of the specified class do match - see
+ * {@link #indexOfThrowable(Throwable, Class)} for the opposite.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>-1</code>.
+ * A <code>null</code> type returns <code>-1</code>.
+ * No match in the chain returns <code>-1</code>.
+ * A negative start index is treated as zero.
+ * A start index greater than the number of throwables returns <code>-1</code>.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, subclasses match, null returns -1
+ * @param fromIndex the (zero-based) index of the starting position,
+ * negative treated as zero, larger than chain size returns -1
+ * @return the index into the throwable chain, -1 if no match or null input
+ * @since 2.1
+ */
+ public static int indexOfType(final Throwable throwable, final Class<?> type, final int fromIndex) {
+ return indexOf(throwable, type, fromIndex, true);
}
//-----------------------------------------------------------------------
@@ -585,233 +633,67 @@ public class ExceptionUtils {
Validate.isTrue(stream != null, "The PrintStream must not be null");
final String trace[] = getRootCauseStackTrace(throwable);
for (final String element : trace) {
- stream.println(element);
- }
- stream.flush();
- }
-
- /**
- * <p>Prints a compact stack trace for the root cause of a throwable.</p>
- *
- * <p>The compact stack trace starts with the root cause and prints
- * stack frames up to the place where it was caught and wrapped.
- * Then it prints the wrapped exception and continues with stack frames
- * until the wrapper exception is caught and wrapped again, etc.</p>
- *
- * <p>The output of this method is consistent across JDK versions.
- * Note that this is the opposite order to the JDK1.4 display.</p>
- *
- * <p>The method is equivalent to <code>printStackTrace</code> for throwables
- * that don't have nested causes.</p>
- *
- * @param throwable the throwable to output, may be null
- * @param writer the writer to output to, may not be null
- * @throws IllegalArgumentException if the writer is <code>null</code>
- * @since 2.0
- */
- public static void printRootCauseStackTrace(final Throwable throwable, final PrintWriter writer) {
- if (throwable == null) {
- return;
- }
- Validate.isTrue(writer != null, "The PrintWriter must not be null");
- final String trace[] = getRootCauseStackTrace(throwable);
- for (final String element : trace) {
- writer.println(element);
- }
- writer.flush();
- }
-
- //-----------------------------------------------------------------------
- /**
- * <p>Creates a compact stack trace for the root cause of the supplied
- * <code>Throwable</code>.</p>
- *
- * <p>The output of this method is consistent across JDK versions.
- * It consists of the root exception followed by each of its wrapping
- * exceptions separated by '[wrapped]'. Note that this is the opposite
- * order to the JDK1.4 display.</p>
- *
- * @param throwable the throwable to examine, may be null
- * @return an array of stack trace frames, never null
- * @since 2.0
- */
- public static String[] getRootCauseStackTrace(final Throwable throwable) {
- if (throwable == null) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
- final Throwable throwables[] = getThrowables(throwable);
- final int count = throwables.length;
- final List<String> frames = new ArrayList<>();
- List<String> nextTrace = getStackFrameList(throwables[count - 1]);
- for (int i = count; --i >= 0;) {
- final List<String> trace = nextTrace;
- if (i != 0) {
- nextTrace = getStackFrameList(throwables[i - 1]);
- removeCommonFrames(trace, nextTrace);
- }
- if (i == count - 1) {
- frames.add(throwables[i].toString());
- } else {
- frames.add(WRAPPED_MARKER + throwables[i].toString());
- }
- frames.addAll(trace);
- }
- return frames.toArray(new String[frames.size()]);
- }
-
- /**
- * <p>Removes common frames from the cause trace given the two stack traces.</p>
- *
- * @param causeFrames stack trace of a cause throwable
- * @param wrapperFrames stack trace of a wrapper throwable
- * @throws IllegalArgumentException if either argument is null
- * @since 2.0
- */
- public static void removeCommonFrames(final List<String> causeFrames, final List<String> wrapperFrames) {
- if (causeFrames == null || wrapperFrames == null) {
- throw new IllegalArgumentException("The List must not be null");
- }
- int causeFrameIndex = causeFrames.size() - 1;
- int wrapperFrameIndex = wrapperFrames.size() - 1;
- while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
- // Remove the frame from the cause trace if it is the same
- // as in the wrapper trace
- final String causeFrame = causeFrames.get(causeFrameIndex);
- final String wrapperFrame = wrapperFrames.get(wrapperFrameIndex);
- if (causeFrame.equals(wrapperFrame)) {
- causeFrames.remove(causeFrameIndex);
- }
- causeFrameIndex--;
- wrapperFrameIndex--;
- }
- }
-
- //-----------------------------------------------------------------------
- /**
- * <p>Gets the stack trace from a Throwable as a String.</p>
- *
- * <p>The result of this method vary by JDK version as this method
- * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
- * On JDK1.3 and earlier, the cause exception will not be shown
- * unless the specified throwable alters printStackTrace.</p>
- *
- * @param throwable the <code>Throwable</code> to be examined
- * @return the stack trace as generated by the exception's
- * <code>printStackTrace(PrintWriter)</code> method
- */
- public static String getStackTrace(final Throwable throwable) {
- final StringWriter sw = new StringWriter();
- final PrintWriter pw = new PrintWriter(sw, true);
- throwable.printStackTrace(pw);
- return sw.getBuffer().toString();
- }
-
- /**
- * <p>Captures the stack trace associated with the specified
- * <code>Throwable</code> object, decomposing it into a list of
- * stack frames.</p>
- *
- * <p>The result of this method vary by JDK version as this method
- * uses {@link Throwable#printStackTrace(java.io.PrintWriter)}.
- * On JDK1.3 and earlier, the cause exception will not be shown
- * unless the specified throwable alters printStackTrace.</p>
- *
- * @param throwable the <code>Throwable</code> to examine, may be null
- * @return an array of strings describing each stack frame, never null
- */
- public static String[] getStackFrames(final Throwable throwable) {
- if (throwable == null) {
- return ArrayUtils.EMPTY_STRING_ARRAY;
- }
- return getStackFrames(getStackTrace(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 System#lineSeparator()}.</p>
- *
- * @param stackTrace a stack trace String
- * @return an array where each element is a line from the argument
- */
- static String[] getStackFrames(final String stackTrace) {
- final String linebreak = System.lineSeparator();
- final StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
- final List<String> list = new ArrayList<>();
- while (frames.hasMoreTokens()) {
- list.add(frames.nextToken());
+ stream.println(element);
}
- return list.toArray(new String[list.size()]);
+ stream.flush();
}
/**
- * <p>Produces a <code>List</code> of stack frames - the message
- * is not included. Only the trace of the specified exception is
- * returned, any caused by trace is stripped.</p>
+ * <p>Prints a compact stack trace for the root cause of a throwable.</p>
*
- * <p>This works in most cases - it will only fail if the exception
- * message contains a line that starts with:
- * <code>" at".</code></p>
+ * <p>The compact stack trace starts with the root cause and prints
+ * stack frames up to the place where it was caught and wrapped.
+ * Then it prints the wrapped exception and continues with stack frames
+ * until the wrapper exception is caught and wrapped again, etc.</p>
*
- * @param t is any throwable
- * @return List of stack frames
- */
- static List<String> getStackFrameList(final Throwable t) {
- final String stackTrace = getStackTrace(t);
- final String linebreak = System.lineSeparator();
- final StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
- final List<String> list = new ArrayList<>();
- boolean traceStarted = false;
- while (frames.hasMoreTokens()) {
- final String token = frames.nextToken();
- // Determine if the line starts with <whitespace>at
- final int at = token.indexOf("at");
- if (at != -1 && token.substring(0, at).trim().isEmpty()) {
- traceStarted = true;
- list.add(token);
- } else if (traceStarted) {
- break;
- }
- }
- return list;
- }
-
- //-----------------------------------------------------------------------
- /**
- * Gets a short message summarising the exception.
- * <p>
- * The message returned is of the form
- * {ClassNameWithoutPackage}: {ThrowableMessage}
+ * <p>The output of this method is consistent across JDK versions.
+ * Note that this is the opposite order to the JDK1.4 display.</p>
*
- * @param th the throwable to get a message for, null returns empty string
- * @return the message, non-null
- * @since 2.2
+ * <p>The method is equivalent to <code>printStackTrace</code> for throwables
+ * that don't have nested causes.</p>
+ *
+ * @param throwable the throwable to output, may be null
+ * @param writer the writer to output to, may not be null
+ * @throws IllegalArgumentException if the writer is <code>null</code>
+ * @since 2.0
*/
- public static String getMessage(final Throwable th) {
- if (th == null) {
- return StringUtils.EMPTY;
+ public static void printRootCauseStackTrace(final Throwable throwable, final PrintWriter writer) {
+ if (throwable == null) {
+ return;
}
- final String clsName = ClassUtils.getShortClassName(th, null);
- final String msg = th.getMessage();
- return clsName + ": " + StringUtils.defaultString(msg);
+ Validate.isTrue(writer != null, "The PrintWriter must not be null");
+ final String trace[] = getRootCauseStackTrace(throwable);
+ for (final String element : trace) {
+ writer.println(element);
+ }
+ writer.flush();
}
- //-----------------------------------------------------------------------
/**
- * Gets a short message summarising the root cause exception.
- * <p>
- * The message returned is of the form
- * {ClassNameWithoutPackage}: {ThrowableMessage}
+ * <p>Removes common frames from the cause trace given the two stack traces.</p>
*
- * @param th the throwable to get a message for, null returns empty string
- * @return the message, non-null
- * @since 2.2
+ * @param causeFrames stack trace of a cause throwable
+ * @param wrapperFrames stack trace of a wrapper throwable
+ * @throws IllegalArgumentException if either argument is null
+ * @since 2.0
*/
- public static String getRootCauseMessage(final Throwable th) {
- Throwable root = getRootCause(th);
- root = root == null ? th : root;
- return getMessage(root);
+ public static void removeCommonFrames(final List<String> causeFrames, final List<String> wrapperFrames) {
+ if (causeFrames == null || wrapperFrames == null) {
+ throw new IllegalArgumentException("The List must not be null");
+ }
+ int causeFrameIndex = causeFrames.size() - 1;
+ int wrapperFrameIndex = wrapperFrames.size() - 1;
+ while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
+ // Remove the frame from the cause trace if it is the same
+ // as in the wrapper trace
+ final String causeFrame = causeFrames.get(causeFrameIndex);
+ final String wrapperFrame = wrapperFrames.get(wrapperFrameIndex);
+ if (causeFrame.equals(wrapperFrame)) {
+ causeFrames.remove(causeFrameIndex);
+ }
+ causeFrameIndex--;
+ wrapperFrameIndex--;
+ }
}
/**
@@ -875,6 +757,135 @@ public class ExceptionUtils {
}
/**
+ * <p>Worker method for the <code>throwableOfType</code> methods.</p>
+ *
+ * @param <T> the type of Throwable you are searching.
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search, subclasses match, null returns null
+ * @param fromIndex the (zero-based) index of the starting position,
+ * negative treated as zero, larger than chain size returns null
+ * @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
+ * using references
+ * @return throwable of the <code>type</code> within throwables nested within the specified <code>throwable</code>
+ */
+ private static <T extends Throwable> T throwableOf(final Throwable throwable, final Class<T> type, int fromIndex, final boolean subclass) {
+ if (throwable == null || type == null) {
+ return null;
+ }
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ }
+ final Throwable[] throwables = getThrowables(throwable);
+ if (fromIndex >= throwables.length) {
+ return null;
+ }
+ if (subclass) {
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (type.isAssignableFrom(throwables[i].getClass())) {
+ return type.cast(throwables[i]);
+ }
+ }
+ } else {
+ for (int i = fromIndex; i < throwables.length; i++) {
+ if (type.equals(throwables[i].getClass())) {
+ return type.cast(throwables[i]);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * <p>Returns the first <code>Throwable</code>
+ * that matches the specified class (exactly) in the exception chain.
+ * Subclasses of the specified class do not match - see
+ * {@link #throwableOfType(Throwable, Class)} for the opposite.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>null</code>.
+ * A <code>null</code> type returns <code>null</code>.
+ * No match in the chain returns <code>null</code>.</p>
+ *
+ * @param <T> the type of Throwable you are searching.
+ * @param throwable the throwable to inspect, may be null
+ * @param clazz the class to search for, subclasses do not match, null returns null
+ * @return the index into the throwable chain, null if no match or null input
+ * @since 3.10
+ */
+ public static <T extends Throwable> T throwableOfThrowable(final Throwable throwable, final Class<T> clazz) {
+ return throwableOf(throwable, clazz, 0, false);
+ }
+
+ /**
+ * <p>Returns the first <code>Throwable</code>
+ * that matches the specified type in the exception chain from
+ * a specified index.
+ * Subclasses of the specified class do not match - see
+ * {@link #throwableOfType(Throwable, Class, int)} for the opposite.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>null</code>.
+ * A <code>null</code> type returns <code>null</code>.
+ * No match in the chain returns <code>null</code>.
+ * A negative start index is treated as zero.
+ * A start index greater than the number of throwables returns <code>null</code>.</p>
+ *
+ * @param <T> the type of Throwable you are searching.
+ * @param throwable the throwable to inspect, may be null
+ * @param clazz the class to search for, subclasses do not match, null returns null
+ * @param fromIndex the (zero-based) index of the starting position,
+ * negative treated as zero, larger than chain size returns null
+ * @return the index into the throwable chain, null if no match or null input
+ * @since 3.10
+ */
+ public static <T extends Throwable> T throwableOfThrowable(final Throwable throwable, final Class<T> clazz, final int fromIndex) {
+ return throwableOf(throwable, clazz, fromIndex, false);
+ }
+
+ /**
+ * <p>Returns the throwable of the first <code>Throwable</code>
+ * that matches the specified class or subclass in the exception chain.
+ * Subclasses of the specified class do match - see
+ * {@link #throwableOfThrowable(Throwable, Class)} for the opposite..</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>null</code>.
+ * A <code>null</code> type returns <code>null</code>.
+ * No match in the chain returns <code>null</code>.</p>
+ *
+ * @param <T> the type of Throwable you are searching.
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, subclasses match, null returns null
+ * @return the index into the throwable chain, null if no match or null input
+ * @since 3.10
+ */
+ public static <T extends Throwable> T throwableOfType(final Throwable throwable, final Class<T> type) {
+ return throwableOf(throwable, type, 0, true);
+ }
+
+ /**
+ * <p>Returns the first <code>Throwable</code>
+ * that matches the specified type in the exception chain from
+ * a specified index.
+ * Subclasses of the specified class do match - see
+ * {@link #throwableOfThrowable(Throwable, Class)} for the opposite.</p>
+ *
+ * <p>A <code>null</code> throwable returns <code>null</code>.
+ * A <code>null</code> type returns <code>null</code>.
+ * No match in the chain returns <code>null</code>.
+ * A negative start index is treated as zero.
+ * A start index greater than the number of throwables returns <code>null</code>.</p>
+ *
+ * @param <T> the type of Throwable you are searching.
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, subclasses match, null returns null
+ * @param fromIndex the (zero-based) index of the starting position,
+ * negative treated as zero, larger than chain size returns null
+ * @return the index into the throwable chain, null if no match or null input
+ * @since 3.10
+ */
+ public static <T extends Throwable> T throwableOfType(final Throwable throwable, final Class<T> type, final int fromIndex) {
+ return throwableOf(throwable, type, fromIndex, true);
+ }
+
+ /**
* Claim a Throwable is another Exception type using type erasure. This
* hides a checked exception from the java compiler, allowing a checked
* exception to be thrown without having the exception in the method's throw
@@ -917,23 +928,12 @@ public class ExceptionUtils {
}
/**
- * Does the throwable's causal chain have an immediate or wrapped exception
- * of the given type?
- *
- * @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.
- * @since 3.5
- * @see #wrapAndThrow(Throwable)
+ * <p>
+ * Public constructor allows an instance of <code>ExceptionUtils</code> to be created, although that is not
+ * normally necessary.
+ * </p>
*/
- public static boolean hasCause(Throwable chain,
- final Class<? extends Throwable> type) {
- if (chain instanceof UndeclaredThrowableException) {
- chain = chain.getCause();
- }
- return type.isInstance(chain);
+ public ExceptionUtils() {
+ super();
}
}
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 ad57dcb..30e7cb3 100644
--- a/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/exception/ExceptionUtilsTest.java
@@ -44,13 +44,112 @@ import org.junit.jupiter.api.Test;
*/
public class ExceptionUtilsTest {
+ /**
+ * Provides a method with a well known chained/nested exception
+ * name which matches the full signature (e.g. has a return value
+ * of <code>Throwable</code>.
+ */
+ private static class ExceptionWithCause extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ private Throwable cause;
+
+ ExceptionWithCause(final String str, final Throwable cause) {
+ super(str);
+ setCause(cause);
+ }
+
+ ExceptionWithCause(final Throwable cause) {
+ super();
+ setCause(cause);
+ }
+
+ @Override
+ public Throwable getCause() {
+ return cause;
+ }
+
+ public void setCause(final Throwable cause) {
+ this.cause = cause;
+ }
+ }
+ /**
+ * Provides a method with a well known chained/nested exception
+ * name which does not match the full signature (e.g. lacks a
+ * return value of <code>Throwable</code>.
+ */
+ private static class ExceptionWithoutCause extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings("unused")
+ public void getTargetException() {
+ // noop
+ }
+ }
+ // Temporary classes to allow the nested exception code to be removed
+ // prior to a rewrite of this test class.
+ private static class NestableException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings("unused")
+ NestableException() {
+ super();
+ }
+
+ NestableException(final Throwable t) {
+ super(t);
+ }
+ }
+ public static class TestThrowable extends Throwable {
+ private static final long serialVersionUID = 1L;
+ }
+ private static int redeclareCheckedException() {
+ return throwsCheckedException();
+ }
+ private static int throwsCheckedException() {
+ try {
+ throw new IOException();
+ } catch (final Exception e) {
+ return ExceptionUtils.<Integer>rethrow(e);
+ }
+ }
+
+
private NestableException nested;
+
+
private Throwable withCause;
+
private Throwable withoutCause;
+
private Throwable jdkNoCause;
+
+ //-----------------------------------------------------------------------
+
private ExceptionWithCause cyclicCause;
+
private Throwable notVisibleException;
+ private Throwable createExceptionWithCause() {
+ try {
+ try {
+ throw new ExceptionWithCause(createExceptionWithoutCause());
+ } catch (final Throwable t) {
+ throw new ExceptionWithCause(t);
+ }
+ } catch (final Throwable t) {
+ return t;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ private Throwable createExceptionWithoutCause() {
+ try {
+ throw new ExceptionWithoutCause();
+ } catch (final Throwable t) {
+ return t;
+ }
+ }
@BeforeEach
public void setUp() {
@@ -65,7 +164,6 @@ public class ExceptionUtilsTest {
notVisibleException = NotVisibleExceptionFactory.createException(withoutCause);
}
-
@AfterEach
public void tearDown() {
withoutCause = null;
@@ -76,28 +174,38 @@ public class ExceptionUtilsTest {
notVisibleException = null;
}
- //-----------------------------------------------------------------------
- private Throwable createExceptionWithoutCause() {
- try {
- throw new ExceptionWithoutCause();
- } catch (final Throwable t) {
- return t;
- }
+ @Test
+ public void test_getMessage_Throwable() {
+ Throwable th = null;
+ assertEquals("", ExceptionUtils.getMessage(th));
+
+ th = new IllegalArgumentException("Base");
+ assertEquals("IllegalArgumentException: Base", ExceptionUtils.getMessage(th));
+
+ th = new ExceptionWithCause("Wrapper", th);
+ assertEquals("ExceptionUtilsTest.ExceptionWithCause: Wrapper", ExceptionUtils.getMessage(th));
}
- private Throwable createExceptionWithCause() {
- try {
- try {
- throw new ExceptionWithCause(createExceptionWithoutCause());
- } catch (final Throwable t) {
- throw new ExceptionWithCause(t);
- }
- } catch (final Throwable t) {
- return t;
- }
+ @Test
+ public void test_getRootCauseMessage_Throwable() {
+ Throwable th = null;
+ assertEquals("", ExceptionUtils.getRootCauseMessage(th));
+
+ th = new IllegalArgumentException("Base");
+ assertEquals("IllegalArgumentException: Base", ExceptionUtils.getRootCauseMessage(th));
+
+ th = new ExceptionWithCause("Wrapper", th);
+ assertEquals("IllegalArgumentException: Base", ExceptionUtils.getRootCauseMessage(th));
}
- //-----------------------------------------------------------------------
+ @Test
+ public void testCatchTechniques() {
+ IOException ioe = assertThrows(IOException.class, ExceptionUtilsTest::throwsCheckedException);
+ assertEquals(1, ExceptionUtils.getThrowableCount(ioe));
+
+ ioe = assertThrows(IOException.class, ExceptionUtilsTest::redeclareCheckedException);
+ assertEquals(1, ExceptionUtils.getThrowableCount(ioe));
+ }
@Test
public void testConstructor() {
@@ -156,6 +264,33 @@ public class ExceptionUtilsTest {
//-----------------------------------------------------------------------
@Test
+ public void testGetRootCauseStackTrace_Throwable() {
+ assertEquals(0, ExceptionUtils.getRootCauseStackTrace(null).length);
+
+ final Throwable cause = createExceptionWithCause();
+ String[] stackTrace = ExceptionUtils.getRootCauseStackTrace(cause);
+ boolean match = false;
+ for (final String element : stackTrace) {
+ if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) {
+ match = true;
+ break;
+ }
+ }
+ assertTrue(match);
+
+ stackTrace = ExceptionUtils.getRootCauseStackTrace(withoutCause);
+ match = false;
+ for (final String element : stackTrace) {
+ if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) {
+ match = true;
+ break;
+ }
+ }
+ assertFalse(match);
+ }
+
+ //-----------------------------------------------------------------------
+ @Test
public void testGetThrowableCount_Throwable() {
assertEquals(0, ExceptionUtils.getThrowableCount(null));
assertEquals(1, ExceptionUtils.getThrowableCount(withoutCause));
@@ -165,34 +300,51 @@ public class ExceptionUtilsTest {
assertEquals(3, ExceptionUtils.getThrowableCount(cyclicCause));
}
+ @Test
+ public void testGetThrowableList_Throwable_jdkNoCause() {
+ final List<?> throwables = ExceptionUtils.getThrowableList(jdkNoCause);
+ assertEquals(1, throwables.size());
+ assertSame(jdkNoCause, throwables.get(0));
+ }
+
+ @Test
+ public void testGetThrowableList_Throwable_nested() {
+ final List<?> throwables = ExceptionUtils.getThrowableList(nested);
+ assertEquals(2, throwables.size());
+ assertSame(nested, throwables.get(0));
+ assertSame(withoutCause, throwables.get(1));
+ }
+
//-----------------------------------------------------------------------
@Test
- public void testGetThrowables_Throwable_null() {
- assertEquals(0, ExceptionUtils.getThrowables(null).length);
+ public void testGetThrowableList_Throwable_null() {
+ final List<?> throwables = ExceptionUtils.getThrowableList(null);
+ assertEquals(0, throwables.size());
}
@Test
- public void testGetThrowables_Throwable_withoutCause() {
- final Throwable[] throwables = ExceptionUtils.getThrowables(withoutCause);
- assertEquals(1, throwables.length);
- assertSame(withoutCause, throwables[0]);
+ public void testGetThrowableList_Throwable_recursiveCause() {
+ final List<?> throwables = ExceptionUtils.getThrowableList(cyclicCause);
+ assertEquals(3, throwables.size());
+ assertSame(cyclicCause, throwables.get(0));
+ assertSame(cyclicCause.getCause(), throwables.get(1));
+ assertSame(cyclicCause.getCause().getCause(), throwables.get(2));
}
@Test
- public void testGetThrowables_Throwable_nested() {
- final Throwable[] throwables = ExceptionUtils.getThrowables(nested);
- assertEquals(2, throwables.length);
- assertSame(nested, throwables[0]);
- assertSame(withoutCause, throwables[1]);
+ public void testGetThrowableList_Throwable_withCause() {
+ final List<?> throwables = ExceptionUtils.getThrowableList(withCause);
+ assertEquals(3, throwables.size());
+ assertSame(withCause, throwables.get(0));
+ assertSame(nested, throwables.get(1));
+ assertSame(withoutCause, throwables.get(2));
}
@Test
- public void testGetThrowables_Throwable_withCause() {
- final Throwable[] throwables = ExceptionUtils.getThrowables(withCause);
- assertEquals(3, throwables.length);
- assertSame(withCause, throwables[0]);
- assertSame(nested, throwables[1]);
- assertSame(withoutCause, throwables[2]);
+ public void testGetThrowableList_Throwable_withoutCause() {
+ final List<?> throwables = ExceptionUtils.getThrowableList(withoutCause);
+ assertEquals(1, throwables.size());
+ assertSame(withoutCause, throwables.get(0));
}
@Test
@@ -203,6 +355,20 @@ public class ExceptionUtilsTest {
}
@Test
+ public void testGetThrowables_Throwable_nested() {
+ final Throwable[] throwables = ExceptionUtils.getThrowables(nested);
+ assertEquals(2, throwables.length);
+ assertSame(nested, throwables[0]);
+ assertSame(withoutCause, throwables[1]);
+ }
+
+ //-----------------------------------------------------------------------
+ @Test
+ public void testGetThrowables_Throwable_null() {
+ assertEquals(0, ExceptionUtils.getThrowables(null).length);
+ }
+
+ @Test
public void testGetThrowables_Throwable_recursiveCause() {
final Throwable[] throwables = ExceptionUtils.getThrowables(cyclicCause);
assertEquals(3, throwables.length);
@@ -211,51 +377,20 @@ public class ExceptionUtilsTest {
assertSame(cyclicCause.getCause().getCause(), throwables[2]);
}
- //-----------------------------------------------------------------------
@Test
- public void testGetThrowableList_Throwable_null() {
- final List<?> throwables = ExceptionUtils.getThrowableList(null);
- assertEquals(0, throwables.size());
+ public void testGetThrowables_Throwable_withCause() {
+ final Throwable[] throwables = ExceptionUtils.getThrowables(withCause);
+ assertEquals(3, throwables.length);
+ assertSame(withCause, throwables[0]);
+ assertSame(nested, throwables[1]);
+ assertSame(withoutCause, throwables[2]);
}
@Test
- public void testGetThrowableList_Throwable_withoutCause() {
- final List<?> throwables = ExceptionUtils.getThrowableList(withoutCause);
- assertEquals(1, throwables.size());
- assertSame(withoutCause, throwables.get(0));
- }
-
- @Test
- public void testGetThrowableList_Throwable_nested() {
- final List<?> throwables = ExceptionUtils.getThrowableList(nested);
- assertEquals(2, throwables.size());
- assertSame(nested, throwables.get(0));
- assertSame(withoutCause, throwables.get(1));
- }
-
- @Test
- public void testGetThrowableList_Throwable_withCause() {
- final List<?> throwables = ExceptionUtils.getThrowableList(withCause);
- assertEquals(3, throwables.size());
- assertSame(withCause, throwables.get(0));
- assertSame(nested, throwables.get(1));
- assertSame(withoutCause, throwables.get(2));
- }
-
- @Test
- public void testGetThrowableList_Throwable_jdkNoCause() {
- final List<?> throwables = ExceptionUtils.getThrowableList(jdkNoCause);
- assertEquals(1, throwables.size());
- assertSame(jdkNoCause, throwables.get(0));
- }
-
- @Test
- public void testGetThrowableList_Throwable_recursiveCause() {
- final List<?> throwables = ExceptionUtils.getThrowableList(cyclicCause);
- assertEquals(3, throwables.size());
- assertSame(cyclicCause, throwables.get(0));
- assertSame(cyclicCause.getCause(), throwables.get(1));
- assertSame(cyclicCause.getCause().getCause(), throwables.get(2));
+ public void testGetThrowables_Throwable_withoutCause() {
+ final Throwable[] throwables = ExceptionUtils.getThrowables(withoutCause);
+ assertEquals(1, throwables.length);
+ assertSame(withoutCause, throwables[0]);
}
@Test
@@ -283,30 +418,6 @@ public class ExceptionUtilsTest {
}
@Test
- public void testThrowableOf_ThrowableClass() {
- assertEquals(null, ExceptionUtils.throwableOfThrowable(null, null));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(null, NestableException.class));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, null));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithCause.class));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, NestableException.class));
- assertEquals(withoutCause, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithoutCause.class));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, null));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, ExceptionWithCause.class));
- assertEquals(nested, ExceptionUtils.throwableOfThrowable(nested, NestableException.class));
- assertEquals(nested.getCause(), ExceptionUtils.throwableOfThrowable(nested, ExceptionWithoutCause.class));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, null));
- assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class));
- assertEquals(withCause.getCause(), ExceptionUtils.throwableOfThrowable(withCause, NestableException.class));
- assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithoutCause.class));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Exception.class));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Throwable.class));
- }
-
- @Test
public void testIndexOf_ThrowableClassInt() {
assertEquals(-1, ExceptionUtils.indexOfThrowable(null, null, 0));
assertEquals(-1, ExceptionUtils.indexOfThrowable(null, NestableException.class, 0));
@@ -335,35 +446,6 @@ public class ExceptionUtilsTest {
assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Throwable.class, 0));
}
- @Test
- public void testThrowableOf_ThrowableClassInt() {
- assertEquals(null, ExceptionUtils.throwableOfThrowable(null, null, 0));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(null, NestableException.class, 0));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, null));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithCause.class, 0));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, NestableException.class, 0));
- assertEquals(withoutCause, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithoutCause.class, 0));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, null, 0));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, ExceptionWithCause.class, 0));
- assertEquals(nested, ExceptionUtils.throwableOfThrowable(nested, NestableException.class, 0));
- assertEquals(nested.getCause(), ExceptionUtils.throwableOfThrowable(nested, ExceptionWithoutCause.class, 0));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, null));
- assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 0));
- assertEquals(withCause.getCause(), ExceptionUtils.throwableOfThrowable(withCause, NestableException.class, 0));
- assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithoutCause.class, 0));
-
- assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, -1));
- assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 0));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 1));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 9));
-
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Exception.class, 0));
- assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Throwable.class, 0));
- }
-
//-----------------------------------------------------------------------
@Test
public void testIndexOfType_ThrowableClass() {
@@ -390,30 +472,6 @@ public class ExceptionUtilsTest {
}
@Test
- public void testThrowableOfType_ThrowableClass() {
- assertEquals(null, ExceptionUtils.throwableOfType(null, null));
- assertEquals(null, ExceptionUtils.throwableOfType(null, NestableException.class));
-
- assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, null));
- assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithCause.class));
- assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, NestableException.class));
- assertEquals(withoutCause, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithoutCause.class));
-
- assertEquals(null, ExceptionUtils.throwableOfType(nested, null));
- assertEquals(null, ExceptionUtils.throwableOfType(nested, ExceptionWithCause.class));
- assertEquals(nested, ExceptionUtils.throwableOfType(nested, NestableException.class));
- assertEquals(nested.getCause(), ExceptionUtils.throwableOfType(nested, ExceptionWithoutCause.class));
-
- assertEquals(null, ExceptionUtils.throwableOfType(withCause, null));
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class));
- assertEquals(withCause.getCause(), ExceptionUtils.throwableOfType(withCause, NestableException.class));
- assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfType(withCause, ExceptionWithoutCause.class));
-
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Exception.class));
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Throwable.class));
- }
-
- @Test
public void testIndexOfType_ThrowableClassInt() {
assertEquals(-1, ExceptionUtils.indexOfType(null, null, 0));
assertEquals(-1, ExceptionUtils.indexOfType(null, NestableException.class, 0));
@@ -442,35 +500,6 @@ public class ExceptionUtilsTest {
assertEquals(0, ExceptionUtils.indexOfType(withCause, Throwable.class, 0));
}
- @Test
- public void testThrowableOfType_ThrowableClassInt() {
- assertEquals(null, ExceptionUtils.throwableOfType(null, null, 0));
- assertEquals(null, ExceptionUtils.throwableOfType(null, NestableException.class, 0));
-
- assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, null));
- assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithCause.class, 0));
- assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, NestableException.class, 0));
- assertEquals(withoutCause, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithoutCause.class, 0));
-
- assertEquals(null, ExceptionUtils.throwableOfType(nested, null, 0));
- assertEquals(null, ExceptionUtils.throwableOfType(nested, ExceptionWithCause.class, 0));
- assertEquals(nested, ExceptionUtils.throwableOfType(nested, NestableException.class, 0));
- assertEquals(nested.getCause(), ExceptionUtils.throwableOfType(nested, ExceptionWithoutCause.class, 0));
-
- assertEquals(null, ExceptionUtils.throwableOfType(withCause, null));
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 0));
- assertEquals(withCause.getCause(), ExceptionUtils.throwableOfType(withCause, NestableException.class, 0));
- assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfType(withCause, ExceptionWithoutCause.class, 0));
-
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, -1));
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 0));
- assertEquals(null, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 1));
- assertEquals(null, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 9));
-
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Exception.class, 0));
- assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Throwable.class, 0));
- }
-
//-----------------------------------------------------------------------
@Test
public void testPrintRootCauseStackTrace_Throwable() {
@@ -479,6 +508,8 @@ public class ExceptionUtilsTest {
// internally this method calls stream method anyway
}
+ //-----------------------------------------------------------------------
+
@Test
public void testPrintRootCauseStackTrace_ThrowableStream() {
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
@@ -527,153 +558,128 @@ public class ExceptionUtilsTest {
assertFalse(stackTrace.contains(ExceptionUtils.WRAPPED_MARKER));
}
- //-----------------------------------------------------------------------
- @Test
- public void testGetRootCauseStackTrace_Throwable() {
- assertEquals(0, ExceptionUtils.getRootCauseStackTrace(null).length);
-
- final Throwable cause = createExceptionWithCause();
- String[] stackTrace = ExceptionUtils.getRootCauseStackTrace(cause);
- boolean match = false;
- for (final String element : stackTrace) {
- if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) {
- match = true;
- break;
- }
- }
- assertTrue(match);
-
- stackTrace = ExceptionUtils.getRootCauseStackTrace(withoutCause);
- match = false;
- for (final String element : stackTrace) {
- if (element.startsWith(ExceptionUtils.WRAPPED_MARKER)) {
- match = true;
- break;
- }
- }
- assertFalse(match);
- }
-
@Test
public void testRemoveCommonFrames_ListList() {
assertThrows(IllegalArgumentException.class, () -> ExceptionUtils.removeCommonFrames(null, null));
}
@Test
- public void test_getMessage_Throwable() {
- Throwable th = null;
- assertEquals("", ExceptionUtils.getMessage(th));
-
- th = new IllegalArgumentException("Base");
- assertEquals("IllegalArgumentException: Base", ExceptionUtils.getMessage(th));
-
- th = new ExceptionWithCause("Wrapper", th);
- assertEquals("ExceptionUtilsTest.ExceptionWithCause: Wrapper", ExceptionUtils.getMessage(th));
+ public void testThrow() {
+ final Exception expected = new InterruptedException();
+ Exception actual = assertThrows(Exception.class, () -> ExceptionUtils.rethrow(expected));
+ assertSame(expected, actual);
}
@Test
- public void test_getRootCauseMessage_Throwable() {
- Throwable th = null;
- assertEquals("", ExceptionUtils.getRootCauseMessage(th));
+ public void testThrowableOf_ThrowableClass() {
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(null, null));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(null, NestableException.class));
- th = new IllegalArgumentException("Base");
- assertEquals("IllegalArgumentException: Base", ExceptionUtils.getRootCauseMessage(th));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, null));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithCause.class));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, NestableException.class));
+ assertEquals(withoutCause, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithoutCause.class));
- th = new ExceptionWithCause("Wrapper", th);
- assertEquals("IllegalArgumentException: Base", ExceptionUtils.getRootCauseMessage(th));
- }
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, null));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, ExceptionWithCause.class));
+ assertEquals(nested, ExceptionUtils.throwableOfThrowable(nested, NestableException.class));
+ assertEquals(nested.getCause(), ExceptionUtils.throwableOfThrowable(nested, ExceptionWithoutCause.class));
- //-----------------------------------------------------------------------
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, null));
+ assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class));
+ assertEquals(withCause.getCause(), ExceptionUtils.throwableOfThrowable(withCause, NestableException.class));
+ assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithoutCause.class));
- /**
- * Provides a method with a well known chained/nested exception
- * name which matches the full signature (e.g. has a return value
- * of <code>Throwable</code>.
- */
- private static class ExceptionWithCause extends Exception {
- private static final long serialVersionUID = 1L;
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Exception.class));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Throwable.class));
+ }
- private Throwable cause;
+ @Test
+ public void testThrowableOf_ThrowableClassInt() {
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(null, null, 0));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(null, NestableException.class, 0));
- ExceptionWithCause(final String str, final Throwable cause) {
- super(str);
- setCause(cause);
- }
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, null));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithCause.class, 0));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withoutCause, NestableException.class, 0));
+ assertEquals(withoutCause, ExceptionUtils.throwableOfThrowable(withoutCause, ExceptionWithoutCause.class, 0));
- ExceptionWithCause(final Throwable cause) {
- super();
- setCause(cause);
- }
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, null, 0));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(nested, ExceptionWithCause.class, 0));
+ assertEquals(nested, ExceptionUtils.throwableOfThrowable(nested, NestableException.class, 0));
+ assertEquals(nested.getCause(), ExceptionUtils.throwableOfThrowable(nested, ExceptionWithoutCause.class, 0));
- @Override
- public Throwable getCause() {
- return cause;
- }
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, null));
+ assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 0));
+ assertEquals(withCause.getCause(), ExceptionUtils.throwableOfThrowable(withCause, NestableException.class, 0));
+ assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithoutCause.class, 0));
- public void setCause(final Throwable cause) {
- this.cause = cause;
- }
+ assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, -1));
+ assertEquals(withCause, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 0));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 1));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, ExceptionWithCause.class, 9));
+
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Exception.class, 0));
+ assertEquals(null, ExceptionUtils.throwableOfThrowable(withCause, Throwable.class, 0));
}
- /**
- * Provides a method with a well known chained/nested exception
- * name which does not match the full signature (e.g. lacks a
- * return value of <code>Throwable</code>.
- */
- private static class ExceptionWithoutCause extends Exception {
- private static final long serialVersionUID = 1L;
+ @Test
+ public void testThrowableOfType_ThrowableClass() {
+ assertEquals(null, ExceptionUtils.throwableOfType(null, null));
+ assertEquals(null, ExceptionUtils.throwableOfType(null, NestableException.class));
- @SuppressWarnings("unused")
- public void getTargetException() {
- // noop
- }
- }
+ assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, null));
+ assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithCause.class));
+ assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, NestableException.class));
+ assertEquals(withoutCause, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithoutCause.class));
- // Temporary classes to allow the nested exception code to be removed
- // prior to a rewrite of this test class.
- private static class NestableException extends Exception {
- private static final long serialVersionUID = 1L;
+ assertEquals(null, ExceptionUtils.throwableOfType(nested, null));
+ assertEquals(null, ExceptionUtils.throwableOfType(nested, ExceptionWithCause.class));
+ assertEquals(nested, ExceptionUtils.throwableOfType(nested, NestableException.class));
+ assertEquals(nested.getCause(), ExceptionUtils.throwableOfType(nested, ExceptionWithoutCause.class));
- @SuppressWarnings("unused")
- NestableException() {
- super();
- }
+ assertEquals(null, ExceptionUtils.throwableOfType(withCause, null));
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class));
+ assertEquals(withCause.getCause(), ExceptionUtils.throwableOfType(withCause, NestableException.class));
+ assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfType(withCause, ExceptionWithoutCause.class));
- NestableException(final Throwable t) {
- super(t);
- }
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Exception.class));
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Throwable.class));
}
@Test
- public void testThrow() {
- final Exception expected = new InterruptedException();
- Exception actual = assertThrows(Exception.class, () -> ExceptionUtils.rethrow(expected));
- assertSame(expected, actual);
- }
+ public void testThrowableOfType_ThrowableClassInt() {
+ assertEquals(null, ExceptionUtils.throwableOfType(null, null, 0));
+ assertEquals(null, ExceptionUtils.throwableOfType(null, NestableException.class, 0));
- @Test
- public void testCatchTechniques() {
- IOException ioe = assertThrows(IOException.class, ExceptionUtilsTest::throwsCheckedException);
- assertEquals(1, ExceptionUtils.getThrowableCount(ioe));
+ assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, null));
+ assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithCause.class, 0));
+ assertEquals(null, ExceptionUtils.throwableOfType(withoutCause, NestableException.class, 0));
+ assertEquals(withoutCause, ExceptionUtils.throwableOfType(withoutCause, ExceptionWithoutCause.class, 0));
- ioe = assertThrows(IOException.class, ExceptionUtilsTest::redeclareCheckedException);
- assertEquals(1, ExceptionUtils.getThrowableCount(ioe));
- }
+ assertEquals(null, ExceptionUtils.throwableOfType(nested, null, 0));
+ assertEquals(null, ExceptionUtils.throwableOfType(nested, ExceptionWithCause.class, 0));
+ assertEquals(nested, ExceptionUtils.throwableOfType(nested, NestableException.class, 0));
+ assertEquals(nested.getCause(), ExceptionUtils.throwableOfType(nested, ExceptionWithoutCause.class, 0));
- private static int redeclareCheckedException() {
- return throwsCheckedException();
- }
+ assertEquals(null, ExceptionUtils.throwableOfType(withCause, null));
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 0));
+ assertEquals(withCause.getCause(), ExceptionUtils.throwableOfType(withCause, NestableException.class, 0));
+ assertEquals(withCause.getCause().getCause(), ExceptionUtils.throwableOfType(withCause, ExceptionWithoutCause.class, 0));
- private static int throwsCheckedException() {
- try {
- throw new IOException();
- } catch (final Exception e) {
- return ExceptionUtils.<Integer>rethrow(e);
- }
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, -1));
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 0));
+ assertEquals(null, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 1));
+ assertEquals(null, ExceptionUtils.throwableOfType(withCause, ExceptionWithCause.class, 9));
+
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Exception.class, 0));
+ assertEquals(withCause, ExceptionUtils.throwableOfType(withCause, Throwable.class, 0));
}
- public static class TestThrowable extends Throwable {
- private static final long serialVersionUID = 1L;
+ @Test
+ public void testWrapAndUnwrapCheckedException() {
+ Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new IOException()));
+ assertTrue(ExceptionUtils.hasCause(t, IOException.class));
}
@Test
@@ -689,12 +695,6 @@ public class ExceptionUtilsTest {
}
@Test
- public void testWrapAndUnwrapCheckedException() {
- Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new IOException()));
- assertTrue(ExceptionUtils.hasCause(t, IOException.class));
- }
-
- @Test
public void testWrapAndUnwrapThrowable() {
Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new TestThrowable()));
assertTrue(ExceptionUtils.hasCause(t, TestThrowable.class));