package org.apache.velocity.app.event.implement;

/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import org.apache.velocity.app.event.RuntimeServicesAware;
import org.apache.velocity.app.event.MethodExceptionEventHandler;
import org.apache.velocity.runtime.RuntimeServices;

/**
 * Simple event handler that renders method exceptions in the page
 * rather than throwing the exception.  Useful for debugging.
 *
 * <P>By default this event handler renders the exception name only.
 * To include both the exception name and the message, set the property
 * <code>eventhandler.methodexception.message</code> to <code>true</code>.  To render
 * the stack trace, set the property <code>eventhandler.methodexception.stacktrace</code>
 * to <code>true</code>.
 *
 * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
 * @version $Id$
 */
public class PrintExceptions implements MethodExceptionEventHandler,RuntimeServicesAware
{

    private static String SHOW_MESSAGE = "eventhandler.methodexception.message";
    private static String SHOW_STACK_TRACE = "eventhandler.methodexception.stacktrace";
    private RuntimeServices rs;

    /**
     * Render the method exception, and optionally the exception message and stack trace.
     */
    public Object methodException(Class claz, String method, Exception e) throws Exception
    {
        boolean showMessage = rs.getBoolean(SHOW_MESSAGE,false);
        boolean showStackTrace = rs.getBoolean(SHOW_STACK_TRACE,false);

        StringBuffer st;
        if (showMessage && showStackTrace)
        {
            st = new StringBuffer(200);
            st.append(e.getClass().getName()).append("\n");
            st.append(e.getMessage()).append("\n");
            st.append(getStackTrace(e));

        } else if (showMessage)
        {
            st = new StringBuffer(50);
            st.append(e.getClass().getName()).append("\n");
            st.append(e.getMessage()).append("\n");

        } else if (showStackTrace)
        {
            st = new StringBuffer(200);
            st.append(e.getClass().getName()).append("\n");
            st.append(getStackTrace(e));

        } else
        {
            st = new StringBuffer(15);
            st.append(e.getClass().getName()).append("\n");
        }

        return st.toString();

    }


    private static String getStackTrace(Throwable E)
    {
        try
        {
            StringWriter StackTraceWriter = new StringWriter();
            E.printStackTrace(new PrintWriter(StackTraceWriter));
            StackTraceWriter.flush();
            String StackTrace = StackTraceWriter.toString();
            StackTraceWriter.close();
            return StackTraceWriter.toString() ;
        }
        catch (IOException ioe)
        {
            return "";
        }
    }



    public void setRuntimeServices(RuntimeServices rs) throws Exception
    {
        this.rs = rs;
    }

}

@@ -1756,16 +1756,61 @@
 ktrace%22;
+%0A%0A    /** Reference to the runtime service */
 %0A    pri
@@ -1832,16 +1832,23 @@
 vices rs
+ = null
 ;%0A%0A    /
@@ -3064,17 +3064,25 @@
 ble 
-E
+throwable
 )%0A    %7B%0A
     
@@ -3073,24 +3073,70 @@
 able)%0A    %7B%0A
+        StringWriter stackTraceWriter = null;%0A
         try%0A
@@ -3161,22 +3161,9 @@
     
-StringWriter S
+s
 tack
@@ -3208,17 +3208,25 @@
         
-E
+throwable
 .printSt
@@ -3250,17 +3250,17 @@
 tWriter(
-S
+s
 tackTrac
@@ -3274,33 +3274,33 @@
 ));%0A            
-S
+s
 tackTraceWriter.
@@ -3324,29 +3324,16 @@
     
-String StackTrace = S
+return s
 tack
@@ -3364,21 +3364,61 @@
         
+%7D%0A
     
-S
+    finally%0A        %7B%0A            if (s
 tackTrac
@@ -3428,17 +3428,17 @@
 iter
-.close();
+ != null)
 %0A   
@@ -3450,16 +3450,69 @@
     
-return S
+%7B%0A                try%0A                %7B%0A                    s
 tack
@@ -3527,19 +3527,15 @@
 ter.
-toString
+close
 ()
- 
 ;%0A  
@@ -3532,34 +3532,50 @@
 lose();%0A        
+  
-%7D%0A
+      %7D%0A        
         catch (I
@@ -3590,32 +3590,40 @@
 on ioe)%0A        
+      
+  
 %7B%0A            re
@@ -3624,18 +3624,61 @@
     
-return %22%22;
+        // do nothing%0A                %7D%0A            %7D
 %0A   
@@ -3692,17 +3692,16 @@
     %7D%0A%0A%0A
-%0A
     publ

Make sure that the output stream always gets close. Has the side effect, that getStackTrace will always return the right stack trace as the IOException can only be thrown in close()