Save This Page
Home » struts-2.1.8.1-src » org.apache » struts2 » interceptor » [javadoc | source]
    1   /*
    2    * $Id: MessageStoreInterceptor.java 768855 2009-04-27 02:09:35Z wesw $
    3    *
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
   10    * with the License.  You may obtain a copy of the License at
   11    *
   12    *  http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing,
   15    * software distributed under the License is distributed on an
   16    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   17    * KIND, either express or implied.  See the License for the
   18    * specific language governing permissions and limitations
   19    * under the License.
   20    */
   21   
   22   package org.apache.struts2.interceptor;
   23   
   24   import java.util.ArrayList;
   25   import java.util.Collection;
   26   import java.util.LinkedHashMap;
   27   import java.util.Map;
   28   
   29   import org.apache.struts2.dispatcher.ServletRedirectResult;
   30   
   31   import com.opensymphony.xwork2.ActionContext;
   32   import com.opensymphony.xwork2.ActionInvocation;
   33   import com.opensymphony.xwork2.ValidationAware;
   34   import com.opensymphony.xwork2.interceptor.Interceptor;
   35   import com.opensymphony.xwork2.util.logging.Logger;
   36   import com.opensymphony.xwork2.util.logging.LoggerFactory;
   37   
   38   /**
   39    * <!-- START SNIPPET: description -->
   40    *
   41    * An interceptor to store a {@link ValidationAware} action's messages / errors and field errors into
   42    * HTTP Session, such that it will be retrieveable at a later stage. This allows the action's message /
   43    * errors and field errors to be available longer that just the particular HTTP request.
   44    *
   45    * <p/>
   46    *
   47    * In the 'STORE' mode, the interceptor will store the {@link ValidationAware} action's message / errors
   48    * and field errors into HTTP session.
   49    *
   50    * <p/>
   51    *
   52    * In the 'RETRIEVE' mode, the interceptor will retrieve the stored action's message / errors  and field
   53    * errors and put them back into the {@link ValidationAware} action.
   54    * 
   55    * <p/>
   56    *
   57    * In the 'AUTOMATIC' mode, the interceptor will always retrieve the stored action's message / errors 
   58    * and field errors and put them back into the {@link ValidationAware} action, and after Action execution, 
   59    * if the {@link Result} is an instance of {@link ServletRedirectResult}, the action's message / errors 
   60    * and field errors into automatically be stored in the HTTP session..
   61    *
   62    * <p/>
   63    *
   64    * The interceptor does nothing in the 'NONE' mode, which is the default.
   65    *
   66    * <p/>
   67    *
   68    * The operation mode could be switched using :- <p/>
   69    * 1] Setting the iterceptor parameter eg.
   70    * <pre>
   71    *   &lt;action name="submitApplication" ...&gt;
   72    *      &lt;interceptor-ref name="store"&gt;
   73    *         &lt;param name="operationMode"&gt;STORE&lt;/param&gt;
   74    *      &lt;/interceptor-ref&gt;
   75    *      &lt;interceptor-ref name="defaultStack" /&gt;
   76    *      ....
   77    *   &lt;/action&gt;
   78    * </pre>
   79    *
   80    * 2] Through request parameter (allowRequestParameterSwitch must be 'true' which is the default)
   81    * <pre>
   82    *   // the request will have the operation mode in 'STORE'
   83    *   http://localhost:8080/context/submitApplication.action?operationMode=STORE
   84    * </pre>
   85    *
   86    * <!-- END SNIPPET: description -->
   87    *
   88    *
   89    * <!-- START SNIPPET: parameters -->
   90    *
   91    * <ul>
   92    *      <li>allowRequestParameterSwitch - To enable request parameter that could switch the operation mode
   93    *                                        of this interceptor. </li>
   94    *      <li>requestParameterSwitch - The request parameter that will indicate what mode this
   95    *                                   interceptor is in. </li>
   96    *      <li>operationMode - The operation mode this interceptor should be in
   97    *                          (either 'STORE', 'RETRIEVE', 'AUTOMATIC', or 'NONE'). 'NONE' being the default.</li>
   98    * </ul>
   99    *
  100    * <!-- END SNIPPET: parameters -->
  101    *
  102    * <p/>
  103    *
  104    * <!-- START SNIPPET: extending -->
  105    *
  106    * The following method could be overriden :-
  107    * <ul>
  108    *  <li>getRequestOperationMode - get the operation mode of this interceptor based on the request parameters</li>
  109    *  <li>mergeCollection - merge two collections</li>
  110    *  <li>mergeMap - merge two map</li>
  111    * </ul>
  112    *
  113    * <!-- END SNIPPET: extending -->
  114    *
  115    * <pre>
  116    * <!-- START SNIPPET: example -->
  117    *
  118    * &lt;action name="submitApplication" ....&gt;
  119    *    &lt;interceptor-ref name="store"&gt;
  120    *      &lt;param name="operationMode">STORE&lt;/param&gt;
  121    *    &lt;/interceptor-ref&gt;
  122    *    &lt;interceptor-ref name="defaultStack" /&gt;
  123    *    &lt;result name="input" type="redirect">applicationFailed.action&lt;/result&gt;
  124    *    &lt;result type="dispatcher"&gt;applicationSuccess.jsp&lt;/result&gt;
  125    * &lt;/action&gt;
  126    *
  127    * &lt;action name="applicationFailed" ....&gt;
  128    *    &lt;interceptor-ref name="store"&gt;
  129    *       &lt;param name="operationMode"&gt;RETRIEVE&lt;/param&gt;
  130    *    &lt;/interceptor-ref&gt;
  131    *    &lt;result&gt;applicationFailed.jsp&lt;/result&gt;
  132    * &lt;/action&gt;
  133    *
  134    * <!-- END SNIPPET: example -->
  135    * </pre>
  136    *
  137    * <!-- START SNIPPET: exampleDescription -->
  138    *
  139    * With the example above, 'submitApplication.action' will have the action messages / errors / field errors stored
  140    * in the HTTP Session. Later when needed, (in this case, when 'applicationFailed.action' is fired, it
  141    * will get the action messages / errors / field errors stored in the HTTP Session and put them back into
  142    * the action.
  143    *
  144    * <!-- END SNIPPET: exampleDescription -->
  145    *
  146    * @version $Date: 2009-04-26 22:09:35 -0400 (Sun, 26 Apr 2009) $ $Id: MessageStoreInterceptor.java 768855 2009-04-27 02:09:35Z wesw $
  147    */
  148   public class MessageStoreInterceptor implements Interceptor {
  149   
  150       private static final long serialVersionUID = 4491997514314242420L;
  151   
  152       private static final Logger LOG = LoggerFactory.getLogger(MessageStoreInterceptor.class);
  153   
  154       public static final String AUTOMATIC_MODE = "AUTOMATIC";
  155       public static final String STORE_MODE = "STORE";
  156       public static final String RETRIEVE_MODE = "RETRIEVE";
  157       public static final String NONE = "NONE";
  158   
  159       private boolean allowRequestParameterSwitch = true;
  160       private String requestParameterSwitch = "operationMode";
  161       private String operationMode = NONE;
  162   
  163       public static final String fieldErrorsSessionKey = "__MessageStoreInterceptor_FieldErrors_SessionKey";
  164       public static final String actionErrorsSessionKey = "__MessageStoreInterceptor_ActionErrors_SessionKey";
  165       public static final String actionMessagesSessionKey = "__MessageStoreInterceptor_ActionMessages_SessionKey";
  166   
  167   
  168   
  169       public void setAllowRequestParameterSwitch(boolean allowRequestParameterSwitch) {
  170           this.allowRequestParameterSwitch = allowRequestParameterSwitch;
  171       }
  172       public boolean getAllowRequestParameterSwitch() {
  173           return this.allowRequestParameterSwitch;
  174       }
  175   
  176   
  177       public void setRequestParameterSwitch(String requestParameterSwitch) {
  178           this.requestParameterSwitch = requestParameterSwitch;
  179       }
  180       public String getRequestParameterSwitch() {
  181           return this.requestParameterSwitch;
  182       }
  183   
  184   
  185   
  186       public void setOperationMode(String operationMode) {
  187           this.operationMode = operationMode;
  188       }
  189       public String getOperationModel() {
  190           return this.operationMode;
  191       }
  192   
  193   
  194       public void destroy() {
  195       }
  196   
  197       public void init() {
  198       }
  199   
  200       public String intercept(ActionInvocation invocation) throws Exception {
  201           LOG.debug("entering MessageStoreInterceptor ...");
  202   
  203           before(invocation);
  204           String result = invocation.invoke();
  205           after(invocation, result);
  206   
  207           LOG.debug("exit executing MessageStoreInterceptor");
  208           return result;
  209       }
  210   
  211       /**
  212        * Handle the retrieving of field errors / action messages / field errors, which is
  213        * done before action invocation, and the <code>operationMode</code> is 'RETRIEVE'.
  214        *
  215        * @param invocation
  216        * @throws Exception
  217        */
  218       protected void before(ActionInvocation invocation) throws Exception {
  219           String reqOperationMode = getRequestOperationMode(invocation);
  220   
  221           if (RETRIEVE_MODE.equalsIgnoreCase(reqOperationMode) ||
  222                   RETRIEVE_MODE.equalsIgnoreCase(operationMode) ||
  223                   AUTOMATIC_MODE.equalsIgnoreCase(operationMode)) {
  224   
  225               Object action = invocation.getAction();
  226               if (action instanceof ValidationAware) {
  227                   // retrieve error / message from session
  228                   Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION);
  229                   ValidationAware validationAwareAction = (ValidationAware) action;
  230   
  231                   LOG.debug("retrieve error / message from session to populate into action ["+action+"]");
  232   
  233                   Collection actionErrors = (Collection) session.get(actionErrorsSessionKey);
  234                   Collection actionMessages = (Collection) session.get(actionMessagesSessionKey);
  235                   Map fieldErrors = (Map) session.get(fieldErrorsSessionKey);
  236   
  237                   if (actionErrors != null && actionErrors.size() > 0) {
  238                       Collection mergedActionErrors = mergeCollection(validationAwareAction.getActionErrors(), actionErrors);
  239                       validationAwareAction.setActionErrors(mergedActionErrors);
  240                   }
  241   
  242                   if (actionMessages != null && actionMessages.size() > 0) {
  243                       Collection mergedActionMessages = mergeCollection(validationAwareAction.getActionMessages(), actionMessages);
  244                       validationAwareAction.setActionMessages(mergedActionMessages);
  245                   }
  246   
  247                   if (fieldErrors != null && fieldErrors.size() > 0) {
  248                       Map mergedFieldErrors = mergeMap(validationAwareAction.getFieldErrors(), fieldErrors);
  249                       validationAwareAction.setFieldErrors(mergedFieldErrors);
  250                   }
  251                   session.remove(actionErrorsSessionKey);
  252                   session.remove(actionMessagesSessionKey);
  253                   session.remove(fieldErrorsSessionKey);
  254               }
  255           }
  256       }
  257   
  258       /**
  259        * Handle the storing of field errors / action messages / field errors, which is
  260        * done after action invocation, and the <code>operationMode</code> is in 'STORE'.
  261        *
  262        * @param invocation
  263        * @param result
  264        * @throws Exception
  265        */
  266       protected void after(ActionInvocation invocation, String result) throws Exception {
  267   
  268           String reqOperationMode = getRequestOperationMode(invocation);
  269           boolean isRedirect = invocation.getResult() instanceof ServletRedirectResult;
  270           if (STORE_MODE.equalsIgnoreCase(reqOperationMode) ||
  271                   STORE_MODE.equalsIgnoreCase(operationMode) ||
  272                   (AUTOMATIC_MODE.equalsIgnoreCase(operationMode) && isRedirect)) {
  273   
  274               Object action = invocation.getAction();
  275               if (action instanceof ValidationAware) {
  276                   // store error / messages into session
  277                   Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION);
  278   
  279                   LOG.debug("store action ["+action+"] error/messages into session ");
  280   
  281                   ValidationAware validationAwareAction = (ValidationAware) action;
  282                   session.put(actionErrorsSessionKey, validationAwareAction.getActionErrors());
  283                   session.put(actionMessagesSessionKey, validationAwareAction.getActionMessages());
  284                   session.put(fieldErrorsSessionKey, validationAwareAction.getFieldErrors());
  285               }
  286               else {
  287                   LOG.debug("Action ["+action+"] is not ValidationAware, no message / error that are storeable");
  288               }
  289           }
  290       }
  291   
  292   
  293       /**
  294        * Get the operationMode through request paramter, if <code>allowRequestParameterSwitch</code>
  295        * is 'true', else it simply returns 'NONE', meaning its neither in the 'STORE_MODE' nor
  296        * 'RETRIEVE_MODE'.
  297        *
  298        * @return String
  299        */
  300       protected String getRequestOperationMode(ActionInvocation invocation) {
  301           String reqOperationMode = NONE;
  302           if (allowRequestParameterSwitch) {
  303               Map reqParams = (Map) invocation.getInvocationContext().get(ActionContext.PARAMETERS);
  304               boolean containsParameter = reqParams.containsKey(requestParameterSwitch);
  305               if (containsParameter) {
  306                   String[] reqParamsArr = (String[]) reqParams.get(requestParameterSwitch);
  307                   if (reqParamsArr != null && reqParamsArr.length > 0) {
  308                       reqOperationMode = reqParamsArr[0];
  309                   }
  310               }
  311           }
  312           return reqOperationMode;
  313       }
  314   
  315       /**
  316        * Merge <code>col1</code> and <code>col2</code> and return the composite
  317        * <code>Collection</code>.
  318        *
  319        * @param col1
  320        * @param col2
  321        * @return Collection
  322        */
  323       protected Collection mergeCollection(Collection col1, Collection col2) {
  324           Collection _col1 = (col1 == null ? new ArrayList() : col1);
  325           Collection _col2 = (col2 == null ? new ArrayList() : col2);
  326           _col1.addAll(_col2);
  327           return _col1;
  328       }
  329   
  330       /**
  331        * Merge <code>map1</code> and <code>map2</code> and return the composite
  332        * <code>Map</code>
  333        *
  334        * @param map1
  335        * @param map2
  336        * @return Map
  337        */
  338       protected Map mergeMap(Map map1, Map map2) {
  339           Map _map1 = (map1 == null ? new LinkedHashMap() : map1);
  340           Map _map2 = (map2 == null ? new LinkedHashMap() : map2);
  341           _map1.putAll(_map2);
  342           return _map1;
  343       }
  344   
  345   }

Save This Page
Home » struts-2.1.8.1-src » org.apache » struts2 » interceptor » [javadoc | source]