Home » xwork-2.1.5 » com.opensymphony » xwork2 » interceptor » [javadoc | source]

    1   /*
    2    * Copyright (c) 2002-2006 by OpenSymphony
    3    * All rights reserved.
    4    */
    5   
    6   package com.opensymphony.xwork2.interceptor;
    7   
    8   import com.opensymphony.xwork2.ActionContext;
    9   import com.opensymphony.xwork2.ActionInvocation;
   10   import com.opensymphony.xwork2.ValidationAware;
   11   import com.opensymphony.xwork2.inject.Inject;
   12   import com.opensymphony.xwork2.config.entities.ActionConfig;
   13   import com.opensymphony.xwork2.util.ValueStack;
   14   import com.opensymphony.xwork2.util.ClearableValueStack;
   15   import com.opensymphony.xwork2.util.ValueStackFactory;
   16   import com.opensymphony.xwork2.util.LocalizedTextUtil;
   17   import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
   18   import com.opensymphony.xwork2.util.logging.Logger;
   19   import com.opensymphony.xwork2.util.logging.LoggerFactory;
   20   
   21   import java.util.Map;
   22   
   23   
   24   /**
   25    * <!-- START SNIPPET: description -->
   26    *
   27    * The aim of this Interceptor is to alias a named parameter to a different named parameter. By acting as the glue
   28    * between actions sharing similiar parameters (but with different names), it can help greatly with action chaining.
   29    *
   30    * <p/>  Action's alias expressions should be in the form of  <code>#{ "name1" : "alias1", "name2" : "alias2" }</code>.
   31    * This means that assuming an action (or something else in the stack) has a value for the expression named <i>name1</i> and the
   32    * action this interceptor is applied to has a setter named <i>alias1</i>, <i>alias1</i> will be set with the value from
   33    * <i>name1</i>.
   34    *
   35    * <!-- END SNIPPET: description -->
   36    *
   37    * <p/> <u>Interceptor parameters:</u>
   38    *
   39    * <!-- START SNIPPET: parameters -->
   40    *
   41    * <ul>
   42    *
   43    * <li>aliasesKey (optional) - the name of the action parameter to look for the alias map (by default this is
   44    * <i>aliases</i>).</li>
   45    *
   46    * </ul>
   47    *
   48    * <!-- END SNIPPET: parameters -->
   49    *
   50    * <p/> <u>Extending the interceptor:</u>
   51    *
   52    * <p/>
   53    *
   54    * <!-- START SNIPPET: extending -->
   55    *
   56    * This interceptor does not have any known extension points.
   57    *
   58    * <!-- END SNIPPET: extending -->
   59    *
   60    * <p/> <u>Example code:</u>
   61    *
   62    * <pre>
   63    * <!-- START SNIPPET: example -->
   64    * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
   65    *     &lt;!-- The value for the foo parameter will be applied as if it were named bar --&gt;
   66    *     &lt;param name="aliases"&gt;#{ 'foo' : 'bar' }&lt;/param&gt;
   67    *
   68    *     &lt;interceptor-ref name="alias"/&gt;
   69    *     &lt;interceptor-ref name="basicStack"/&gt;
   70    *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
   71    * &lt;/action&gt;
   72    * <!-- END SNIPPET: example -->
   73    * </pre>
   74    *
   75    * @author Matthew Payne
   76    */
   77   public class AliasInterceptor extends AbstractInterceptor {
   78   
   79       private static final Logger LOG = LoggerFactory.getLogger(AliasInterceptor.class);
   80   
   81       private static final String DEFAULT_ALIAS_KEY = "aliases";
   82       protected String aliasesKey = DEFAULT_ALIAS_KEY;
   83   
   84       protected ValueStackFactory valueStackFactory;
   85       static boolean devMode = false;
   86   
   87       @Inject("devMode")
   88       public static void setDevMode(String mode) {
   89           devMode = "true".equals(mode);
   90       }   
   91   
   92       @Inject
   93       public void setValueStackFactory(ValueStackFactory valueStackFactory) {
   94           this.valueStackFactory = valueStackFactory;
   95       }
   96   
   97       /**
   98        * Sets the name of the action parameter to look for the alias map.
   99        * <p/>
  100        * Default is <code>aliases</code>.
  101        *
  102        * @param aliasesKey  the name of the action parameter
  103        */
  104       public void setAliasesKey(String aliasesKey) {
  105           this.aliasesKey = aliasesKey;
  106       }
  107   
  108       @Override public String intercept(ActionInvocation invocation) throws Exception {
  109   
  110           ActionConfig config = invocation.getProxy().getConfig();
  111           ActionContext ac = invocation.getInvocationContext();
  112           Object action = invocation.getAction();
  113   
  114           // get the action's parameters
  115           final Map<String, String> parameters = config.getParams();
  116   
  117           if (parameters.containsKey(aliasesKey)) {
  118   
  119               String aliasExpression = parameters.get(aliasesKey);
  120               ValueStack stack = ac.getValueStack();
  121               Object obj = stack.findValue(aliasExpression);
  122   
  123               if (obj != null && obj instanceof Map) {
  124                   //get secure stack
  125                   ValueStack newStack = valueStackFactory.createValueStack(stack);
  126                   boolean clearableStack = newStack instanceof ClearableValueStack;
  127                   if (clearableStack) {
  128                       //if the stack's context can be cleared, do that to prevent OGNL
  129                       //from having access to objects in the stack, see XW-641
  130                       ((ClearableValueStack)newStack).clearContextValues();
  131                       Map<String, Object> context = newStack.getContext();
  132                       ReflectionContextState.setCreatingNullObjects(context, true);
  133                       ReflectionContextState.setDenyMethodExecution(context, true);
  134                       ReflectionContextState.setReportingConversionErrors(context, true);
  135   
  136                       //keep locale from original context
  137                       context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
  138                   }
  139   
  140                   // override
  141                   Map aliases = (Map) obj;
  142                   for (Object o : aliases.entrySet()) {
  143                       Map.Entry entry = (Map.Entry) o;
  144                       String name = entry.getKey().toString();
  145                       String alias = (String) entry.getValue();
  146                       Object value = stack.findValue(name);
  147                       if (null == value) {
  148                           // workaround
  149                           Map<String, Object> contextParameters = ActionContext.getContext().getParameters();
  150   
  151                           if (null != contextParameters) {
  152                               value = contextParameters.get(name);
  153                           }
  154                       }
  155                       if (null != value) {
  156                           try {
  157                               newStack.setValue(alias, value);
  158                           } catch (RuntimeException e) {
  159                               if (devMode) {
  160                                   String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{
  161                                           "Unexpected Exception caught setting '" + entry.getKey() + "' on '" + action.getClass() + ": " + e.getMessage()
  162                                   });
  163                                   LOG.error(developerNotification);
  164                                   if (action instanceof ValidationAware) {
  165                                       ((ValidationAware) action).addActionMessage(developerNotification);
  166                                   }
  167                               }
  168                           }
  169                       }
  170                   }
  171   
  172                   if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))
  173                       stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS));
  174               } else {
  175                   LOG.debug("invalid alias expression:" + aliasesKey);
  176               }
  177           }
  178           
  179           return invocation.invoke();
  180       }
  181       
  182   }

Home » xwork-2.1.5 » com.opensymphony » xwork2 » interceptor » [javadoc | source]