You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by dm...@apache.org on 2002/12/17 00:05:30 UTC

cvs commit: jakarta-commons/lang/src/java/org/apache/commons/lang/exception ExceptionUtils.java

dmitri      2002/12/16 15:05:29

  Modified:    lang/src/test/org/apache/commons/lang/exception
                        ExceptionUtilsTestCase.java
               lang/src/java/org/apache/commons/lang/exception
                        ExceptionUtils.java
  Log:
  Added printRootCauseStackTrace
  
  Revision  Changes    Path
  1.5       +36 -3     jakarta-commons/lang/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java
  
  Index: ExceptionUtilsTestCase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/test/org/apache/commons/lang/exception/ExceptionUtilsTestCase.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ExceptionUtilsTestCase.java	25 Sep 2002 05:50:49 -0000	1.4
  +++ ExceptionUtilsTestCase.java	16 Dec 2002 23:05:29 -0000	1.5
  @@ -54,8 +54,9 @@
    * <http://www.apache.org/>.
    */
   
  +import java.io.PrintWriter;
  +
   import junit.framework.Test;
  -import junit.framework.TestCase;
   import junit.framework.TestSuite;
   
   /**
  @@ -83,11 +84,34 @@
   
       public void setUp()
       {
  -        withoutCause = new ExceptionWithoutCause();
  +        withoutCause = createExceptionWithoutCause();
           nested = new NestableException(withoutCause);
           withCause = new ExceptionWithCause(nested);
       }
  -
  +    
  +    private Throwable createExceptionWithoutCause(){
  +        try {
  +            throw new ExceptionWithoutCause();
  +        }
  +        catch (Throwable t){
  +            return t;
  +        }
  +    }
  +
  +    private Throwable createExceptionWithCause(){
  +        try {
  +            try {
  +                throw new ExceptionWithCause(createExceptionWithoutCause());
  +            }
  +            catch (Throwable t){
  +                throw new ExceptionWithCause(t);
  +            }
  +        }
  +        catch (Throwable t){
  +            return t;
  +        }
  +    } 
  +    
       public void testGetCause()
       {
           assertNull(ExceptionUtils.getCause(withoutCause));
  @@ -107,6 +131,15 @@
           assertEquals(ExceptionUtils.getThrowableCount(null), 0);
       }
   
  +    public void testPrintThrowables()
  +    {
  +        Throwable withCause = createExceptionWithCause();
  +        ExceptionUtils.printRootCauseStackTrace(withCause, 
  +            new PrintWriter(System.out));
  +        ExceptionUtils.printRootCauseStackTrace(withoutCause, 
  +            System.out);
  +    }
  +    
       /**
        * Provides a method with a well known chained/nested exception
        * name which matches the full signature (e.g. has a return value
  
  
  
  1.18      +122 -2    jakarta-commons/lang/src/java/org/apache/commons/lang/exception/ExceptionUtils.java
  
  Index: ExceptionUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/exception/ExceptionUtils.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- ExceptionUtils.java	13 Oct 2002 17:57:10 -0000	1.17
  +++ ExceptionUtils.java	16 Dec 2002 23:05:29 -0000	1.18
  @@ -54,11 +54,12 @@
    * <http://www.apache.org/>.
    */
   
  +import java.io.PrintStream;
  +import java.io.PrintWriter;
  +import java.io.StringWriter;
   import java.lang.reflect.Field;
   import java.lang.reflect.InvocationTargetException;
   import java.lang.reflect.Method;
  -import java.io.PrintWriter;
  -import java.io.StringWriter;
   import java.sql.SQLException;
   import java.util.ArrayList;
   import java.util.LinkedList;
  @@ -371,8 +372,100 @@
           }
           return -1;
       }
  +    
  +    /**
  +     * Prints a compact stack trace for the root cause of a throwable.
  +     * The compact stack trace starts with the root cause and prints
  +     * stack frames up to the place where it was caught and wrapped.
  +     * Then it prints the wrapped exception and continues with stack frames
  +     * until the wrapper exception is caught and wrapped again, etc.
  +     * <p>
  +     * The method is equivalent to t.printStackTrace() for throwables
  +     * that don't have nested causes.
  +     */
  +    public static void printRootCauseStackTrace(Throwable t, PrintStream stream)
  +    {
  +        String trace[] = getRootCauseStackTrace(t);
  +        for (int i = 0; i < trace.length; i++){
  +            stream.println(trace[i]);
  +        }
  +        stream.flush();
  +    }
  +    
  +    /**
  +     * Equivalent to printRootCauseStackTrace(t, System.err)
  +     */
  +    public static void printRootCauseStackTrace(Throwable t)
  +    {
  +        printRootCauseStackTrace(t, System.err);
  +    }
  +
  +    /**
  +     * Same as printRootCauseStackTrace(t, stream), except it takes
  +     * a PrintWriter as an argument.
  +     */
  +    public static void printRootCauseStackTrace(Throwable t, PrintWriter writer)
  +    {
  +        String trace[] = getRootCauseStackTrace(t);
  +        for (int i = 0; i < trace.length; i++){
  +            writer.println(trace[i]);
  +        }
  +        writer.flush();
  +    }
  +
   
       /**
  +     * Creates a compact stack trace for the root cause of the supplied 
  +     * throwable.
  +     *   
  +     * See <code>printRootCauseStackTrace(Throwable t, PrintStream s)</code> 
     */
  +    public static String[] getRootCauseStackTrace(Throwable t)
  +    {
  +        Throwable throwables[] = getThrowables(t);
  +        int count = throwables.length;        
  +        ArrayList frames = new ArrayList();
  +        List nextTrace = getStackFrameList(throwables[count-1]);        
  +        for (int i = count; --i >= 0;){
  +            List 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] " + throwables[i].toString());
  +            }
  +            for (int j = 0; j < trace.size(); j++){
  +                frames.add(trace.get(j));
  +            }
  +        }
  +        return (String[]) frames.toArray(new String[0]);
  +    }
  +
  +    /**
  +     * Given two stack traces, removes common frames from the cause trace.
  +     * 
     * @param causeFrames   stack trace of a cause throwable
     * @param wrapperFrames stack trace of a wrapper throwable 
     */
  +    private static void removeCommonFrames(List causeFrames, List wrapperFrames)
  +    {
  +        int causeFrameIndex = causeFrames.size() - 1; 
  +        int wrapperFrameIndex = wrapperFrames.size() - 1;
  +        while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0)
  +        {
  +            // Remove the frame from the cause trace if it is the same
  +            // as in the wrapper trace
  +            String causeFrame = (String)causeFrames.get(causeFrameIndex);
  +            String wrapperFrame = (String)wrapperFrames.get(wrapperFrameIndex);
  +            if (causeFrame.equals(wrapperFrame)){
  +                causeFrames.remove(causeFrameIndex);
  +            }
  +            causeFrameIndex--;
  +            wrapperFrameIndex--;
  +        }
  +    }
  +    
  +    /**
        * A convenient way of extracting the stack trace from an
        * exception.
        *
  @@ -417,5 +510,32 @@
               list.add(frames.nextToken());
           }
           return (String []) list.toArray(new String[] {});
  +    }
  +    
  +    /**
  +     * Produces a List of stack frames - the message is not included.
  +     * This works in most cases - it will only fail if the exception message
  +     * contains a line that starts with:  "   at".
  +     * 
     * @param t is any throwable
     * @return List of stack frames
     */
  +    static List getStackFrameList(Throwable t){
  +        String stackTrace = getStackTrace(t);
  +        String linebreak = SystemUtils.LINE_SEPARATOR;
  +        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
  +        List list = new LinkedList();
  +        boolean traceStarted = false;
  +        while (frames.hasMoreTokens())
  +        {
  +            String token = frames.nextToken(); 
  +            // Determine if the line starts with <whitespace>at
  +            int at = token.indexOf("at");
  +            if (at != -1 && token.substring(0, at).trim().length() == 0){
  +                traceStarted = true;
  +                list.add(token);
  +            }
  +            else if (traceStarted){
  +                break;
  +            }
  +        }
  +        return list;
       }
   }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>