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]

Reply via email to