Save This Page
Home » xwork-2.1.5 » com.opensymphony » xwork2 » validator » [javadoc | source]
    1   /*
    2    * Copyright (c) 2002-2007 by OpenSymphony
    3    * All rights reserved.
    4    */
    5   package com.opensymphony.xwork2.validator;
    6   
    7   import com.opensymphony.xwork2.ActionInvocation;
    8   import com.opensymphony.xwork2.ActionProxy;
    9   import com.opensymphony.xwork2.Validateable;
   10   import com.opensymphony.xwork2.inject.Inject;
   11   import com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor;
   12   import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
   13   import com.opensymphony.xwork2.interceptor.PrefixMethodInvocationUtil;
   14   import com.opensymphony.xwork2.util.logging.Logger;
   15   import com.opensymphony.xwork2.util.logging.LoggerFactory;
   16   
   17   /**
   18    * <!-- START SNIPPET: description -->
   19    *
   20    * This interceptor runs the action through the standard validation framework, which in turn checks the action against
   21    * any validation rules (found in files such as <i>ActionClass-validation.xml</i>) and adds field-level and action-level
   22    * error messages (provided that the action implements {@link com.opensymphony.xwork2.ValidationAware}). This interceptor
   23    * is often one of the last (or second to last) interceptors applied in a stack, as it assumes that all values have
   24    * already been set on the action.
   25    *
   26    * <p/>This interceptor does nothing if the name of the method being invoked is specified in the <b>excludeMethods</b>
   27    * parameter. <b>excludeMethods</b> accepts a comma-delimited list of method names. For example, requests to
   28    * <b>foo!input.action</b> and <b>foo!back.action</b> will be skipped by this interceptor if you set the
   29    * <b>excludeMethods</b> parameter to "input, back".
   30    * 
   31    * </ol>
   32    * 
   33    * <p/> The workflow of the action request does not change due to this interceptor. Rather,
   34    * this interceptor is often used in conjuction with the <b>workflow</b> interceptor.
   35    *
   36    * <p/>
   37    * 
   38    * <b>NOTE:</b> As this method extends off MethodFilterInterceptor, it is capable of
   39    * deciding if it is applicable only to selective methods in the action class. See
   40    * <code>MethodFilterInterceptor</code> for more info.
   41    *
   42    * <!-- END SNIPPET: description -->
   43    *
   44    * <p/> <u>Interceptor parameters:</u>
   45    *
   46    * <!-- START SNIPPET: parameters -->
   47    *
   48    * <ul>
   49    *
   50    * <li>alwaysInvokeValidate - Defaults to true. If true validate() method will always
   51    * be invoked, otherwise it will not.</li>
   52    *
   53    * <li>programmatic - Defaults to true. If true and the action is Validateable call validate(),
   54    * and any method that starts with "validate".
   55    * </li>
   56    * 
   57    * <li>declarative - Defaults to true. Perform validation based on xml or annotations.</li>
   58    * 
   59    * </ul>
   60    *
   61    * <!-- END SNIPPET: parameters -->
   62    *
   63    * <p/> <u>Extending the interceptor:</u>
   64    *
   65    * <p/>
   66    *
   67    * <!-- START SNIPPET: extending -->
   68    *
   69    * There are no known extension points for this interceptor.
   70    *
   71    * <!-- END SNIPPET: extending -->
   72    *
   73    * <p/> <u>Example code:</u>
   74    *
   75    * <pre>
   76    * <!-- START SNIPPET: example -->
   77    * 
   78    * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
   79    *     &lt;interceptor-ref name="params"/&gt;
   80    *     &lt;interceptor-ref name="validation"/&gt;
   81    *     &lt;interceptor-ref name="workflow"/&gt;
   82    *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
   83    * &lt;/action&gt;
   84    * 
   85    * &lt;-- in the following case myMethod of the action class will not
   86    *        get validated --&gt;
   87    * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
   88    *     &lt;interceptor-ref name="params"/&gt;
   89    *     &lt;interceptor-ref name="validation"&gt;
   90    *         &lt;param name="excludeMethods"&gt;myMethod&lt;/param&gt;
   91    *     &lt;/interceptor-ref&gt;
   92    *     &lt;interceptor-ref name="workflow"/&gt;
   93    *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
   94    * &lt;/action&gt;
   95    * 
   96    * &lt;-- in the following case only annotated methods of the action class will
   97    *        be validated --&gt;
   98    * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
   99    *     &lt;interceptor-ref name="params"/&gt;
  100    *     &lt;interceptor-ref name="validation"&gt;
  101    *         &lt;param name="validateAnnotatedMethodOnly"&gt;true&lt;/param&gt;
  102    *     &lt;/interceptor-ref&gt;
  103    *     &lt;interceptor-ref name="workflow"/&gt;
  104    *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
  105    * &lt;/action&gt;
  106    *
  107    *
  108    * <!-- END SNIPPET: example -->
  109    * </pre>
  110    *
  111    * @author Jason Carreira
  112    * @author Rainer Hermanns
  113    * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
  114    * @see ActionValidatorManager
  115    * @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
  116    */
  117   public class ValidationInterceptor extends MethodFilterInterceptor {
  118   
  119       private boolean validateAnnotatedMethodOnly;
  120       
  121       private ActionValidatorManager actionValidatorManager;
  122       
  123       private static final Logger LOG = LoggerFactory.getLogger(ValidationInterceptor.class);
  124       
  125       private final static String VALIDATE_PREFIX = "validate";
  126       private final static String ALT_VALIDATE_PREFIX = "validateDo";
  127       
  128       private boolean alwaysInvokeValidate = true;
  129       private boolean programmatic = true;
  130       private boolean declarative = true;
  131   
  132       @Inject
  133       public void setActionValidatorManager(ActionValidatorManager mgr) {
  134           this.actionValidatorManager = mgr;
  135       }
  136       
  137       /**
  138        * Determines if {@link Validateable}'s <code>validate()</code> should be called,
  139        * as well as methods whose name that start with "validate". Defaults to "true".
  140        * 
  141        * @param programmatic <tt>true</tt> then <code>validate()</code> is invoked.
  142        */
  143       public void setProgrammatic(boolean programmatic) {
  144           this.programmatic = programmatic;
  145       }
  146   
  147       /**
  148        * Determines if validation based on annotations or xml should be performed. Defaults 
  149        * to "true".
  150        * 
  151        * @param declarative <tt>true</tt> then perform validation based on annotations or xml.
  152        */
  153       public void setDeclarative(boolean declarative) {
  154           this.declarative = declarative;
  155       }
  156   
  157       /**
  158        * Determines if {@link Validateable}'s <code>validate()</code> should always 
  159        * be invoked. Default to "true".
  160        * 
  161        * @param alwaysInvokeValidate <tt>true</tt> then <code>validate()</code> is always invoked.
  162        */
  163       public void setAlwaysInvokeValidate(String alwaysInvokeValidate) {
  164               this.alwaysInvokeValidate = Boolean.parseBoolean(alwaysInvokeValidate);
  165       }
  166   
  167       /**
  168        * Gets if <code>validate()</code> should always be called or only per annotated method.
  169        *
  170        * @return <tt>true</tt> to only validate per annotated method, otherwise <tt>false</tt> to always validate.
  171        */
  172       public boolean isValidateAnnotatedMethodOnly() {
  173           return validateAnnotatedMethodOnly;
  174       }
  175   
  176       /**
  177        * Determine if <code>validate()</code> should always be called or only per annotated method.
  178        * Default to <tt>false</tt>.
  179        *
  180        * @param validateAnnotatedMethodOnly  <tt>true</tt> to only validate per annotated method, otherwise <tt>false</tt> to always validate.
  181        */
  182       public void setValidateAnnotatedMethodOnly(boolean validateAnnotatedMethodOnly) {
  183           this.validateAnnotatedMethodOnly = validateAnnotatedMethodOnly;
  184       }
  185   
  186       /**
  187        * Gets the current action and its context and delegates to {@link ActionValidatorManager} proper validate method.
  188        *
  189        * @param invocation  the execution state of the Action.
  190        * @throws Exception if an error occurs validating the action.
  191        */
  192       protected void doBeforeInvocation(ActionInvocation invocation) throws Exception {
  193           Object action = invocation.getAction();
  194           ActionProxy proxy = invocation.getProxy();
  195   
  196           //the action name has to be from the url, otherwise validators that use aliases, like
  197           //MyActio-someaction-validator.xml will not be found, see WW-3194
  198           String context = proxy.getActionName();
  199           String method = proxy.getMethod();
  200   
  201           if (log.isDebugEnabled()) {
  202               log.debug("Validating "
  203                       + invocation.getProxy().getNamespace() + "/" + invocation.getProxy().getActionName() + " with method "+ method +".");
  204           }
  205           
  206   
  207           if (declarative) {
  208              if (validateAnnotatedMethodOnly) {
  209                  actionValidatorManager.validate(action, context, method);
  210              } else {
  211                  actionValidatorManager.validate(action, context);
  212              }
  213          }    
  214           
  215           if (action instanceof Validateable && programmatic) {
  216               // keep exception that might occured in validateXXX or validateDoXXX
  217               Exception exception = null; 
  218               
  219               Validateable validateable = (Validateable) action;
  220               if (LOG.isDebugEnabled()) {
  221                   LOG.debug("Invoking validate() on action "+validateable);
  222               }
  223               
  224               try {
  225                   PrefixMethodInvocationUtil.invokePrefixMethod(
  226                                   invocation, 
  227                                   new String[] { VALIDATE_PREFIX, ALT_VALIDATE_PREFIX });
  228               }
  229               catch(Exception e) {
  230                   // If any exception occurred while doing reflection, we want 
  231                   // validate() to be executed
  232                   LOG.warn("an exception occured while executing the prefix method", e);
  233                   exception = e;
  234               }
  235               
  236               
  237               if (alwaysInvokeValidate) {
  238                   validateable.validate();
  239               }
  240               
  241               if (exception != null) { 
  242                   // rethrow if something is wrong while doing validateXXX / validateDoXXX 
  243                   throw exception;
  244               }
  245           }
  246       }
  247   
  248       @Override
  249       protected String doIntercept(ActionInvocation invocation) throws Exception {
  250           doBeforeInvocation(invocation);
  251           
  252           return invocation.invoke();
  253       }
  254   
  255   }

Save This Page
Home » xwork-2.1.5 » com.opensymphony » xwork2 » validator » [javadoc | source]