Our goal was to get the last throwable of a specific class in the stack
trace. So we extended ExceptionUtils with some methods:
public static int lastIndexOfThrowable(Throwable throwable, Class clazz)
public static int lastIndexOfThrowable(Throwable throwable, Class clazz,
int fromIndex)
public static int lastIndexOfType(Throwable throwable, Class type)
public static int lastIndexOfType(Throwable throwable, Class type, int
fromIndex)
The patches are attached, the testcases as well.
We would be pleased, if you can use it.
have a nice day :-)
marc
--
Marc Gassmann | [EMAIL PROTECTED]
phone +41 (0)44 247 79 84 | fax +41 (0)44 247 70 75
Netcetera AG | 8040 Zürich | Switzerland | http://netcetera.ch
Index:
C:/data/eclipse-workspace/jakarta-commons-lang/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
===================================================================
---
C:/data/eclipse-workspace/jakarta-commons-lang/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
(revision 358559)
+++
C:/data/eclipse-workspace/jakarta-commons-lang/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
(working copy)
@@ -576,6 +576,150 @@
//-----------------------------------------------------------------------
/**
+ * <p>Returns the (zero based) index of the last <code>Throwable</code>
+ * that matches the specified class (exactly) in the exception chain.
+ * Subclasses of the specified class do not match - see
+ * [EMAIL PROTECTED] #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 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
+ */
+ public static int lastIndexOfThrowable(Throwable throwable, Class clazz) {
+ return lastIndexOf(throwable, clazz, -1, false);
+ }
+
+ /**
+ * <p>Returns the (zero based) index of the last <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
+ * [EMAIL PROTECTED] #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 chain size.
+ * A start index greater than the number of throwables is treated as chain
size.</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 chain size, larger than chain size treated as
chain size
+ * @return the index into the throwable chain, -1 if no match or null input
+ */
+ public static int lastIndexOfThrowable(Throwable throwable, Class clazz,
int fromIndex) {
+ return lastIndexOf(throwable, clazz, fromIndex, false);
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * <p>Returns the (zero based) index of the last <code>Throwable</code>
+ * that matches the specified class or subclass in the exception chain.
+ * Subclasses of the specified class do match - see
+ * [EMAIL PROTECTED] #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
+ */
+ public static int lastIndexOfType(Throwable throwable, Class type) {
+ return lastIndexOf(throwable, type, -1, true);
+ }
+
+ /**
+ * <p>Returns the (zero based) index of the last <code>Throwable</code>
+ * that matches the specified type in the exception chain from
+ * a specified index.
+ * Subclasses of the specified class do match - see
+ * [EMAIL PROTECTED] #lastIndexOfThrowable(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 chain size.
+ * A start index greater than the number of throwables returns is treated
as chain size.</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 chain size, larger than chain size treated as
chain size
+ * @return the index into the throwable chain, -1 if no match or null input
+ */
+ public static int lastIndexOfType(Throwable throwable, Class type, int
fromIndex) {
+ return lastIndexOf(throwable, type, fromIndex, true);
+ }
+
+ /**
+ * <p>Worker method for the <code>lastIndexOfType</code> methods.</p>
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, null returns -1
+ * @param fromIndex the (zero based) index of the starting position,
+ * negative treated as chain size, larger than chain size treated as
chain size
+ * @param subclass if <code>true</code>, compares with [EMAIL PROTECTED]
Class#isAssignableFrom(Class)}, otherwise compares
+ * using references
+ * @return index of the last occurence of the <code>type</code> within
throwables nested within the specified <code>throwable</code>
+ */
+ private static int lastIndexOf(Throwable throwable, Class type, int
fromIndex, boolean subclass) {
+ if (throwable == null || type == null) {
+ return -1;
+ }
+ Throwable[] throwables = ExceptionUtils.getThrowables(throwable);
+ if (fromIndex < 0) {
+ fromIndex = throwables.length - 1;
+ }
+ if (fromIndex >= throwables.length) {
+ fromIndex = throwables.length - 1;
+ }
+ if (subclass) {
+ for (int i = fromIndex; i >= 0; i--) {
+ if (type.isAssignableFrom(throwables[i].getClass())) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = fromIndex; i >= 0; i--) {
+ if (type.equals(throwables[i].getClass())) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * <p>Returns the last <code>Throwable</code> that matches the
+ * specified type in the exception chain.
+ * Subclasses of the specified class do not match.
+ *
+ * <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>.
+ *
+ * @param throwable the throwable to inspect, may be null
+ * @param type the type to search for, null returns -1
+ * @return the last occurence of the <code>type</code> within throwables
nested within the specified <code>throwable</code>
+ */
+ public static Throwable getLastThrowableOfType(Throwable throwable, Class
type) {
+ int index = ExceptionUtils.lastIndexOf(throwable, type, -1, false);
+ if (index < 0) {
+ return null;
+ } else {
+ return ExceptionUtils.getThrowables(throwable)[index];
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
* <p>Prints a compact stack trace for the root cause of a throwable
* to <code>System.err</code>.</p>
*
Index:
C:/data/eclipse-workspace/jakarta-commons-lang/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java
===================================================================
---
C:/data/eclipse-workspace/jakarta-commons-lang/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java
(revision 358559)
+++
C:/data/eclipse-workspace/jakarta-commons-lang/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java
(working copy)
@@ -287,6 +287,87 @@
}
//-----------------------------------------------------------------------
+ public void testLastIndexOf_ThrowableClassInt() {
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(null, null, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(null,
NestableException.class, 0));
+
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withoutCause, null));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withoutCause,
ExceptionWithCause.class, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withoutCause,
NestableException.class, 0));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withoutCause,
ExceptionWithoutCause.class, 0));
+
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(nested, null, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(nested,
ExceptionWithCause.class, 0));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(nested,
NestableException.class, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(nested,
ExceptionWithoutCause.class, 0));
+
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withCause, null));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withCause,
NestableException.class, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithoutCause.class, 0));
+
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, -1));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, 0));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, 1));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, 9));
+
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
Exception.class, 0));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(nested,
Exception.class, 0));
+ assertEquals(2, ExceptionUtils.lastIndexOfType(withCause,
Exception.class, 2));
+ assertEquals(1, ExceptionUtils.lastIndexOfType(nested,
Exception.class, 2));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withoutCause,
Exception.class, 2));
+ }
+
+ public void testLastIndexOfType_ThrowableClassInt() {
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(null, null, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(null,
NestableException.class, 0));
+
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withoutCause, null));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withoutCause,
ExceptionWithCause.class, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withoutCause,
NestableException.class, 0));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withoutCause,
ExceptionWithoutCause.class, 0));
+
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(nested, null, 0));
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(nested,
ExceptionWithCause.class, 0));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(nested,
NestableException.class, 0));
+ assertEquals(1, ExceptionUtils.lastIndexOfType(nested,
ExceptionWithoutCause.class, 1));
+
+ assertEquals(-1, ExceptionUtils.lastIndexOfType(withCause, null));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, 0));
+ assertEquals(1, ExceptionUtils.lastIndexOfType(withCause,
NestableException.class, 1));
+ assertEquals(2, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithoutCause.class, 2));
+
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, -1));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, 1));
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
ExceptionWithCause.class, 9));
+
+ assertEquals(0, ExceptionUtils.lastIndexOfType(withCause,
Exception.class, 0));
+ }
+
+ public void testGetLastThrowableOfType() {
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(null, null));
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(nested, null));
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(null,
Exception.class));
+
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(withoutCause,
null));
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(withoutCause,
ExceptionWithCause.class));
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(withoutCause,
NestableException.class));
+ assertEquals(withoutCause,
ExceptionUtils.getLastThrowableOfType(withoutCause,
ExceptionWithoutCause.class));
+
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(nested,
null));
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(nested,
ExceptionWithCause.class));
+ assertEquals(nested, ExceptionUtils.getLastThrowableOfType(nested,
NestableException.class));
+ assertEquals(withoutCause,
ExceptionUtils.getLastThrowableOfType(nested, ExceptionWithoutCause.class));
+
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(withCause,
null));
+ assertEquals(withCause,
ExceptionUtils.getLastThrowableOfType(withCause, ExceptionWithCause.class));
+ assertEquals(nested, ExceptionUtils.getLastThrowableOfType(withCause,
NestableException.class));
+ assertEquals(withoutCause,
ExceptionUtils.getLastThrowableOfType(withCause, ExceptionWithoutCause.class));
+
+ assertEquals(null, ExceptionUtils.getLastThrowableOfType(withCause,
Exception.class));
+ }
+
+ //-----------------------------------------------------------------------
public void testPrintRootCauseStackTrace_Throwable() throws Exception {
ExceptionUtils.printRootCauseStackTrace(null);
// could pipe system.err to a known stream, but not much point as
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]