[LANG-1457] Add ExceptionUtils.throwableOfType(Throwable, Class) and
friends.
This commit is contained in:
parent
4b77d24042
commit
1ec6c0ae9a
|
@ -47,6 +47,7 @@ The <action> type attribute can be add,update,fix,remove.
|
|||
|
||||
<release version="3.10" date="YYYY-MM-DD" description="TBD">
|
||||
<action issue="LANG-1450" type="fix" dev="chtompki">Generate javadoc jar on build.</action>
|
||||
<action issue="LANG-1457" type="fix" dev="ggregory">Add ExceptionUtils.throwableOfType(Throwable, Class) and friends.</action>
|
||||
</release>
|
||||
|
||||
<release version="3.9" date="2019-04-09" description="New features and bug fixes. Requires Java 8, supports Java 9, 10, 11">
|
||||
|
|
|
@ -285,9 +285,8 @@ public class ExceptionUtils {
|
|||
return list;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Returns the (zero based) index of the first <code>Throwable</code>
|
||||
* <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>
|
||||
|
@ -305,7 +304,27 @@ public class ExceptionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the (zero based) index of the first <code>Throwable</code>
|
||||
* <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 (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
|
||||
|
@ -319,7 +338,7 @@ public class ExceptionUtils {
|
|||
*
|
||||
* @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,
|
||||
* @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
|
||||
*/
|
||||
|
@ -327,9 +346,33 @@ public class ExceptionUtils {
|
|||
return indexOf(throwable, clazz, fromIndex, false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* <p>Returns the (zero based) index of the first <code>Throwable</code>
|
||||
* <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>
|
||||
|
@ -348,7 +391,52 @@ public class ExceptionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the (zero based) index of the first <code>Throwable</code>
|
||||
* <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
|
||||
|
@ -362,7 +450,7 @@ public class ExceptionUtils {
|
|||
*
|
||||
* @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,
|
||||
* @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
|
||||
|
@ -376,7 +464,7 @@ public class ExceptionUtils {
|
|||
*
|
||||
* @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,
|
||||
* @param fromIndex the (zero-based) index of the starting position,
|
||||
* negative treated as zero, larger than chain size returns -1
|
||||
* @param subclass if <code>true</code>, compares with {@link Class#isAssignableFrom(Class)}, otherwise compares
|
||||
* using references
|
||||
|
@ -409,6 +497,45 @@ public class ExceptionUtils {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* <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>Prints a compact stack trace for the root cause of a throwable
|
||||
|
|
|
@ -258,7 +258,6 @@ public class ExceptionUtilsTest {
|
|||
assertSame(cyclicCause.getCause().getCause(), throwables.get(2));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Test
|
||||
public void testIndexOf_ThrowableClass() {
|
||||
assertEquals(-1, ExceptionUtils.indexOfThrowable(null, null));
|
||||
|
@ -280,6 +279,31 @@ public class ExceptionUtilsTest {
|
|||
assertEquals(2, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithoutCause.class));
|
||||
|
||||
assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Exception.class));
|
||||
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
|
||||
|
@ -308,6 +332,36 @@ public class ExceptionUtilsTest {
|
|||
assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, ExceptionWithCause.class, 9));
|
||||
|
||||
assertEquals(-1, ExceptionUtils.indexOfThrowable(withCause, Exception.class, 0));
|
||||
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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -332,6 +386,31 @@ public class ExceptionUtilsTest {
|
|||
assertEquals(2, ExceptionUtils.indexOfType(withCause, ExceptionWithoutCause.class));
|
||||
|
||||
assertEquals(0, ExceptionUtils.indexOfType(withCause, Exception.class));
|
||||
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
|
||||
|
@ -360,6 +439,36 @@ public class ExceptionUtilsTest {
|
|||
assertEquals(-1, ExceptionUtils.indexOfType(withCause, ExceptionWithCause.class, 9));
|
||||
|
||||
assertEquals(0, ExceptionUtils.indexOfType(withCause, Exception.class, 0));
|
||||
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));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
@ -516,6 +625,7 @@ public class ExceptionUtilsTest {
|
|||
|
||||
@SuppressWarnings("unused")
|
||||
public void getTargetException() {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue