Package com.acciente.induction.dispatcher

Source Code of com.acciente.induction.dispatcher.HttpDispatcher$StopRequestProcessingSignal

/*
* Copyright 2008-2011 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 )
      {
         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 )
      {
         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 )
      {
         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 )
      {
         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, 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();
         }

         return true;
      }

      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 );
   }

   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
TOP

Related Classes of com.acciente.induction.dispatcher.HttpDispatcher$StopRequestProcessingSignal

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.