Sort by method name.
This commit is contained in:
parent
1ec6c0ae9a
commit
f698f9e64e
|
@ -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>
|
||||
|
@ -164,28 +139,6 @@ public class ExceptionUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <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>
|
||||
*
|
||||
|
@ -212,6 +165,209 @@ public class ExceptionUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets a short message summarising the exception.
|
||||
* <p>
|
||||
* The message returned is of the form
|
||||
* {ClassNameWithoutPackage}: {ThrowableMessage}
|
||||
*
|
||||
* @param th the throwable to get a message for, null returns empty string
|
||||
* @return the message, non-null
|
||||
* @since 2.2
|
||||
*/
|
||||
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>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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets a short message summarising the root cause exception.
|
||||
* <p>
|
||||
* The message returned is of the form
|
||||
* {ClassNameWithoutPackage}: {ThrowableMessage}
|
||||
*
|
||||
* @param th the throwable to get a message for, null returns empty string
|
||||
* @return the message, non-null
|
||||
* @since 2.2
|
||||
*/
|
||||
public static String getRootCauseMessage(final Throwable th) {
|
||||
Throwable root = getRootCause(th);
|
||||
root = root == null ? th : root;
|
||||
return getMessage(root);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <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>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>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 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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <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());
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* <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>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>Counts the number of <code>Throwable</code> objects in the
|
||||
|
@ -232,31 +388,7 @@ public class ExceptionUtils {
|
|||
public static int getThrowableCount(final Throwable throwable) {
|
||||
return getThrowableList(throwable).size();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the list of <code>Throwable</code> objects in the
|
||||
* exception chain.</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
|
||||
* @return the array of throwables, never null
|
||||
*/
|
||||
public static Throwable[] getThrowables(final Throwable throwable) {
|
||||
final List<Throwable> list = getThrowableList(throwable);
|
||||
return list.toArray(new Throwable[list.size()]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Returns the list of <code>Throwable</code> objects in the
|
||||
* exception chain.</p>
|
||||
|
@ -286,177 +418,48 @@ public class ExceptionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* <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>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>.</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 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
|
||||
* @return the array of throwables, never null
|
||||
*/
|
||||
public static int indexOfThrowable(final Throwable throwable, final Class<?> clazz) {
|
||||
return indexOf(throwable, clazz, 0, false);
|
||||
public static Throwable[] getThrowables(final Throwable throwable) {
|
||||
final List<Throwable> list = getThrowableList(throwable);
|
||||
return list.toArray(new Throwable[list.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>
|
||||
* Does the throwable's causal chain have an immediate or wrapped exception
|
||||
* of the given type?
|
||||
*
|
||||
* <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
|
||||
* @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 <T extends Throwable> T throwableOfThrowable(final Throwable throwable, final Class<T> clazz) {
|
||||
return throwableOf(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 -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, final int fromIndex) {
|
||||
return indexOf(throwable, clazz, fromIndex, 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 (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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <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);
|
||||
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 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>
|
||||
* @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
|
||||
*/
|
||||
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) {
|
||||
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 -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, 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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -621,44 +669,6 @@ public class ExceptionUtils {
|
|||
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>
|
||||
*
|
||||
|
@ -686,134 +696,6 @@ public class ExceptionUtils {
|
|||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <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());
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* <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>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 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}
|
||||
*
|
||||
* @param th the throwable to get a message for, null returns empty string
|
||||
* @return the message, non-null
|
||||
* @since 2.2
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets a short message summarising the root cause exception.
|
||||
* <p>
|
||||
* The message returned is of the form
|
||||
* {ClassNameWithoutPackage}: {ThrowableMessage}
|
||||
*
|
||||
* @param th the throwable to get a message for, null returns empty string
|
||||
* @return the message, non-null
|
||||
* @since 2.2
|
||||
*/
|
||||
public static String getRootCauseMessage(final Throwable th) {
|
||||
Throwable root = getRootCause(th);
|
||||
root = root == null ? th : root;
|
||||
return getMessage(root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a checked exception without adding the exception to the throws
|
||||
* clause of the calling method. This method prevents throws clause
|
||||
|
@ -874,6 +756,135 @@ public class ExceptionUtils {
|
|||
return ExceptionUtils.<R, RuntimeException>typeErasure(throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* <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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,46 +44,91 @@ import org.junit.jupiter.api.Test;
|
|||
*/
|
||||
public class ExceptionUtilsTest {
|
||||
|
||||
private NestableException nested;
|
||||
private Throwable withCause;
|
||||
private Throwable withoutCause;
|
||||
private Throwable jdkNoCause;
|
||||
private ExceptionWithCause cyclicCause;
|
||||
private Throwable notVisibleException;
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
withoutCause = createExceptionWithoutCause();
|
||||
nested = new NestableException(withoutCause);
|
||||
withCause = new ExceptionWithCause(nested);
|
||||
jdkNoCause = new NullPointerException();
|
||||
final ExceptionWithCause a = new ExceptionWithCause(null);
|
||||
final ExceptionWithCause b = new ExceptionWithCause(a);
|
||||
a.setCause(b);
|
||||
cyclicCause = new ExceptionWithCause(a);
|
||||
notVisibleException = NotVisibleExceptionFactory.createException(withoutCause);
|
||||
}
|
||||
ExceptionWithCause(final String str, final Throwable cause) {
|
||||
super(str);
|
||||
setCause(cause);
|
||||
}
|
||||
|
||||
ExceptionWithCause(final Throwable cause) {
|
||||
super();
|
||||
setCause(cause);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
withoutCause = null;
|
||||
nested = null;
|
||||
withCause = null;
|
||||
jdkNoCause = null;
|
||||
cyclicCause = null;
|
||||
notVisibleException = null;
|
||||
}
|
||||
@Override
|
||||
public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private Throwable createExceptionWithoutCause() {
|
||||
try {
|
||||
throw new ExceptionWithoutCause();
|
||||
} catch (final Throwable t) {
|
||||
return t;
|
||||
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 {
|
||||
|
@ -98,6 +143,69 @@ public class ExceptionUtilsTest {
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private Throwable createExceptionWithoutCause() {
|
||||
try {
|
||||
throw new ExceptionWithoutCause();
|
||||
} catch (final Throwable t) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
withoutCause = createExceptionWithoutCause();
|
||||
nested = new NestableException(withoutCause);
|
||||
withCause = new ExceptionWithCause(nested);
|
||||
jdkNoCause = new NullPointerException();
|
||||
final ExceptionWithCause a = new ExceptionWithCause(null);
|
||||
final ExceptionWithCause b = new ExceptionWithCause(a);
|
||||
a.setCause(b);
|
||||
cyclicCause = new ExceptionWithCause(a);
|
||||
notVisibleException = NotVisibleExceptionFactory.createException(withoutCause);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
withoutCause = null;
|
||||
nested = null;
|
||||
withCause = null;
|
||||
jdkNoCause = null;
|
||||
cyclicCause = null;
|
||||
notVisibleException = 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));
|
||||
}
|
||||
|
||||
@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() {
|
||||
|
@ -154,6 +262,33 @@ public class ExceptionUtilsTest {
|
|||
assertSame(cyclicCause.getCause().getCause(), ExceptionUtils.getRootCause(cyclicCause));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@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() {
|
||||
|
@ -165,50 +300,19 @@ public class ExceptionUtilsTest {
|
|||
assertEquals(3, ExceptionUtils.getThrowableCount(cyclicCause));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Test
|
||||
public void testGetThrowables_Throwable_null() {
|
||||
assertEquals(0, ExceptionUtils.getThrowables(null).length);
|
||||
public void testGetThrowableList_Throwable_jdkNoCause() {
|
||||
final List<?> throwables = ExceptionUtils.getThrowableList(jdkNoCause);
|
||||
assertEquals(1, throwables.size());
|
||||
assertSame(jdkNoCause, throwables.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetThrowables_Throwable_withoutCause() {
|
||||
final Throwable[] throwables = ExceptionUtils.getThrowables(withoutCause);
|
||||
assertEquals(1, throwables.length);
|
||||
assertSame(withoutCause, throwables[0]);
|
||||
}
|
||||
|
||||
@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_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 testGetThrowables_Throwable_jdkNoCause() {
|
||||
final Throwable[] throwables = ExceptionUtils.getThrowables(jdkNoCause);
|
||||
assertEquals(1, throwables.length);
|
||||
assertSame(jdkNoCause, throwables[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetThrowables_Throwable_recursiveCause() {
|
||||
final Throwable[] throwables = ExceptionUtils.getThrowables(cyclicCause);
|
||||
assertEquals(3, throwables.length);
|
||||
assertSame(cyclicCause, throwables[0]);
|
||||
assertSame(cyclicCause.getCause(), throwables[1]);
|
||||
assertSame(cyclicCause.getCause().getCause(), throwables[2]);
|
||||
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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -219,18 +323,12 @@ public class ExceptionUtilsTest {
|
|||
}
|
||||
|
||||
@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));
|
||||
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
|
||||
|
@ -243,19 +341,56 @@ public class ExceptionUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testGetThrowableList_Throwable_jdkNoCause() {
|
||||
final List<?> throwables = ExceptionUtils.getThrowableList(jdkNoCause);
|
||||
public void testGetThrowableList_Throwable_withoutCause() {
|
||||
final List<?> throwables = ExceptionUtils.getThrowableList(withoutCause);
|
||||
assertEquals(1, throwables.size());
|
||||
assertSame(jdkNoCause, throwables.get(0));
|
||||
assertSame(withoutCause, 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_jdkNoCause() {
|
||||
final Throwable[] throwables = ExceptionUtils.getThrowables(jdkNoCause);
|
||||
assertEquals(1, throwables.length);
|
||||
assertSame(jdkNoCause, throwables[0]);
|
||||
}
|
||||
|
||||
@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);
|
||||
assertSame(cyclicCause, throwables[0]);
|
||||
assertSame(cyclicCause.getCause(), throwables[1]);
|
||||
assertSame(cyclicCause.getCause().getCause(), throwables[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]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetThrowables_Throwable_withoutCause() {
|
||||
final Throwable[] throwables = ExceptionUtils.getThrowables(withoutCause);
|
||||
assertEquals(1, throwables.length);
|
||||
assertSame(withoutCause, throwables[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -282,30 +417,6 @@ public class ExceptionUtilsTest {
|
|||
assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Throwable.class));
|
||||
}
|
||||
|
||||
@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));
|
||||
|
@ -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() {
|
||||
|
@ -389,30 +471,6 @@ public class ExceptionUtilsTest {
|
|||
assertEquals(0, ExceptionUtils.indexOfType(withCause, Throwable.class));
|
||||
}
|
||||
|
||||
@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));
|
||||
|
@ -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,123 +558,11 @@ 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));
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThrow() {
|
||||
final Exception expected = new InterruptedException();
|
||||
|
@ -652,28 +571,115 @@ public class ExceptionUtilsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCatchTechniques() {
|
||||
IOException ioe = assertThrows(IOException.class, ExceptionUtilsTest::throwsCheckedException);
|
||||
assertEquals(1, ExceptionUtils.getThrowableCount(ioe));
|
||||
public void testThrowableOf_ThrowableClass() {
|
||||
assertEquals(null, ExceptionUtils.throwableOfThrowable(null, null));
|
||||
assertEquals(null, ExceptionUtils.throwableOfThrowable(null, NestableException.class));
|
||||
|
||||
ioe = assertThrows(IOException.class, ExceptionUtilsTest::redeclareCheckedException);
|
||||
assertEquals(1, ExceptionUtils.getThrowableCount(ioe));
|
||||
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));
|
||||
}
|
||||
|
||||
private static int redeclareCheckedException() {
|
||||
return throwsCheckedException();
|
||||
@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));
|
||||
}
|
||||
|
||||
private static int throwsCheckedException() {
|
||||
try {
|
||||
throw new IOException();
|
||||
} catch (final Exception e) {
|
||||
return ExceptionUtils.<Integer>rethrow(e);
|
||||
}
|
||||
@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));
|
||||
}
|
||||
|
||||
public static class TestThrowable extends Throwable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@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 testWrapAndUnwrapCheckedException() {
|
||||
Throwable t = assertThrows(Throwable.class, () -> ExceptionUtils.wrapAndThrow(new IOException()));
|
||||
assertTrue(ExceptionUtils.hasCause(t, IOException.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -688,12 +694,6 @@ public class ExceptionUtilsTest {
|
|||
assertTrue(ExceptionUtils.hasCause(t, RuntimeException.class));
|
||||
}
|
||||
|
||||
@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()));
|
||||
|
|
Loading…
Reference in New Issue