001    package com.mockrunner.struts;
002    
003    import javax.servlet.ServletException;
004    import javax.servlet.http.HttpServletRequest;
005    import javax.servlet.http.HttpServletResponse;
006    
007    import org.apache.struts.action.ActionForm;
008    import org.apache.struts.action.ActionMapping;
009    import org.apache.struts.action.ExceptionHandler;
010    import org.apache.struts.config.ExceptionConfig;
011    
012    import com.mockrunner.base.NestedApplicationException;
013    
014    /**
015     * The default implementation of {@link ExceptionHandlerConfig}. It uses the Struts
016     * exception handling mechanism. Use the various constructors to provide your subclass
017     * of <code>ExceptionHandler</code> or to configure exception handling using an
018     * instance of <code>ExceptionConfig</code>. The <code>ExceptionConfig</code> class
019     * allows you to set the handler class an exception type.
020     * Use {@link ActionTestModule#addExceptionHandler} to register an exception handler.
021     */
022    public class DefaultExceptionHandlerConfig implements ExceptionHandlerConfig
023    {
024        private ExceptionConfig exceptionConfig;
025        private ExceptionHandler exceptionHandler;
026        private Class exceptionClass;
027        
028        public DefaultExceptionHandlerConfig(ExceptionConfig exceptionConfig)
029        {
030            this.exceptionConfig = exceptionConfig;
031            try
032            {
033                Class handlerClass = exceptionConfig.getClass().getClassLoader().loadClass(exceptionConfig.getHandler());
034                exceptionHandler = (ExceptionHandler)handlerClass.newInstance();
035                exceptionClass = exceptionConfig.getClass().getClassLoader().loadClass(exceptionConfig.getType());
036            } 
037            catch(Exception exc)
038            {
039                throw new NestedApplicationException(exc);
040            }
041        }
042        
043        public DefaultExceptionHandlerConfig(ExceptionHandler exceptionHandler, ExceptionConfig exceptionConfig)
044        {
045            this.exceptionHandler = exceptionHandler;
046            this.exceptionConfig = exceptionConfig;
047            this.exceptionConfig.setHandler(exceptionHandler.getClass().getName());
048            try
049            {
050                exceptionClass = exceptionConfig.getClass().getClassLoader().loadClass(exceptionConfig.getType());
051            } 
052            catch(Exception exc)
053            {
054                throw new NestedApplicationException(exc);
055            }
056        }
057        
058        public DefaultExceptionHandlerConfig(ExceptionHandler exceptionHandler, Class exceptionClass)
059        {
060            this.exceptionHandler = exceptionHandler;
061            this.exceptionClass = exceptionClass;
062            this.exceptionConfig = new ExceptionConfig();
063            this.exceptionConfig.setHandler(exceptionHandler.getClass().getName());
064            this.exceptionConfig.setType(exceptionClass.getName());
065        }
066        
067        public DefaultExceptionHandlerConfig(Class exceptionClass)
068        {
069            this.exceptionHandler = new ExceptionHandler();
070            this.exceptionClass = exceptionClass;
071            this.exceptionConfig = new ExceptionConfig();
072            this.exceptionConfig.setHandler(ExceptionHandler.class.getName());
073            this.exceptionConfig.setType(exceptionClass.getName());
074        }
075        
076        public boolean canHandle(Exception exception)
077        {
078            return exceptionClass.isInstance(exception);
079        }
080    
081        public Object handle(Exception exception, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException
082        {
083            if(!canHandle(exception)) return null;
084            if(null == exceptionHandler) return null;
085            return exceptionHandler.execute((Exception)exception, exceptionConfig, mapping, form, request, response);
086        }
087    
088        /**
089         * Get the underlying <code>ExceptionConfig</code>. If you did not provide
090         * an instance of <code>ExceptionConfig</code>, this class will create one
091         * internally.
092         * @return the <code>ExceptionConfig</code>
093         */
094        public ExceptionConfig getExceptionConfig()
095        {
096            return exceptionConfig;
097        }
098    
099        /**
100         * Get the underlying <code>ExceptionHandler</code>.
101         * @return the <code>ExceptionHandler</code>
102         */
103        public ExceptionHandler getExceptionHandler()
104        {
105            return exceptionHandler;
106        }
107    }