Java tutorial
/* * Copyright 2008-2013 Acciente, LLC * * Acciente, LLC licenses this file to you 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. */ package com.acciente.induction.dispatcher; import com.acciente.commons.reflect.ParameterProviderException; import com.acciente.induction.controller.Redirect; import com.acciente.induction.dispatcher.controller.ControllerExecutor; import com.acciente.induction.dispatcher.controller.ControllerParameterProviderFactory; import com.acciente.induction.dispatcher.controller.ControllerPool; import com.acciente.induction.dispatcher.interceptor.RequestInterceptorExecutor; import com.acciente.induction.dispatcher.interceptor.RequestInterceptorParameterProviderFactory; import com.acciente.induction.dispatcher.model.ModelFactory; import com.acciente.induction.dispatcher.model.ModelPool; import com.acciente.induction.dispatcher.redirect.RedirectExecutor; import com.acciente.induction.dispatcher.redirect.RedirectExecutorException; import com.acciente.induction.dispatcher.resolver.*; import com.acciente.induction.dispatcher.view.ViewExecutor; import com.acciente.induction.dispatcher.view.ViewExecutorException; import com.acciente.induction.dispatcher.view.ViewFactory; import com.acciente.induction.dispatcher.view.ViewParameterProviderFactory; import com.acciente.induction.init.ClassLoaderInitializer; import com.acciente.induction.init.ConfigLoaderInitializer; import com.acciente.induction.init.ControllerResolverInitializer; import com.acciente.induction.init.RedirectResolverInitializer; import com.acciente.induction.init.RequestInterceptorInitializer; import com.acciente.induction.init.TemplatingEngineInitializer; import com.acciente.induction.init.ViewResolverInitializer; import com.acciente.induction.init.config.Config; import com.acciente.induction.init.config.ConfigLoaderException; import com.acciente.induction.interceptor.RequestInterceptor; import com.acciente.induction.resolver.ControllerResolver; import com.acciente.induction.resolver.RedirectResolver; import com.acciente.induction.resolver.ViewResolver; import com.acciente.induction.template.TemplatingEngine; import com.acciente.induction.util.ConstructorNotFoundException; import com.acciente.induction.util.MethodNotFoundException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; /** * This is the Induction dispatcher servlet. * * @created Feb 29, 2008 * * @author Adinath Raveendra Raj */ public class HttpDispatcher extends HttpServlet { private RequestInterceptorExecutor _oRequestInterceptorExecutor; private ControllerResolverExecutor _oControllerResolverExecutor; private ViewResolverExecutor _oViewResolverExecutor; private RedirectResolverExecutor _oRedirectResolverExecutor; private ControllerExecutor _oControllerExecutor; private ViewExecutor _oViewExecutor; private Log _oLog; /** * This method is called by the webcontainer to initialize this servlet * * @param oServletConfig web container-provided access to this servlet's configuration * @throws javax.servlet.ServletException */ public void init(ServletConfig oServletConfig) throws ServletException { super.init(oServletConfig); // first setup a logger _oLog = LogFactory.getLog(HttpDispatcher.class); Config oConfig; // load the configuration for the dispatcher try { oConfig = ConfigLoaderInitializer.getConfigLoader(oServletConfig).getConfig(); //System.out.println( "config: \n" + oConfig ); } catch (ClassNotFoundException e) { throw new ServletException("init-error: config-loader-initializer", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: config-loader-initializer", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: config-loader-initializer", e); } catch (InstantiationException e) { throw new ServletException("init-error: config-loader-initializer", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: config-loader-initializer", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: config-loader-initializer", e); } catch (ConfigLoaderException e) { throw new ServletException("init-error: config-loader", e); } // setup up our classloader ClassLoader oClassLoader; try { oClassLoader = ClassLoaderInitializer.getClassLoader(oConfig.getJavaClassPath(), getClass().getClassLoader()); } catch (ClassNotFoundException e) { throw new ServletException("init-error: class-loader-initializer", e); } // we setup the model factory and pool managers early since we now support inject models // into the initializers for the templating engine, controller resolver, view resolver and // redirect resolver ModelFactory oModelFactory = new ModelFactory(oClassLoader, oServletConfig, oConfig.getFileUpload()); ModelPool oModelPool; try { oModelPool = new ModelPool(oConfig.getModelDefs(), oModelFactory, oServletConfig.getServletContext()); } catch (MethodNotFoundException e) { throw new ServletException("init-error: model-pool", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: model-pool", e); } catch (ClassNotFoundException e) { throw new ServletException("init-error: model-pool", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: model-pool", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: model-pool", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: model-pool", e); } catch (InstantiationException e) { throw new ServletException("init-error: model-pool", e); } // now set the pool for the model factory to use in model-to-model injection oModelFactory.setModelPool(oModelPool); // we instantiate the templating engine early since we now support injecting the // TemplatingEngine instance into models TemplatingEngine oTemplatingEngine; try { oTemplatingEngine = TemplatingEngineInitializer.getTemplatingEngine(oConfig.getTemplating(), oModelPool, oClassLoader, oServletConfig); } catch (IOException e) { throw new ServletException("init-error: templating-engine-initializer", e); } catch (ClassNotFoundException e) { throw new ServletException("init-error: templating-engine-initializer", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: templating-engine-initializer", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: templating-engine-initializer", e); } catch (InstantiationException e) { throw new ServletException("init-error: templating-engine-initializer", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: templating-engine-initializer", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: templating-engine-initializer", e); } // after the templating engine is setup is we set the templating engine in the model factory, // to make it available to models or any of the other classes that can request it oModelFactory.setTemplatingEngine(oTemplatingEngine); // pre-initialize any app scope models that requested it Log oLog = LogFactory.getLog(ModelPool.class); for (Iterator oIter = oConfig.getModelDefs().getModelDefList().iterator(); oIter.hasNext();) { Config.ModelDefs.ModelDef oModelDef = (Config.ModelDefs.ModelDef) oIter.next(); if (oModelDef.isApplicationScope() && oModelDef.isInitOnStartUp()) { oLog.info("model-pool: initializing model: " + oModelDef.getModelClassName()); try { oModelPool.initAppModel(oModelDef.getModelClassName()); } catch (MethodNotFoundException e) { throw new ServletException("init-error: model-init-on-startup", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: model-init-on-startup", e); } catch (ClassNotFoundException e) { throw new ServletException("init-error: model-init-on-startup", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: model-init-on-startup", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: model-init-on-startup", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: model-init-on-startup", e); } catch (InstantiationException e) { throw new ServletException("init-error: model-init-on-startup", e); } } } // setup the interceptor chain try { RequestInterceptor[] oRequestInterceptorArray; oRequestInterceptorArray = RequestInterceptorInitializer.getRequestInterceptor( oConfig.getRequestInterceptors(), oModelPool, oClassLoader, oServletConfig); _oRequestInterceptorExecutor = new RequestInterceptorExecutor(oRequestInterceptorArray, new RequestInterceptorParameterProviderFactory(oModelPool, oConfig.getFileUpload(), oTemplatingEngine, oClassLoader)); } catch (ClassNotFoundException e) { throw new ServletException("init-error: request-interceptor-initializer", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: request-interceptor-initializer", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: request-interceptor-initializer", e); } catch (InstantiationException e) { throw new ServletException("init-error: request-interceptor-initializer", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: request-interceptor-initializer", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: request-interceptor-initializer", e); } // setup a resolver that maps a request to a controller try { ControllerResolver oControllerResolver; oControllerResolver = ControllerResolverInitializer.getControllerResolver( oConfig.getControllerResolver(), oConfig.getControllerMapping(), oModelPool, oClassLoader, oServletConfig); _oControllerResolverExecutor = new ControllerResolverExecutor(oControllerResolver, new ControllerResolverParameterProviderFactory(oModelPool, oConfig.getFileUpload(), oClassLoader)); } catch (ClassNotFoundException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } catch (InstantiationException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } catch (IOException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } catch (MethodNotFoundException e) { throw new ServletException("init-error: controller-resolver-initializer", e); } // setup a resolver that maps a request to a view try { ViewResolver oViewResolver; oViewResolver = ViewResolverInitializer.getViewResolver(oConfig.getViewResolver(), oConfig.getViewMapping(), oModelPool, oClassLoader, oServletConfig); _oViewResolverExecutor = new ViewResolverExecutor(oViewResolver, new ViewResolverParameterProviderFactory(oModelPool, oConfig.getFileUpload(), oClassLoader)); } catch (ClassNotFoundException e) { throw new ServletException("init-error: view-resolver-initializer", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: view-resolver-initializer", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: view-resolver-initializer", e); } catch (InstantiationException e) { throw new ServletException("init-error: view-resolver-initializer", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: view-resolver-initializer", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: view-resolver-initializer", e); } catch (IOException e) { throw new ServletException("init-error: view-resolver-initializer", e); } catch (MethodNotFoundException e) { throw new ServletException("init-error: view-resolver-initializer", e); } // setup a resolver that maps a redirect to a URL try { RedirectResolver oRedirectResolver; oRedirectResolver = RedirectResolverInitializer.getRedirectResolver(oConfig.getRedirectResolver(), oConfig.getRedirectMapping(), oModelPool, oClassLoader, oServletConfig); _oRedirectResolverExecutor = new RedirectResolverExecutor(oRedirectResolver, new RedirectResolverParameterProviderFactory(oModelPool, oConfig.getFileUpload(), oClassLoader)); } catch (ClassNotFoundException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } catch (InvocationTargetException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } catch (IllegalAccessException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } catch (InstantiationException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } catch (ConstructorNotFoundException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } catch (ParameterProviderException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } catch (IOException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } catch (MethodNotFoundException e) { throw new ServletException("init-error: redirect-resolver-initializer", e); } // tell the model pool of the redirect resolver, so that models can now request it oModelFactory.setRedirectResolver(_oRedirectResolverExecutor); // the ControllerPool manages a pool of controllers, reloading if the underlying controller def changes ControllerPool oControllerPool = new ControllerPool(oClassLoader, oServletConfig); // the ControllerExecutor manages the execution of controllers _oControllerExecutor = new ControllerExecutor(oControllerPool, new ControllerParameterProviderFactory( oModelPool, oConfig.getFileUpload(), oTemplatingEngine, _oRedirectResolverExecutor, oClassLoader)); // the ViewExecutor manages the loading (when needed) and processing of views ViewParameterProviderFactory oViewParameterProviderFactory = new ViewParameterProviderFactory(oModelPool, oConfig.getFileUpload(), oTemplatingEngine, _oRedirectResolverExecutor, oClassLoader); ViewFactory oViewFactory = new ViewFactory(oClassLoader, oViewParameterProviderFactory); // we have to delay setting this until here, since ViewParameterProviderFactory and // ViewFactory have a cyclical relationship oViewParameterProviderFactory.setViewFactory(oViewFactory); // finally create the view executor _oViewExecutor = new ViewExecutor(oViewFactory, oTemplatingEngine); } public void service(HttpServletRequest oRequest, HttpServletResponse oResponse) throws IOException { dispatchRequest(oRequest, oResponse); } public void dispatchRequest(HttpServletRequest oRequest, HttpServletResponse oResponse) throws IOException { try { // fire the preResolution interceptor dispatchInterceptors_preResolution(oRequest, oResponse); // first try to resolve the request to a controller if (!dispatchControllerRequest(oRequest, oResponse)) { // try to dispatch the request to a view if (!dispatchViewRequest(oRequest, oResponse)) { // even if we did not resolve to a contoller or view since we attempted resolution, // we fire the postResolution interceptor dispatchInterceptors_postResolution(oRequest, oResponse, null, null); throw new StopRequestProcessingSignal("dispatch-request", "Request did not resolve to a controller or view, path > " + oRequest.getPathInfo()); } } } catch (StopRequestProcessingSignal oSignal) { if (oSignal.isError()) { logAndRespond(oResponse, oSignal); } } } private void dispatchInterceptors_preResolution(HttpServletRequest oRequest, HttpServletResponse oResponse) throws StopRequestProcessingSignal { try { Object oInterceptorReturnValue = _oRequestInterceptorExecutor.preResolution(oRequest, oResponse); dispatchLastInterceptorReturnValue(oRequest, oResponse, null, null, oInterceptorReturnValue); } catch (StopRequestProcessingSignal e) { throw e; } catch (Throwable e) { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, null, null, false, e)) { throw new StopRequestProcessingSignal("dispatch-interceptors > pre-resolution", e); } } } private void dispatchInterceptors_postResolution(HttpServletRequest oRequest, HttpServletResponse oResponse, ControllerResolver.Resolution oControllerResolution, ViewResolver.Resolution oViewResolution) throws StopRequestProcessingSignal { try { Object oInterceptorReturnValue = _oRequestInterceptorExecutor.postResolution(oRequest, oResponse, oControllerResolution, oViewResolution); dispatchLastInterceptorReturnValue(oRequest, oResponse, oControllerResolution, oViewResolution, oInterceptorReturnValue); } catch (StopRequestProcessingSignal e) { throw e; } catch (Throwable e) { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, oViewResolution, false, e)) { throw new StopRequestProcessingSignal("dispatch-interceptors > post-resolution", e); } } } private void dispatchInterceptors_preResponse(HttpServletRequest oRequest, HttpServletResponse oResponse, ControllerResolver.Resolution oControllerResolution, ViewResolver.Resolution oViewResolution) throws StopRequestProcessingSignal { try { Object oInterceptorReturnValue = _oRequestInterceptorExecutor.preResponse(oRequest, oResponse, oControllerResolution, oViewResolution); dispatchLastInterceptorReturnValue(oRequest, oResponse, oControllerResolution, oViewResolution, oInterceptorReturnValue); } catch (StopRequestProcessingSignal e) { throw e; } catch (Throwable e) { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, oViewResolution, true, e)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal("dispatch-interceptors > pre-response", e); } } } private void dispatchInterceptors_postResponse(HttpServletRequest oRequest, HttpServletResponse oResponse, ControllerResolver.Resolution oControllerResolution, ViewResolver.Resolution oViewResolution) throws StopRequestProcessingSignal { try { Object oInterceptorReturnValue = _oRequestInterceptorExecutor.postResponse(oRequest, oResponse, oControllerResolution, oViewResolution); dispatchLastInterceptorReturnValue(oRequest, oResponse, oControllerResolution, oViewResolution, oInterceptorReturnValue); } catch (StopRequestProcessingSignal e) { throw e; } catch (Throwable e) { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, oViewResolution, true, e)) { throw new StopRequestProcessingSignal("dispatch-interceptors > post-response", e); } } } private void dispatchLastInterceptorReturnValue(HttpServletRequest oRequest, HttpServletResponse oResponse, ControllerResolver.Resolution oControllerResolution, ViewResolver.Resolution oViewResolution, Object oInterceptorReturnValue) throws StopRequestProcessingSignal { if (oInterceptorReturnValue != null) { if (oInterceptorReturnValue instanceof Boolean) { if (((Boolean) oInterceptorReturnValue).booleanValue()) { // if the last interceptor returns true, then stop further processing of the request, per our spec throw new StopRequestProcessingSignal(); } } else { try { // is it a redirect? if (!dispatchRedirect(oRequest, oResponse, oInterceptorReturnValue)) { // assume its a view dispatchViewClassOrInstance(oRequest, oResponse, oInterceptorReturnValue); } } catch (StopRequestProcessingSignal e1) { throw e1; } catch (ViewExecutorException e1) // exception thrown by dispatchViewClassOrInstance() { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, oViewResolution, true, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal( "dispatch-interceptor-return-value > during view execution", e1); } } catch (RedirectExecutorException e1) // exception thrown by dispatchRedirect() { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, oViewResolution, true, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal( "dispatch-interceptor-return-value > during redirect execution", e1); } } catch (Throwable e1) // other exception { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, oViewResolution, true, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal("dispatch-interceptor-return-value", e1); } } } } } private boolean dispatchControllerRequest(HttpServletRequest oRequest, HttpServletResponse oResponse) throws StopRequestProcessingSignal { ControllerResolver.Resolution oControllerResolution; // first try to resolve the request to a controller oControllerResolution = _oControllerResolverExecutor.resolveRequest(oRequest); if (oControllerResolution != null) { // fire the postResolution interceptor dispatchInterceptors_postResolution(oRequest, oResponse, oControllerResolution, null); // now execute the controller, this try/catch is to handle any exceptions thrown during controller execution Object oControllerReturnValue; try { oControllerReturnValue = _oControllerExecutor.execute(oControllerResolution, oRequest, oResponse, null); } catch (Throwable e1) { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, null, false, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal( "dispatch-controller-request > during controller execution", e1); } // the redundant stop signal below is to inform the compiler of the above fact to prevent it // from giving an error that oControllerReturnValue below may be uninitialized throw new StopRequestProcessingSignal(); } // process the controller's return value (if any) if (oControllerReturnValue != null) { // fire the preResponse interceptor dispatchInterceptors_preResponse(oRequest, oResponse, oControllerResolution, null); try { // is it a redirect? if (!dispatchRedirect(oRequest, oResponse, oControllerReturnValue)) { // otherwise assume it is a view dispatchViewClassOrInstance(oRequest, oResponse, oControllerReturnValue); } } catch (StopRequestProcessingSignal e1) { throw e1; } catch (ViewExecutorException e1) // exception thrown by dispatchViewClassOrInstance() { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, null, true, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal("dispatch-controller-request > during view execution", e1); } } catch (RedirectExecutorException e1) // exception thrown by dispatchRedirect() { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, null, true, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal( "dispatch-controller-request > during redirect execution", e1); } } catch (Throwable e1) // other exception thrown { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, oControllerResolution, null, true, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal("dispatch-controller-request", e1); } } // fire the postResponse interceptors dispatchInterceptors_postResponse(oRequest, oResponse, oControllerResolution, null); } return true; } return false; } private boolean dispatchViewRequest(HttpServletRequest oRequest, HttpServletResponse oResponse) throws StopRequestProcessingSignal { ViewResolver.Resolution oViewResolution; // try to resolve the request to a view oViewResolution = _oViewResolverExecutor.resolveRequest(oRequest); if (oViewResolution != null) { // fire the postResolution interceptor dispatchInterceptors_postResolution(oRequest, oResponse, null, oViewResolution); // fire the preResponse interceptor dispatchInterceptors_preResponse(oRequest, oResponse, null, oViewResolution); // now execute the view try { _oViewExecutor.execute(oViewResolution, oRequest, oResponse); } catch (Throwable e1) { // note that the dispatcher below raises a stop signal if it handled the error if (!dispatchErrorController(oRequest, oResponse, null, oViewResolution, true, e1)) { // there is no error handler!! so we resort to a stop signal with cause throw new StopRequestProcessingSignal("dispatch-view-request > during view execution", e1); } } // fire the postResponse interceptors dispatchInterceptors_postResponse(oRequest, oResponse, null, oViewResolution); return true; } return false; } private boolean dispatchErrorController(HttpServletRequest oRequest, HttpServletResponse oResponse, ControllerResolver.Resolution oControllerResolution, ViewResolver.Resolution oViewResolution, boolean bPreResponseInterceptorCalled, Throwable oError) throws StopRequestProcessingSignal { // there was an exception, first try to invoke the error handler controller (if any) ControllerResolver.Resolution oErrorControllerResolution; oErrorControllerResolution = _oControllerResolverExecutor.resolveThrowable(oRequest, getRootCause(oError)); if (oErrorControllerResolution != null) { Object oErrorControllerReturnValue; try { oErrorControllerReturnValue = _oControllerExecutor.execute(oErrorControllerResolution, oRequest, oResponse, oError); } catch (Throwable e1) { // there was an error executing the error handler!! so we abort throw new StopRequestProcessingSignal( "dispatch-error-controller > during error-handler-controller execution", e1); } // process the controller's return value (if any) if (oErrorControllerReturnValue != null) { // fire the preResponse interceptor if (!bPreResponseInterceptorCalled) { dispatchInterceptors_preResponse(oRequest, oResponse, oControllerResolution, oViewResolution); } // now process the return value of the error controller // otherwise assume it is a view try { // is it a redirect? if (!dispatchRedirect(oRequest, oResponse, oErrorControllerReturnValue)) { // otherwise assume that its a view dispatchViewClassOrInstance(oRequest, oResponse, oErrorControllerReturnValue); } } catch (StopRequestProcessingSignal e1) { throw e1; } catch (ViewExecutorException e1) { // there was an error executing the error handler!! so we abort throw new StopRequestProcessingSignal( "dispatch-error-controller > during execution of view returned by error-handler-controller", e1); } catch (RedirectExecutorException e1) { // there was an error executing the error handler!! so we abort throw new StopRequestProcessingSignal( "dispatch-error-controller > during execution of redirect returned by error-handler-controller", e1); } catch (Throwable e1) { // there was an error executing the error handler!! so we abort throw new StopRequestProcessingSignal( "dispatch-error-controller > during processing of value returned by error-handler-controller", e1); } // fire the postResponse interceptors dispatchInterceptors_postResponse(oRequest, oResponse, oControllerResolution, oViewResolution); // we sucessfully ran the error handler controller, so we are done with this request throw new StopRequestProcessingSignal(); } throw new StopRequestProcessingSignal(); } return false; } private void dispatchViewClassOrInstance(HttpServletRequest oRequest, HttpServletResponse oResponse, Object oControllerReturnValue) throws ViewExecutorException { // check if the value returned is a type ... if (oControllerReturnValue instanceof Class) { // if so process as a view type ... _oViewExecutor.execute((Class) oControllerReturnValue, oRequest, oResponse); } else { // ... otherwise process as a view object _oViewExecutor.execute(oControllerReturnValue, oResponse); } } private boolean dispatchRedirect(HttpServletRequest oRequest, HttpServletResponse oResponse, Object oReturnValue) throws StopRequestProcessingSignal, RedirectExecutorException { if (oReturnValue instanceof Redirect) { String sRedirectURL = _oRedirectResolverExecutor.resolveRedirect(oRequest, (Redirect) oReturnValue); if (sRedirectURL != null) { RedirectExecutor.redirect(oResponse, sRedirectURL); } else { // note that we are choosing to not call the error-handler controller here, wondering if // this is the right decision throw new StopRequestProcessingSignal("dispatch-redirect", "Could not resolve redirect request: " + oReturnValue); } throw new StopRequestProcessingSignal(); } return false; } private void logAndRespond(HttpServletResponse oResponse, StopRequestProcessingSignal oSignal) throws IOException { String sError; Throwable oErrorRootCause; // we try to be helpful and display the root cause of the error if (oSignal.getErrorCause() != null) { oErrorRootCause = oSignal.getErrorCause(); while (oErrorRootCause.getCause() != null && oErrorRootCause.getCause() != oErrorRootCause) { oErrorRootCause = oErrorRootCause.getCause(); } } else { oErrorRootCause = null; } if (oSignal.getErrorDescription() == null) { if (oErrorRootCause == null) { sError = "| Message: (none) | Cause: (none)"; } else { sError = "| Message: " + oErrorRootCause.getMessage() + " | Cause: " + oErrorRootCause.getClass(); } } else { sError = "| Message: " + oSignal.getErrorDescription() + " | Cause: (none)"; } if (oErrorRootCause != null) { _oLog.error("| Context: " + oSignal.getErrorContext() + sError, oErrorRootCause); } else { _oLog.error("| Context: " + oSignal.getErrorContext() + sError); } oResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sError); } private Throwable getRootCause(Throwable oError) { while (oError.getCause() != null && oError.getCause() != oError) { oError = oError.getCause(); } return oError; } public static class StopRequestProcessingSignal extends Exception { private String _bErrorContext; private String _bErrorDescription; private Throwable _oErrorCause; public StopRequestProcessingSignal() { } public StopRequestProcessingSignal(String bErrorContext, Throwable oErrorCause) { _bErrorContext = bErrorContext; _oErrorCause = oErrorCause; } public StopRequestProcessingSignal(String bErrorContext, String bErrorDescription) { _bErrorContext = bErrorContext; _bErrorDescription = bErrorDescription; } public boolean isError() { return _bErrorContext != null; } public String getErrorContext() { return _bErrorContext; } public String getErrorDescription() { return _bErrorDescription; } public Throwable getErrorCause() { return _oErrorCause; } } } // EOF