Monday, August 29, 2011

Dispatch Class source code in struts Api org.apache.struts



    1   /*
    2    * $Id: DispatchAction.java 384089 2006-03-08 01:50:52Z niallp $
    3    *
    4    * Copyright 2001-2006 The Apache Software Foundation.
    5    *
    6    * Licensed under the Apache License, Version 2.0 (the "License");
    7    * you may not use this file except in compliance with the License.
    8    * You may obtain a copy of the License at
    9    *
   10    *      http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing, software
   13    * distributed under the License is distributed on an "AS IS" BASIS,
   14    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15    * See the License for the specific language governing permissions and
   16    * limitations under the License.
   17    */
   18  
   19   package org.apache.struts.actions;
   20  
   21   import java.lang.reflect.InvocationTargetException;
   22   import java.lang.reflect.Method;
   23   import java.util.HashMap;
   24  
   25   import javax.servlet.ServletException;
   26   import javax.servlet.http.HttpServletRequest;
   27   import javax.servlet.http.HttpServletResponse;
   28  
   29   import org.apache.commons.logging.Log;
   30   import org.apache.commons.logging.LogFactory;
   31   import org.apache.struts.action.Action;
   32   import org.apache.struts.action.ActionForm;
   33   import org.apache.struts.action.ActionForward;
   34   import org.apache.struts.action.ActionMapping;
   35   import org.apache.struts.util.MessageResources;
   36  
   37   /**
   38    *
An abstract Action that dispatches to a public
   39    * method that is named by the request parameter whose name is specified
   40    * by the parameter property of the corresponding
   41    * ActionMapping.  This Action is useful for developers who prefer to
   42    * combine many similar actions into a single Action class, in order to
   43    * simplify their application design.

   44    *
   45    * To configure the use of this action in your
   46    * struts-config.xml file, create an entry like this:

   47    *
   48    *
   49    *   <action path="/saveSubscription"
   50    *           type="org.apache.struts.actions.DispatchAction"
   51    *           name="subscriptionForm"
   52    *          scope="request"
   53    *          input="/subscription.jsp"
   54    *      parameter="method"/>
   55    *

   56    *
   57    * which will use the value of the request parameter named "method"
   58    * to pick the appropriate "execute" method, which must have the same
   59    * signature (other than method name) of the standard Action.execute
   60    * method.  For example, you might have the following three methods in the
   61    * same action:

   62    *
       63    *
  • public ActionForward delete(ActionMapping mapping, ActionForm form,
       64    *     HttpServletRequest request, HttpServletResponse response)
       65    *     throws Exception


  •    66    *
  • public ActionForward insert(ActionMapping mapping, ActionForm form,
       67    *     HttpServletRequest request, HttpServletResponse response)
       68    *     throws Exception


  •    69    *
  • public ActionForward update(ActionMapping mapping, ActionForm form,
       70    *     HttpServletRequest request, HttpServletResponse response)
       71    *     throws Exception


  •    72    *

   73    * and call one of the methods with a URL like this:

   74    *
   75    *   http://localhost:8080/myapp/saveSubscription.do?method=update
   76    *

   77    *
   78    * NOTE - All of the other mapping characteristics of
   79    * this action must be shared by the various handlers.  This places some
   80    * constraints over what types of handlers may reasonably be packaged into
   81    * the same DispatchAction subclass.

   82    *
   83    * NOTE - If the value of the request parameter is empty,
   84    * a method named unspecified is called. The default action is
   85    * to throw an exception. If the request was cancelled (a html:cancel
   86    * button was pressed), the custom handler cancelled will be used instead.
   87    * You can also override the getMethodName method to override the action's
   88    * default handler selection.

   89    *
   90    * @version $Rev: 384089 $ $Date: 2006-03-08 01:50:52 +0000 (Wed, 08 Mar 2006) $
   91    */
   92   public abstract class DispatchAction extends Action {
   93  
   94  
   95       // ----------------------------------------------------- Instance Variables
   96  
   97  
   98       /**
   99        * The Class instance of this DispatchAction class.
  100        */
  101       protected Class clazz = this.getClass();
  102  
  103  
  104       /**
  105        * Commons Logging instance.
  106        */
  107       protected static Log log = LogFactory.getLog(DispatchAction.class);
  108  
  109  
  110       /**
  111        * The message resources for this package.
  112        */
  113       protected static MessageResources messages =
  114               MessageResources.getMessageResources
  115               ("org.apache.struts.actions.LocalStrings");
  116  
  117  
  118       /**
  119        * The set of Method objects we have introspected for this class,
  120        * keyed by method name.  This collection is populated as different
  121        * methods are called, so that introspection needs to occur only
  122        * once per method name.
  123        */
  124       protected HashMap methods = new HashMap();
  125  
  126  
  127       /**
  128        * The set of argument type classes for the reflected method call.  These
  129        * are the same for all calls, so calculate them only once.
  130        */
  131       protected Class[] types =
  132               {
  133                   ActionMapping.class,
  134                   ActionForm.class,
  135                   HttpServletRequest.class,
  136                   HttpServletResponse.class};
  137  
  138  
  139  
  140       // --------------------------------------------------------- Public Methods
  141  
  142  
  143       /**
  144        * Process the specified HTTP request, and create the corresponding HTTP
  145        * response (or forward to another web component that will create it).
  146        * Return an ActionForward instance describing where and how
  147        * control should be forwarded, or null if the response has
  148        * already been completed.
  149        *
  150        * @param mapping The ActionMapping used to select this instance
  151        * @param form The optional ActionForm bean for this request (if any)
  152        * @param request The HTTP request we are processing
  153        * @param response The HTTP response we are creating
  154        *
  155        * @exception Exception if an exception occurs
  156        */
  157       public ActionForward execute(ActionMapping mapping,
  158                                    ActionForm form,
  159                                    HttpServletRequest request,
  160                                    HttpServletResponse response)
  161               throws Exception {
  162           if (isCancelled(request)) {
  163               ActionForward af = cancelled(mapping, form, request, response);
  164               if (af != null) {
  165                   return af;
  166               }
  167           }
  168  
  169           // Get the parameter. This could be overridden in subclasses.
  170           String parameter = getParameter(mapping, form, request, response);
  171  
  172           // Get the method's name. This could be overridden in subclasses.
  173           String name = getMethodName(mapping, form, request, response, parameter);
  174  
  175  
  176       // Prevent recursive calls
  177       if ("execute".equals(name) || "perform".equals(name)){
  178           String message =
  179               messages.getMessage("dispatch.recursive", mapping.getPath());
  180  
  181           log.error(message);
  182           throw new ServletException(message);
  183       }
  184  
  185  
  186           // Invoke the named method, and return the result
  187           return dispatchMethod(mapping, form, request, response, name);
  188  
  189       }
  190  
  191  
  192  
  193      
  194       /**
  195        * Method which is dispatched to when there is no value for specified
  196        * request parameter included in the request.  Subclasses of
  197        * DispatchAction should override this method if they wish
  198        * to provide default behavior different than throwing a ServletException.
  199        */
  200       protected ActionForward unspecified(
  201               ActionMapping mapping,
  202               ActionForm form,
  203               HttpServletRequest request,
  204               HttpServletResponse response)
  205               throws Exception {
  206  
  207           String message =
  208                   messages.getMessage(
  209                           "dispatch.parameter",
  210                           mapping.getPath(),
  211                           mapping.getParameter());
  212  
  213           log.error(message);
  214  
  215           throw new ServletException(message);
  216       }
  217  
  218       /**
  219        * Method which is dispatched to when the request is a cancel button submit.
  220        * Subclasses of DispatchAction should override this method if
  221        * they wish to provide default behavior different than returning null.
  222        * @since Struts 1.2.0
  223        */
  224       protected ActionForward cancelled(ActionMapping mapping,
  225                                         ActionForm form,
  226                                         HttpServletRequest request,
  227                                         HttpServletResponse response)
  228               throws Exception {
  229  
  230           return null;
  231       }
  232  
  233       // ----------------------------------------------------- Protected Methods
  234  
  235  
  236       /**
  237        * Dispatch to the specified method.
  238        * @since Struts 1.1
  239        */
  240       protected ActionForward dispatchMethod(ActionMapping mapping,
  241                                              ActionForm form,
  242                                              HttpServletRequest request,
  243                                              HttpServletResponse response,
  244                                              String name) throws Exception {
  245  
  246           // Make sure we have a valid method name to call.
  247           // This may be null if the user hacks the query string.
  248           if (name == null) {
  249               return this.unspecified(mapping, form, request, response);
  250           }
  251  
  252           // Identify the method object to be dispatched to
  253           Method method = null;
  254           try {
  255               method = getMethod(name);
  256  
  257           } catch(NoSuchMethodException e) {
  258               String message =
  259                       messages.getMessage("dispatch.method", mapping.getPath(), name);
  260               log.error(message, e);
  261  
  262               String userMsg =
  263                   messages.getMessage("dispatch.method.user", mapping.getPath());
  264               throw new NoSuchMethodException(userMsg);
  265           }
  266  
  267           ActionForward forward = null;
  268           try {
  269               Object args[] = {mapping, form, request, response};
  270               forward = (ActionForward) method.invoke(this, args);
  271  
  272           } catch(ClassCastException e) {
  273               String message =
  274                       messages.getMessage("dispatch.return", mapping.getPath(), name);
  275               log.error(message, e);
  276               throw e;
  277  
  278           } catch(IllegalAccessException e) {
  279               String message =
  280                       messages.getMessage("dispatch.error", mapping.getPath(), name);
  281               log.error(message, e);
  282               throw e;
  283  
  284           } catch(InvocationTargetException e) {
  285               // Rethrow the target exception if possible so that the
  286               // exception handling machinery can deal with it
  287               Throwable t = e.getTargetException();
  288               if (t instanceof Exception) {
  289                   throw ((Exception) t);
  290               } else {
  291                   String message =
  292                           messages.getMessage("dispatch.error", mapping.getPath(), name);
  293                   log.error(message, e);
  294                   throw new ServletException(t);
  295               }
  296           }
  297  
  298           // Return the returned ActionForward instance
  299           return (forward);
  300       }
  301  
  302       /**
  303        * Returns the parameter value.

  304        *
  305        * @param mapping  The ActionMapping used to select this instance
  306        * @param form     The optional ActionForm bean for this request (if any)
  307        * @param request  The HTTP request we are processing
  308        * @param response The HTTP response we are creating
  309        * @return The ActionMapping parameter's value
  310        * @throws Exception if the parameter is missing.
  311        */
  312       protected String getParameter(ActionMapping mapping, ActionForm form,
  313           HttpServletRequest request, HttpServletResponse response)
  314           throws Exception {
  315  
  316           // Identify the request parameter containing the method name
  317           String parameter = mapping.getParameter();
  318  
  319           if (parameter == null) {
  320               String message =
  321                   messages.getMessage("dispatch.handler", mapping.getPath());
  322  
  323               log.error(message);
  324  
  325               throw new ServletException(message);
  326           }
  327  
  328  
  329           return parameter;
  330       }
  331  
  332       /**
  333        * Introspect the current class to identify a method of the specified
  334        * name that accepts the same parameter types as the execute
  335        * method does.
  336        *
  337        * @param name Name of the method to be introspected
  338        *
  339        * @exception NoSuchMethodException if no such method can be found
  340        */
  341       protected Method getMethod(String name)
  342               throws NoSuchMethodException {
  343  
  344           synchronized(methods) {
  345               Method method = (Method) methods.get(name);
  346               if (method == null) {
  347                   method = clazz.getMethod(name, types);
  348                   methods.put(name, method);
  349               }
  350               return (method);
  351           }
  352  
  353       }
  354  
  355       /**
  356        * Returns the method name, given a parameter's value.
  357        *
  358        * @param mapping The ActionMapping used to select this instance
  359        * @param form The optional ActionForm bean for this request (if any)
  360        * @param request The HTTP request we are processing
  361        * @param response The HTTP response we are creating
  362        * @param parameter The ActionMapping parameter's name
  363        *
  364        * @return The method's name.
  365        * @since Struts 1.2.0
  366        */
  367       protected String getMethodName(ActionMapping mapping,
  368                                      ActionForm form,
  369                                      HttpServletRequest request,
  370                                      HttpServletResponse response,
  371                                      String parameter)
  372               throws Exception {
  373  
  374           // Identify the method name to be dispatched to.
  375           // dispatchMethod() will call unspecified() if name is null
  376           return request.getParameter(parameter);
  377       }
  378  
  379   }

No comments:

Post a Comment