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

    1   /*
    2    * Copyright (c) 2002-2007 by OpenSymphony
    3    * All rights reserved.
    4    */
    5   package com.opensymphony.xwork2.interceptor;
    6   
    7   import com.opensymphony.xwork2.ActionInvocation;
    8   import com.opensymphony.xwork2.util.TextParseUtil;
    9   import com.opensymphony.xwork2.util.logging.Logger;
   10   import com.opensymphony.xwork2.util.logging.LoggerFactory;
   11   
   12   import java.util.Collection;
   13   import java.util.HashSet;
   14   import java.util.Map;
   15   import java.util.TreeMap;
   16   
   17   /**
   18    * <!-- START SNIPPET: description -->
   19    *
   20    * The Parameter Filter Interceptor blocks parameters from getting
   21    * to the rest of the stack or your action. You can use multiple 
   22    * parameter filter interceptors for a given action, so, for example,
   23    * you could use one in your default stack that filtered parameters
   24    * you wanted blocked from every action and those you wanted blocked 
   25    * from an individual action you could add an additional interceptor
   26    * for each action.
   27    * 
   28    * <!-- END SNIPPET: description -->
   29    * 
   30    * <!-- START SNIPPET: parameters -->
   31    *
   32    * <ul>
   33    * <li>allowed - a comma delimited list of parameter prefixes
   34    *  that are allowed to pass to the action</li>
   35    * <li>blocked - a comma delimited list of parameter prefixes 
   36    * that are not allowed to pass to the action</li>
   37    * <li>defaultBlock - boolean (default to false) whether by
   38    * default a given parameter is blocked. If true, then a parameter
   39    * must have a prefix in the allowed list in order to be able 
   40    * to pass to the action
   41    * </ul>
   42    * 
   43    * <p>The way parameters are filtered for the least configuration is that
   44    * if a string is in the allowed or blocked lists, then any parameter
   45    * that is a member of the object represented by the parameter is allowed
   46    * or blocked respectively.</p>
   47    * 
   48    * <p>For example, if the parameters are:
   49    * <ul>
   50    * <li>blocked: person,person.address.createDate,personDao</li>
   51    * <li>allowed: person.address</li>
   52    * <li>defaultBlock: false</li>
   53    * </ul>
   54    * <br>
   55    * The parameters person.name, person.phoneNum etc would be blocked 
   56    * because 'person' is in the blocked list. However, person.address.street
   57    * and person.address.city would be allowed because person.address is
   58    * in the allowed list (the longer string determines permissions).</p> 
   59    * <!-- END SNIPPET: parameters -->
   60    *
   61    * <!-- START SNIPPET: extending -->
   62    * There are no known extension points to this interceptor.
   63    * <!-- END SNIPPET: extending -->
   64    * 
   65    * <pre>
   66    * <!-- START SNIPPET: example -->
   67    * &lt;interceptors&gt;
   68    *   ...
   69    *   &lt;interceptor name="parameterFilter" class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/&gt;
   70    *   ...
   71    * &lt;/interceptors&gt;
   72    * 
   73    * &lt;action ....&gt;
   74    *   ...
   75    *   &lt;interceptor-ref name="parameterFilter"&gt;
   76    *     &lt;param name="blocked"&gt;person,person.address.createDate,personDao&lt;/param&gt;
   77    *   &lt;/interceptor-ref&gt;
   78    *   ...
   79    * &lt;/action&gt;
   80    * <!-- END SNIPPET: example -->
   81    * </pre>
   82    * 
   83    * @author Gabe
   84    */
   85   public class ParameterFilterInterceptor extends AbstractInterceptor {
   86   
   87       private static final Logger LOG = LoggerFactory.getLogger(ParameterFilterInterceptor.class);
   88   
   89       private Collection<String> allowed;
   90       private Collection<String> blocked;
   91       private Map<String, Boolean> includesExcludesMap;
   92       private boolean defaultBlock = false;
   93   
   94       @Override
   95       public String intercept(ActionInvocation invocation) throws Exception {
   96   
   97           Map<String, Object> parameters = invocation.getInvocationContext().getParameters();
   98           HashSet<String> paramsToRemove = new HashSet<String>();
   99   
  100           Map<String, Boolean> includesExcludesMap = getIncludesExcludesMap();
  101   
  102           for (Object o : parameters.keySet()) {
  103               String param = o.toString();
  104   
  105               boolean currentAllowed = !isDefaultBlock();
  106   
  107               boolean foundApplicableRule = false;
  108               for (Object o1 : includesExcludesMap.keySet()) {
  109                   String currRule = (String) o1;
  110   
  111                   if (param.startsWith(currRule)
  112                           && (param.length() == currRule.length()
  113                           || isPropSeperator(param.charAt(currRule.length())))) {
  114                       currentAllowed = includesExcludesMap.get(currRule).booleanValue();
  115                   } else {
  116                       if (foundApplicableRule) {
  117                           foundApplicableRule = false;
  118                           break;
  119                       }
  120                   }
  121               }
  122               if (!currentAllowed) {
  123                   paramsToRemove.add(param);
  124               }
  125           }
  126   
  127           if (LOG.isDebugEnabled()) {
  128               LOG.debug("Params to remove: " + paramsToRemove);
  129           }
  130   
  131           for (Object aParamsToRemove : paramsToRemove) {
  132               parameters.remove(aParamsToRemove);
  133           }
  134   
  135           return invocation.invoke();
  136       }
  137   
  138       /**
  139        * Tests if the given char is a property seperator char <code>.([</code>.
  140        *
  141        * @param c the char
  142        * @return <tt>true</tt>, if char is property separator, <tt>false</tt> otherwise.
  143        */
  144       private static boolean isPropSeperator(char c) {
  145           return c == '.' || c == '(' || c == '[';
  146       }
  147   
  148       private Map<String, Boolean> getIncludesExcludesMap() {
  149           if (this.includesExcludesMap == null) {
  150               this.includesExcludesMap = new TreeMap<String, Boolean>();
  151   
  152               if (getAllowedCollection() != null) {
  153                   for (String e : getAllowedCollection()) {
  154                       this.includesExcludesMap.put(e, Boolean.TRUE);
  155                   }
  156               }
  157               if (getBlockedCollection() != null) {
  158                   for (String b : getBlockedCollection()) {
  159                       this.includesExcludesMap.put(b, Boolean.FALSE);
  160                   }
  161               }
  162           }
  163   
  164           return this.includesExcludesMap;
  165       }
  166   
  167       /**
  168        * @return Returns the defaultBlock.
  169        */
  170       public boolean isDefaultBlock() {
  171           return defaultBlock;
  172       }
  173   
  174       /**
  175        * @param defaultExclude The defaultExclude to set.
  176        */
  177       public void setDefaultBlock(boolean defaultExclude) {
  178           this.defaultBlock = defaultExclude;
  179       }
  180   
  181       /**
  182        * @return Returns the blocked.
  183        */
  184       public Collection<String> getBlockedCollection() {
  185           return blocked;
  186       }
  187   
  188       /**
  189        * @param blocked The blocked to set.
  190        */
  191       public void setBlockedCollection(Collection<String> blocked) {
  192           this.blocked = blocked;
  193       }
  194   
  195       /**
  196        * @param blocked The blocked paramters as comma separated String.
  197        */
  198       public void setBlocked(String blocked) {
  199           setBlockedCollection(asCollection(blocked));
  200       }
  201   
  202       /**
  203        * @return Returns the allowed.
  204        */
  205       public Collection<String> getAllowedCollection() {
  206           return allowed;
  207       }
  208   
  209       /**
  210        * @param allowed The allowed to set.
  211        */
  212       public void setAllowedCollection(Collection<String> allowed) {
  213           this.allowed = allowed;
  214       }
  215   
  216       /**
  217        * @param allowed The allowed paramters as comma separated String.
  218        */
  219       public void setAllowed(String allowed) {
  220           setAllowedCollection(asCollection(allowed));
  221       }
  222   
  223       /**
  224        * Return a collection from the comma delimited String.
  225        *
  226        * @param commaDelim the comma delimited String.
  227        * @return A collection from the comma delimited String. Returns <tt>null</tt> if the string is empty.
  228        */
  229       private Collection<String> asCollection(String commaDelim) {
  230           if (commaDelim == null || commaDelim.trim().length() == 0) {
  231               return null;
  232           }
  233           return TextParseUtil.commaDelimitedStringToSet(commaDelim);
  234       }
  235   
  236   }

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