Commits

Anonymous committed 758a5c0

Comments (0)

Files changed (38)

 name=xwork
-version=2.0.1-SNAPSHOT
-status=integration
+version=2.0.1
+status=release
 fullname = XWork
 cvs.tag = xwork_2-0-1
 
 <p/>
 
-The documentation for the most recently released version can be found <a href="wikidocs/XWork2.html">here</a> (<a href="wikidocs/docs.pdf">PDF</a>). 
+The documentation for the most recently released version can be found <a href="wikidocs/Documentation.html">here</a> (<a href="wikidocs/docs.pdf">PDF</a>). 
 These docs are a snapshot from XWork's wiki at the time of the release. For the most up-to-date documentation, 
 especially if you are using XWork from CVS, please check out the <a href="http://wiki.opensymphony.com/display/XW">wiki</a>.
 

docs/wikidocs/Annotations.html

 </tr>
 <tr>
 <td class='confluenceTd'> <a href="After Annotation.html" title="After Annotation">After Annotation</a> </td>
-<td class='confluenceTd'> Marks a action method that needs to be executed before the result. </td>
+<td class='confluenceTd'> Marks an action method that needs to be executed after the main method and the result. </td>
 </tr>
 <tr>
 <td class='confluenceTd'> <a href="Before Annotation.html" title="Before Annotation">Before Annotation</a> </td>
-<td class='confluenceTd'> Marks a action method that needs to be executed before the main action method. </td>
+<td class='confluenceTd'> Marks an action method that needs to be executed before the main action method. </td>
 </tr>
 <tr>
 <td class='confluenceTd'> <a href="BeforeResult Annotation.html" title="BeforeResult Annotation">BeforeResult Annotation</a> </td>
-<td class='confluenceTd'> Marks a action method that needs to be executed before the result. </td>
+<td class='confluenceTd'> Marks an action method that needs to be executed before the result. </td>
 </tr>
 </tbody></table>
 

docs/wikidocs/CreateIfNull Annotation.html

 
 <h2><a name="CreateIfNullAnnotation-Usage"></a>Usage</h2>
 
-<p><p/>The CreateIfNull annotation must be applied at field level.</p>
+<p><p/>The CreateIfNull annotation must be applied at field or method level.</p>
 
 <h2><a name="CreateIfNullAnnotation-Parameters"></a>Parameters</h2>
 

docs/wikidocs/Element Annotation.html

 
 <h2><a name="ElementAnnotation-Usage"></a>Usage</h2>
 
-<p><p/>The Element annotation must be applied at field level.</p>
+<p><p/>The Element annotation must be applied at field or method level.</p>
 
 <h2><a name="ElementAnnotation-Parameters"></a>Parameters</h2>
 

docs/wikidocs/Key Annotation.html

 
 <h2><a name="KeyAnnotation-Usage"></a>Usage</h2>
 
-<p><p/>The Key annotation must be applied at field level.</p>
+<p><p/>The Key annotation must be applied at field or method level.</p>
 
 <h2><a name="KeyAnnotation-Parameters"></a>Parameters</h2>
 

docs/wikidocs/KeyProperty Annotation.html

 
 <h2><a name="KeyPropertyAnnotation-Usage"></a>Usage</h2>
 
-<p><p/>The KeyProperty annotation must be applied at field level.
+<p><p/>The KeyProperty annotation must be applied at field or method level.
 <p/>This annotation should be used with Generic types, if the key property of the key element needs to be specified.</p>
 
 <h2><a name="KeyPropertyAnnotation-Parameters"></a>Parameters</h2>

docs/wikidocs/Reloading.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <p>It is possible to configure XWork2 to keeps reloading its configuration files (eg. xwork.xml, *<del>conversion.xml, *-validation.xml). This is done as follows:</del></p>
+				    <p>It is possible to configure XWork2 to keeps reloading its configuration files (eg. xwork.xml, *&#45;conversion.xml, *&#45;validation.xml). This is done as follows:</p>
 
 <div class="code"><div class="codeContent">
 <pre class="code-java">FileManager.setReloadingConfigs(<span class="code-keyword">true</span>)</pre>
 <p>Configuration reloading by default is "off".</p>
 
 <table cellpadding='5' width='85%' cellspacing='8px' class='warningMacro' border="0" align='center'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="./icons/emoticons/forbidden.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>
-<p> Configuration reloading could cause performance issue. It might most probably causes the application to run considerably slow.</p></td></tr></table>
+<p> Obviously, this feature does not come for free. It will cause your application to run <b>considerably slower</b>.</p></td></tr></table>
 
                     			    </td>
 		    </tr>

docs/wikidocs/XWork Interceptors.html

 
 <div class="code"><div class="codeContent">
 <pre class="code-xml"><span class="code-tag">&lt;interceptor name=<span class="code-quote">"timer"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.TimerInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"logger"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.LoggingInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"chain"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ChainingInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"static-params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ParametersInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"model-driven"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"scoped-model-driven"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"validation"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.ValidationInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"workflow"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"prepare"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.PrepareInterceptor"</span>/&gt;</span>
-         <span class="code-tag">&lt;interceptor name=<span class="code-quote">"conversionError"</span>  class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor"</span>/&gt;</span>
-<span class="code-tag">&lt;interceptor name=<span class="code-quote">"alias"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.AliasInterceptor"</span>/&gt;</span></pre>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"logger"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.LoggingInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"chain"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ChainingInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"static-params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ParametersInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"filter-params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"remove-params"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"model-driven"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"scoped-model-driven"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"validation"</span> class=<span class="code-quote">"com.opensymphony.xwork2.validator.ValidationInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"workflow"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"prepare"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.PrepareInterceptor"</span>/&gt;</span>
+       <span class="code-tag">&lt;interceptor name=<span class="code-quote">"conversionError"</span>  class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor"</span>/&gt;</span>
+<span class="code-tag">&lt;interceptor name=<span class="code-quote">"alias"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.AliasInterceptor"</span>/&gt;</span>
+<span class="code-tag">&lt;interceptor name=<span class="code-quote">"exception"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"</span>/&gt;</span>
+<span class="code-tag">&lt;interceptor name=<span class="code-quote">"i18n"</span> class=<span class="code-quote">"com.opensymphony.xwork2.interceptor.I18nInterceptor"</span>/&gt;</span></pre>
 </div></div>
 
                     			    </td>

docs/wikidocs/docs.pdf

Binary file modified.
 <ivy-module version="1.0">
     <info organisation="opensymphony" module="xwork"
           revision="2.0.1"
-          status="integration"
-          publication="20070106000000">
+          status="release"
+          publication="20070216000000">
         <license name="Apache" url="http://www.apache.org/licenses/LICENSE-2.0.txt"/>
         <ivyauthor name="opensymphony" url="http://www.opensymphony.com/"/>
 
         <dependency org="mockobjects" name="mockobjects-core" rev="0.09" conf="build->*"/>
         <dependency org="mockobjects" name="mockobjects-jdk1.3" rev="0.09" conf="build->*"/>
         <dependency org="mockobjects" name="mockobjects-alt-jdk1.3" rev="0.09" conf="build->*"/>
-        <dependency org="easymock" name="easymock" rev="1.2_Java1.3" conf="build->*"/>
-        <dependency org="easymock" name="easymockclassextension" rev="1.1" conf="build->*"/>
-        
+        <dependency org="org.easymock" name="easymock" rev="2.0" conf="build->*"/>
+
         <dependency org="clover" name="clover" rev="1.3.11" conf="build->*"/>
         <dependency org="junit" name="junit" rev="3.8.1" conf="build->*"/>
         <dependency org="org/testng" name="testng" rev="5.1" conf="build->*"/>
 
         <!-- default -->
         <dependency org="opensymphony" name="oscore" rev="2.2.4" conf="default->*"/>
-        <dependency org="ognl" name="ognl" rev="2.6.7" conf="default->*"/>
+        <dependency org="opensymphony" name="ognl" rev="2.6.10" conf="default->*"/>
         <dependency org="rife" name="rife-continuations" rev="0.0.2" conf="default->*"/>
         <dependency org="apache" name="commons-logging" rev="1.0.4" conf="default->*"/>
         <dependency org="sun" name="javamail" rev="1.3.3" conf="default->*"/>
     <modelVersion>4.0.0</modelVersion>
     <groupId>opensymphony</groupId>
     <artifactId>xwork</artifactId>
-    <version>2.0.1-SNAPSHOT</version>
+    <version>2.0.1</version>
     <name>XWork</name>
     <description>
         XWork is an command-pattern framework that is used to power WebWork

src/java/com/opensymphony/xwork2/ActionSupport.java

  */
 public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
 
-    protected transient static final Log LOG = LogFactory.getLog(ActionSupport.class);
+    protected static Log LOG = LogFactory.getLog(ActionSupport.class);
 
-    private transient final TextProvider textProvider = new TextProviderSupport(getClass(), this);
+    private final transient TextProvider textProvider = TextProviderFactory.getInstance(getClass(), this);
     private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
 
 

src/java/com/opensymphony/xwork2/ObjectFactory.java

 import com.opensymphony.xwork2.validator.Validator;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
  *
  * @author Jason Carreira
  */
-public class ObjectFactory {
+public class ObjectFactory implements Serializable {
     private static final Log LOG = LogFactory.getLog(ObjectFactory.class);
 
-    private ClassLoader ccl;
+    private transient ClassLoader ccl;
     private static ThreadLocal<ObjectFactory> thSelf = new ThreadLocal<ObjectFactory>();
     private Container container;
 

src/java/com/opensymphony/xwork2/TextProviderFactory.java

+/*
+ * Copyright (c) 2002-2007 by OpenSymphony
+ * All rights reserved.
+ */
+package com.opensymphony.xwork2;
+
+import java.util.ResourceBundle;
+
+/**
+ * <code>TextProviderFactory</code>
+ *
+ * @author Oleg Gorobets
+ */
+public class TextProviderFactory {
+
+    private static TextProvider instance = new TextProviderSupport();
+
+    /**
+     * @param instance Text provider
+     */
+    public static void setInstance(TextProvider instance) {
+        TextProviderFactory.instance = instance;
+    }
+
+    public static TextProvider getInstance() {
+        return instance;
+    }
+
+    public static TextProvider getInstance(Class clazz, LocaleProvider provider) {
+        if (instance instanceof TextProviderSupport) {
+            ((TextProviderSupport) instance).setClazz(clazz);
+            ((TextProviderSupport) instance).setLocaleProvider(provider);
+        }
+        return instance;
+    }
+
+    public static TextProvider getInstance(ResourceBundle bundle, LocaleProvider provider) {
+        if (instance instanceof TextProviderSupport) {
+            ((TextProviderSupport) instance).setBundle(bundle);
+            ((TextProviderSupport) instance).setLocaleProvider(provider);
+        }
+        return instance;
+    }
+}

src/java/com/opensymphony/xwork2/TextProviderSupport.java

 
 
     /**
+     * Default constructor
+     */
+    public TextProviderSupport() {
+    }
+
+    /**
      * Constructor.
      *
-     * @param clazz   a clazz to use for reading the resource bundle.
-     * @param provider  a locale provider.
+     * @param clazz    a clazz to use for reading the resource bundle.
+     * @param provider a locale provider.
      */
     public TextProviderSupport(Class clazz, LocaleProvider provider) {
         this.clazz = clazz;
     /**
      * Constructor.
      *
-     * @param bundle    the resource bundle.
-     * @param provider  a locale provider.
+     * @param bundle   the resource bundle.
+     * @param provider a locale provider.
      */
     public TextProviderSupport(ResourceBundle bundle, LocaleProvider provider) {
         this.bundle = bundle;
         this.localeProvider = provider;
     }
 
+    /**
+     * @param bundle the resource bundle.
+     */
+    public void setBundle(ResourceBundle bundle) {
+        this.bundle = bundle;
+    }
+
+    /**
+     * @param clazz a clazz to use for reading the resource bundle.
+     */
+    public void setClazz(Class clazz) {
+        this.clazz = clazz;
+    }
+
+
+    /**
+     * @param localeProvider a locale provider.
+     */
+    public void setLocaleProvider(LocaleProvider localeProvider) {
+        this.localeProvider = localeProvider;
+    }
 
     /**
      * Get a text from the resource bundles associated with this action.

src/java/com/opensymphony/xwork2/config/Configuration.java

 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.io.Serializable;
 
 
 /**
  *
  * @author Mike
  */
-public interface Configuration {
+public interface Configuration extends Serializable {
     
-    public void rebuildRuntimeConfiguration();
+    void rebuildRuntimeConfiguration();
 
     PackageConfig getPackageConfig(String name);
 
     /**
      * @return the container
      */
-    public Container getContainer();
+    Container getContainer();
 
-    public Set<String> getLoadedFileNames();
+    Set<String> getLoadedFileNames();
 }

src/java/com/opensymphony/xwork2/config/RuntimeConfiguration.java

 import com.opensymphony.xwork2.config.entities.ActionConfig;
 
 import java.util.Map;
+import java.io.Serializable;
 
 
 /**
  * @author Jason Carreira
  *         Created Feb 25, 2003 10:56:02 PM
  */
-public interface RuntimeConfiguration {
+public interface RuntimeConfiguration extends Serializable {
 
     /**
      * get the fully expanded ActionConfig for a specified namespace and (action) name

src/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java

  * @author Jason Carreira
  *         Created Feb 24, 2003 7:38:06 AM
  */
-public class DefaultConfiguration implements Configuration, Serializable {
+public class DefaultConfiguration implements Configuration {
 
     protected static final Log LOG = LogFactory.getLog(DefaultConfiguration.class);
 

src/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java

         for (int i = 0; i < interceptorRefList.getLength(); i++) {
             Element interceptorRefElement = (Element) interceptorRefList.item(i);
 
-            if (interceptorRefElement.getParentNode().equals(element)) {
+            if (interceptorRefElement.getParentNode().equals(element) || interceptorRefElement.getParentNode().getNodeName().equals(element.getNodeName())) {
                 List interceptors = lookupInterceptorReference(context, interceptorRefElement);
                 interceptorList.addAll(interceptors);
             }
         for (int i = 0; i < resultEls.getLength(); i++) {
             Element resultElement = (Element) resultEls.item(i);
 
-            if (resultElement.getParentNode().equals(element)) {
+            if (resultElement.getParentNode().equals(element) || resultElement.getParentNode().getNodeName().equals(element.getNodeName())) {
                 String resultName = resultElement.getAttribute("name");
                 String resultType = resultElement.getAttribute("type");
 
         for (int i = 0; i < exceptionMappingEls.getLength(); i++) {
             Element ehElement = (Element) exceptionMappingEls.item(i);
 
-            if (ehElement.getParentNode().equals(element)) {
+            if (ehElement.getParentNode().equals(element) || ehElement.getParentNode().getNodeName().equals(element.getNodeName())) {
                 String emName = ehElement.getAttribute("name");
                 String exceptionClassName = ehElement.getAttribute("exception");
                 String exceptionResult = ehElement.getAttribute("result");

src/java/com/opensymphony/xwork2/config/providers/XmlHelper.java

                 Element paramElement = (Element) childNode;
                 String paramName = paramElement.getAttribute("name");
 
-
-                if (paramElement.getChildNodes().item(0) != null) {
-                    String paramValue = paramElement.getChildNodes().item(0).getNodeValue();
-                    if (paramValue != null) {
-                        paramValue = paramValue.trim();
-                    } else {
-                        paramValue = "";
-                    }
-                    params.put(paramName, paramValue);
+                StringBuffer paramValue = new StringBuffer();
+                for (int j=0; j <paramElement.getChildNodes().getLength(); j++) {
+                	if (paramElement.getChildNodes().item(j) != null && 
+                			paramElement.getChildNodes().item(j).getNodeType() == Node.TEXT_NODE) {
+                		String val = paramElement.getChildNodes().item(j).getNodeValue();
+                		if (val != null) {
+                			paramValue .append(val.trim());
+                		} 
+                	}
+                }
+                String val = paramValue.toString().trim();
+                if (val.length() > 0) {
+                	params.put(paramName, val);
                 }
-
             }
         }
 

src/java/com/opensymphony/xwork2/inject/Container.java

 package com.opensymphony.xwork2.inject;
 
 import java.util.Set;
+import java.io.Serializable;
 
 /**
  * Injects dependencies into constructors, methods and fields annotated with
  * @see ContainerBuilder
  * @author crazybob@google.com (Bob Lee)
  */
-public interface Container {
+public interface Container extends Serializable {
 
   /**
    * Default dependency name.

src/java/com/opensymphony/xwork2/inject/ContainerImpl.java

 import java.util.Map;
 import java.util.Set;
 import java.util.Map.Entry;
+import java.io.Serializable;
 
 /**
  * Default {@link Container} implementation.
   /**
    * Injects a field or method in a given object.
    */
-  interface Injector {
+  interface Injector extends Serializable {
     void inject(InternalContext context, Object o);
   }
 

src/java/com/opensymphony/xwork2/inject/InternalFactory.java

 
 package com.opensymphony.xwork2.inject;
 
+import java.io.Serializable;
+
 /**
  * Creates objects which will be injected.
  *
  * @author crazybob@google.com (Bob Lee)
  */
-interface InternalFactory<T> {
+interface InternalFactory<T> extends Serializable {
 
   /**
    * Creates an object to be injected.

src/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java

+package com.opensymphony.xwork2.interceptor;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.util.TextParseUtil;
+
+/**
+ * <!-- START SNIPPET: description -->
+ * This is a simple XWork interceptor that allows parameters (matching
+ * one of the paramNames attribute csv value) to be 
+ * removed from the parameter map if they match a certain value
+ * (matching one of the paramValues attribute csv value), before they 
+ * are set on the action. A typical usage would be to want a dropdown/select 
+ * to map onto a boolean value on an action. The select had the options 
+ * none, yes and no with values -1, true and false. The true and false would 
+ * map across correctly. However the -1 would be set to false. 
+ * This was not desired as one might needed the value on the action to stay null. 
+ * This interceptor fixes this by preventing the parameter from ever reaching 
+ * the action.
+ * <!-- END SNIPPET: description -->
+ * 
+ * 
+ * <!-- START SNIPPET: parameters -->
+ * <ul>
+ * 	<li>paramNames - A comma separated value (csv) indicating the parameter name 
+ * 								    whose param value should be considered that if they match any of the
+ *                                     comma separated value (csv) from paramValues attribute, shall be 
+ *                                     removed from the parameter map such that they will not be applied
+ *                                     to the action</li>
+ * 	<li>paramValues - A comma separated value (csv) indicating the parameter value that if 
+ * 							      matched shall have its parameter be removed from the parameter map 
+ * 							      such that they will not be applied to the action</li>
+ * </ul>
+ * <!-- END SNIPPET: parameters -->
+ * 
+ * 
+ * <!-- START SNIPPET: extending -->
+ * No intended extension point
+ * <!-- END SNIPPET: extending -->
+ * 
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ *	
+ * &lt;action name="sample" class="org.martingilday.Sample"&gt;
+ * 	&lt;interceptor-ref name="paramRemover"&gt;
+ *   		&lt;param name="paramNames"&gt;aParam,anotherParam&lt;/param&gt;
+ *   		&lt;param name="paramValues"&gt;--,-1&lt;/param&gt;
+ * 	&lt;/interceptor-ref&gt;
+ * 	&lt;interceptor-ref name="default-stack" /&gt;
+ * 	...
+ * &lt;/action&gt;
+ *  
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *  
+ *  
+ * @author martin.gilday
+ * @version $Date$ $Id$
+ */
+public class ParameterRemoverInterceptor extends AbstractInterceptor {
+
+	private static final Log LOG = LogFactory.getLog(ParameterRemoverInterceptor.class);
+
+	private static final long serialVersionUID = 1;
+
+	private Set paramNames = Collections.EMPTY_SET;
+
+	private Set paramValues = Collections.EMPTY_SET;
+
+	
+	/**
+	 * Decide if the parameter should be removed from the parameter map based on
+	 * <code>paramNames</code> and <code>paramValues</code>.
+	 * 
+	 * @see com.opensymphony.xwork2.interceptor.AbstractInterceptor
+	 */
+	@Override
+	public String intercept(ActionInvocation invocation) throws Exception {
+		if (!(invocation.getAction() instanceof NoParameters)
+				&& (null != this.paramNames)) {
+			ActionContext ac = invocation.getInvocationContext();
+			final Map parameters = ac.getParameters();
+
+			if (parameters != null) {
+				for (Iterator i = paramNames.iterator(); i.hasNext(); ) {
+					Object removeName = i.next();
+					
+					// see if the field is in the parameter map
+					if (parameters.containsKey(removeName)) {
+
+						try {
+							String[] values = (String[]) parameters
+									.get(removeName);
+							String value = values[0];
+							if (null != value && this.paramValues.contains(value)) {
+								parameters.remove(removeName);
+							}
+						} catch (Exception e) {
+							LOG.error("Failed to convert parameter to string", e);
+						}
+					}
+				}
+			}
+		}
+		return invocation.invoke();
+	}
+
+	/**
+	 * Allows <code>paramNames</code> attribute to be set as comma-separated-values (csv).
+	 * 
+	 * @param paramNames the paramNames to set
+	 */
+	public void setParamNames(String paramNames) {
+		this.paramNames = TextParseUtil.commaDelimitedStringToSet(paramNames);
+	}
+
+
+	/**
+	 * Allows <code>paramValues</code> attribute to be set as a comma-separated-values (csv).
+	 * 
+	 * @param paramValues the paramValues to set
+	 */
+	public void setParamValues(String paramValues) {
+		this.paramValues = TextParseUtil.commaDelimitedStringToSet(paramValues);
+	}
+}
+

src/java/com/opensymphony/xwork2/util/CreateIfNull.java

 
 package com.opensymphony.xwork2.util;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
 /**
  * <!-- START SNIPPET: description -->
  * <p/>Sets the CreateIfNull for type conversion.
  * <p/> <u>Annotation usage:</u>
  *
  * <!-- START SNIPPET: usage -->
- * <p/>The CreateIfNull annotation must be applied at field level.
+ * <p/>The CreateIfNull annotation must be applied at field or method level.
  * <!-- END SNIPPET: usage -->
  * <p/> <u>Annotation parameters:</u>
  *
  * @author Rainer Hermanns
  * @version $Id$
  */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
 public @interface CreateIfNull {
 
     /**

src/java/com/opensymphony/xwork2/util/Element.java

  * <p/> <u>Annotation usage:</u>
  *
  * <!-- START SNIPPET: usage -->
- * <p/>The Element annotation must be applied at field level.
+ * <p/>The Element annotation must be applied at field or method level.
  * <!-- END SNIPPET: usage -->
  * <p/> <u>Annotation parameters:</u>
  *
  * @author Rainer Hermanns
  * @version $Id$
  */
-@Target({ ElementType.FIELD})
 @Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
 public @interface Element {
 
     /**

src/java/com/opensymphony/xwork2/util/Key.java

 
 package com.opensymphony.xwork2.util;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
 /**
  * <!-- START SNIPPET: description -->
  * <p/>Sets the Key for type conversion.
  * <p/> <u>Annotation usage:</u>
  *
  * <!-- START SNIPPET: usage -->
- * <p/>The Key annotation must be applied at field level.
+ * <p/>The Key annotation must be applied at field or method level.
  * <!-- END SNIPPET: usage -->
  * <p/> <u>Annotation parameters:</u>
  *
  * @author Rainer Hermanns
  * @version $Id$
  */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
 public @interface Key {
 
     /**

src/java/com/opensymphony/xwork2/util/KeyProperty.java

 
 package com.opensymphony.xwork2.util;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
 /**
  * <!-- START SNIPPET: description -->
  * <p/>Sets the KeyProperty for type conversion.
  * <p/> <u>Annotation usage:</u>
  *
  * <!-- START SNIPPET: usage -->
- * <p/>The KeyProperty annotation must be applied at field level.
+ * <p/>The KeyProperty annotation must be applied at field or method level.
  * <p/>This annotation should be used with Generic types, if the key property of the key element needs to be specified.
  * <!-- END SNIPPET: usage -->
  * <p/> <u>Annotation parameters:</u>
  * @author Patrick Lightbody
  * @author Rainer Hermanns
  */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.METHOD})
 public @interface KeyProperty {
 
     /**

src/java/com/opensymphony/xwork2/validator/ActionValidatorManager.java

  */
 public interface ActionValidatorManager {
 
+
+    /**
+     * Returns a list of validators for the given class, context, and method. This is the primary
+     * lookup method for validators.
+     *
+     * @param clazz the class to lookup.
+     * @param context the context of the action class - can be <tt>null</tt>.
+     * @param method the name of the method being invoked on the action - can be <tt>null</tt>.
+     * @return a list of all validators for the given class and context.
+     */
+    List<Validator> getValidators(Class clazz, String context, String method);
+
     /**
      * Returns a list of validators for the given class and context. This is the primary
      * lookup method for validators.
      * @param context the context of the action class - can be <tt>null</tt>.
      * @return a list of all validators for the given class and context.
      */
-    List getValidators(Class clazz, String context);
+    List<Validator> getValidators(Class clazz, String context);
 
     /**
      * Validates the given object using action and its context.
      * @throws ValidationException if an error happens when validating the action.
      */
     void validate(Object object, String context, ValidatorContext validatorContext) throws ValidationException;
+
+    /**
+     * Validates the given object using an action, its context, and the name of the method being invoked on the action.
+     *
+     * @param object the action to validate.
+     * @param context the action's context.
+     * @param method the name of the method being invoked on the action - can be <tt>null</tt>.
+     * @throws ValidationException if an error happens when validating the action.
+     */
+    void validate(Object object, String context, String method) throws ValidationException;
+
+    /**
+     * Validates an action give its context and a validation context.
+     *
+     * @param object the action to validate.
+     * @param context the action's context.
+     * @param validatorContext
+     * @param method the name of the method being invoked on the action - can be <tt>null</tt>.
+     * @throws ValidationException if an error happens when validating the action.
+     */
+    void validate(Object object, String context, ValidatorContext validatorContext, String method) throws ValidationException;
 }

src/java/com/opensymphony/xwork2/validator/AnnotationActionValidatorManager.java

 import java.io.IOException;
 
 import com.opensymphony.xwork2.util.FileManager;
+import com.opensymphony.xwork2.ObjectFactory;
 
 /**
  * <code>AnnotationActionValidatorManager</code>
      * @return a list of all validators for the given class and context.
      */
     public synchronized List<Validator> getValidators(Class clazz, String context) {
+        return getValidators(clazz, context, null);
+    }
+
+    /**
+     * Returns a list of validators for the given class, context, and method. This is the primary
+     * lookup method for validators.
+     *
+     * @param clazz   the class to lookup.
+     * @param context the context of the action class - can be <tt>null</tt>.
+     * @param method  the name of the method being invoked on the action - can be <tt>null</tt>.
+     * @return a list of all validators for the given class and context.
+     */
+    public synchronized List<Validator> getValidators(Class clazz, String context, String method) {
         final String validatorKey = buildValidatorKey(clazz, context);
 
         if (validatorCache.containsKey(validatorKey)) {
         // create clean instances of the validators for the caller's use
         ArrayList<Validator> validators = new ArrayList<Validator>(cfgs.size());
         for (ValidatorConfig cfg : cfgs) {
-            Validator validator = ValidatorFactory.getValidator(cfg);
-            validator.setValidatorType(cfg.getType());
-            validators.add(validator);
+            if (method == null || method.equals(cfg.getParams().get("methodName"))) {
+                Validator validator = ValidatorFactory.getValidator(cfg, ObjectFactory.getObjectFactory());
+                validator.setValidatorType(cfg.getType());
+                validators.add(validator);
+            }
         }
 
         return validators;
      * @throws ValidationException if an error happens when validating the action.
      */
     public void validate(Object object, String context) throws ValidationException {
+        validate(object, context, (String) null);
+    }
+
+    /**
+     * Validates the given object using action, its context, and the name of the method being invoked on the action.
+     *
+     * @param object  the action to validate.
+     * @param context the action's context.
+     * @param method  the name of the method being invoked on the action.
+     * @throws ValidationException if an error happens when validating the action.
+     */
+    public void validate(Object object, String context, String method) throws ValidationException {
         ValidatorContext validatorContext = new DelegatingValidatorContext(object);
-        validate(object, context, validatorContext);
+        validate(object, context, validatorContext, method);
     }
 
     /**
      * @throws ValidationException if an error happens when validating the action.
      */
     public void validate(Object object, String context, ValidatorContext validatorContext) throws ValidationException {
-        List<Validator> validators = getValidators(object.getClass(), context);
+        validate(object, context, validatorContext, null);
+    }
+
+    /**
+     * Validates an action give its context, a validation context, and the name of the method being invoked on the action.
+     *
+     * @param object           the action to validate.
+     * @param context          the action's context.
+     * @param validatorContext
+     * @param method           the name of the method being invoked on the action.
+     * @throws ValidationException if an error happens when validating the action.
+     */
+    public void validate(Object object, String context, ValidatorContext validatorContext, String method) throws ValidationException {
+        List<Validator> validators = getValidators(object.getClass(), context, method);
         Set<String> shortcircuitedFields = null;
 
         for (final Validator validator: validators) {
                 validator.setValidatorContext(validatorContext);
 
                 if (LOG.isDebugEnabled()) {
-                    LOG.debug("Running validator: " + validator + " for object " + object);
+                    LOG.debug("Running validator: " + validator + " for object " + object + " and method " + method);
                 }
 
                 FieldValidator fValidator = null;
         }
 
         // look for validators for implemented interfaces
-        Class[] interfaces = clazz.getInterfaces();
-
-        for (Class anInterface1 : interfaces) {
+        for (Class anInterface1 : clazz.getInterfaces()) {
             if (checked.contains(anInterface1.getName())) {
                 continue;
             }

src/java/com/opensymphony/xwork2/validator/AnnotationValidationConfigurationBuilder.java

         List<ValidatorConfig> result = new ArrayList<ValidatorConfig>();
 
         String fieldName = null;
+        String methodName = null;
 
         Annotation[] annotations = null;
 
         if (o instanceof Method) {
             Method method = (Method) o;
             fieldName = resolvePropertyName(method);
+            methodName = method.getName();
 
             annotations = method.getAnnotations();
         }
 
                 }
             }
+            
+            if (methodName != null) {
+                for (ValidatorConfig vc : result) {
+                    vc.getParams().put("methodName", methodName);
+                }
+            }
         }
         return result;
     }

src/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManager.java

 package com.opensymphony.xwork2.validator;
 
 import com.opensymphony.xwork2.util.FileManager;
+import com.opensymphony.xwork2.ObjectFactory;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
     /** The file suffix for any validation file. */
     protected static final String VALIDATION_CONFIG_SUFFIX = "-validation.xml";
 
-    private static final Map validatorCache = Collections.synchronizedMap(new HashMap());
-    private static final Map validatorFileCache = Collections.synchronizedMap(new HashMap());
+    private static final Map<String, List<ValidatorConfig>> validatorCache = Collections.synchronizedMap(new HashMap<String, List<ValidatorConfig>>());
+    private static final Map<String, List<ValidatorConfig>> validatorFileCache = Collections.synchronizedMap(new HashMap<String, List<ValidatorConfig>>());
+
     private static final Log LOG = LogFactory.getLog(DefaultActionValidatorManager.class);
 
     /**
      * @param context the context of the action class - can be <tt>null</tt>.
      * @return a list of all validators for the given class and context.
      */
-    public synchronized List getValidators(Class clazz, String context) {
+    public synchronized List<Validator> getValidators(Class clazz, String context) {
+        return getValidators(clazz, context, null);
+    }
+
+    /**
+     * Returns a list of validators for the given class, context, and method name. This is the primary
+     * lookup method for validators.
+     *
+     * @param clazz the class to lookup.
+     * @param context the context of the action class - can be <tt>null</tt>.
+     * @param method the name of the method being invoked on the action - can be <tt>null</tt>.
+     * @return a list of all validators for the given class and context.
+     */
+    public synchronized List<Validator> getValidators(Class clazz, String context, String method) {
         final String validatorKey = buildValidatorKey(clazz, context);
 
         if (validatorCache.containsKey(validatorKey)) {
         }
 
         // get the set of validator configs
-        List cfgs = (List) validatorCache.get(validatorKey);
+        List<ValidatorConfig> cfgs = validatorCache.get(validatorKey);
 
         // create clean instances of the validators for the caller's use
-        ArrayList validators = new ArrayList(cfgs.size());
-        for (Iterator iterator = cfgs.iterator(); iterator.hasNext(); ) {
-            ValidatorConfig cfg = (ValidatorConfig) iterator.next();
-            Validator validator = ValidatorFactory.getValidator(cfg);
-            validator.setValidatorType(cfg.getType());
-            validators.add(validator);
-        }
+        ArrayList<Validator> validators = new ArrayList<Validator>(cfgs.size());
+        for (ValidatorConfig cfg : cfgs) {
+            if (method == null || method.equals(cfg.getParams().get("methodName"))) {
+                Validator validator = ValidatorFactory.getValidator(cfg, ObjectFactory.getObjectFactory());
+                validator.setValidatorType(cfg.getType());
+                validators.add(validator);
+            }
+        }        
 
         return validators;
     }
      * @throws ValidationException if an error happens when validating the action.
      */
     public void validate(Object object, String context) throws ValidationException {
+        validate(object, context, (String) null);
+    }
+
+    /**
+     * Validates the given object using action, its context, and the name of the method being invoked on the action.
+     *
+     * @param object the action to validate.
+     * @param context the action's context.
+     * @param method the name of the method being invoked on the action.
+     * @throws ValidationException if an error happens when validating the action.
+     */
+    public void validate(Object object, String context, String method) throws ValidationException {
         ValidatorContext validatorContext = new DelegatingValidatorContext(object);
-        validate(object, context, validatorContext);
+        validate(object, context, validatorContext, method);
     }
 
     /**
      * @throws ValidationException if an error happens when validating the action.
      */
     public void validate(Object object, String context, ValidatorContext validatorContext) throws ValidationException {
-        List validators = getValidators(object.getClass(), context);
-        Set shortcircuitedFields = null;
+        validate(object, context, validatorContext, null);
+    }
 
-        for (Iterator iterator = validators.iterator(); iterator.hasNext();) {
-            final Validator validator = (Validator) iterator.next();
+    /**
+     * Validates an action give its context, a validation context, and the name of the method being invoked on the action.
+     *
+     * @param object the action to validate.
+     * @param context the action's context.
+     * @param validatorContext
+     * @param method the name of the method being invoked on the action.
+     * @throws ValidationException if an error happens when validating the action.
+     */
+    public void validate(Object object, String context, ValidatorContext validatorContext, String method) throws ValidationException {
+        List<Validator> validators = getValidators(object.getClass(), context, method);
+        Set<String> shortcircuitedFields = null;
+
+        for (final Validator validator : validators) {
             try {
                 validator.setValidatorContext(validatorContext);
 
                 if (LOG.isDebugEnabled()) {
-                    LOG.debug("Running validator: " + validator + " for object " + object);
+                    LOG.debug("Running validator: " + validator + " for object " + object + " and method " + method);
                 }
 
                 FieldValidator fValidator = null;
 
                 if (validator instanceof ShortCircuitableValidator && ((ShortCircuitableValidator) validator).isShortCircuit()) {
                     // get number of existing errors
-                    List errs = null;
+                    List<String> errs = null;
 
                     if (fValidator != null) {
                         if (validatorContext.hasFieldErrors()) {
-                            Collection fieldErrors = (Collection) validatorContext.getFieldErrors().get(fullFieldName);
+                            Collection<String> fieldErrors = (Collection<String>) validatorContext.getFieldErrors().get(fullFieldName);
 
                             if (fieldErrors != null) {
-                                errs = new ArrayList(fieldErrors);
+                                errs = new ArrayList<String>(fieldErrors);
                             }
                         }
                     } else if (validatorContext.hasActionErrors()) {
-                        Collection actionErrors = validatorContext.getActionErrors();
+                        Collection<String> actionErrors = validatorContext.getActionErrors();
 
                         if (actionErrors != null) {
-                            errs = new ArrayList(actionErrors);
+                            errs = new ArrayList<String>(actionErrors);
                         }
                     }
 
 
                     if (fValidator != null) {
                         if (validatorContext.hasFieldErrors()) {
-                            Collection errCol = (Collection) validatorContext.getFieldErrors().get(fullFieldName);
+                            Collection<String> errCol = (Collection<String>) validatorContext.getFieldErrors().get(fullFieldName);
 
                             if ((errCol != null) && !errCol.equals(errs)) {
                                 if (LOG.isDebugEnabled()) {
                                 }
 
                                 if (shortcircuitedFields == null) {
-                                    shortcircuitedFields = new TreeSet();
+                                    shortcircuitedFields = new TreeSet<String>();
                                 }
 
                                 shortcircuitedFields.add(fullFieldName);
                             }
                         }
                     } else if (validatorContext.hasActionErrors()) {
-                        Collection errCol = validatorContext.getActionErrors();
+                        Collection<String> errCol = validatorContext.getActionErrors();
 
                         if ((errCol != null) && !errCol.equals(errs)) {
                             if (LOG.isDebugEnabled()) {
         return sb.toString();
     }
 
-    private List buildAliasValidatorConfigs(Class aClass, String context, boolean checkFile) {
+    private List<ValidatorConfig> buildAliasValidatorConfigs(Class aClass, String context, boolean checkFile) {
         String fileName = aClass.getName().replace('.', '/') + "-" + context + VALIDATION_CONFIG_SUFFIX;
 
         return loadFile(fileName, aClass, checkFile);
     }
 
-    private List buildClassValidatorConfigs(Class aClass, boolean checkFile) {
+    private List<ValidatorConfig> buildClassValidatorConfigs(Class aClass, boolean checkFile) {
         String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX;
 
         return loadFile(fileName, aClass, checkFile);
      * @param checked the set of previously checked class-contexts, null if none have been checked
      * @return a list of validator configs for the given class and context.
      */
-    private List buildValidatorConfigs(Class clazz, String context, boolean checkFile, Set checked) {
-        List validatorConfigs = new ArrayList();
+    private List<ValidatorConfig> buildValidatorConfigs(Class clazz, String context, boolean checkFile, Set checked) {
+        List<ValidatorConfig> validatorConfigs = new ArrayList<ValidatorConfig>();
 
         if (checked == null) {
             checked = new TreeSet();
         }
 
         if (clazz.isInterface()) {
-            Class[] interfaces = clazz.getInterfaces();
-
-            for (int x = 0; x < interfaces.length; x++) {
-                validatorConfigs.addAll(buildValidatorConfigs(interfaces[x], context, checkFile, checked));
+            for (Class anInterface : clazz.getInterfaces()) {
+                validatorConfigs.addAll(buildValidatorConfigs(anInterface, context, checkFile, checked));
             }
         } else {
             if (!clazz.equals(Object.class)) {
         }
 
         // look for validators for implemented interfaces
-        Class[] interfaces = clazz.getInterfaces();
-
-        for (int x = 0; x < interfaces.length; x++) {
-            if (checked.contains(interfaces[x].getName())) {
+        for (Class anInterface1 : clazz.getInterfaces()) {
+            if (checked.contains(anInterface1.getName())) {
                 continue;
             }
 
-            validatorConfigs.addAll(buildClassValidatorConfigs(interfaces[x], checkFile));
+            validatorConfigs.addAll(buildClassValidatorConfigs(anInterface1, checkFile));
 
             if (context != null) {
-                validatorConfigs.addAll(buildAliasValidatorConfigs(interfaces[x], context, checkFile));
+                validatorConfigs.addAll(buildAliasValidatorConfigs(anInterface1, context, checkFile));
             }
 
-            checked.add(interfaces[x].getName());
+            checked.add(anInterface1.getName());
         }
 
         validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile));
         return validatorConfigs;
     }
 
-    private List loadFile(String fileName, Class clazz, boolean checkFile) {
-        List retList = Collections.EMPTY_LIST;
+    private List<ValidatorConfig> loadFile(String fileName, Class clazz, boolean checkFile) {
+        List<ValidatorConfig> retList = Collections.emptyList();
 
         if ((checkFile && FileManager.fileNeedsReloading(fileName)) || !validatorFileCache.containsKey(fileName)) {
             InputStream is = null;
                 is = FileManager.loadFile(fileName, clazz);
 
                 if (is != null) {
-                    retList = new ArrayList(ValidatorFileParser.parseActionValidatorConfigs(is, fileName));
+                    retList = new ArrayList<ValidatorConfig>(ValidatorFileParser.parseActionValidatorConfigs(is, fileName));
                 }
             } finally {
                 if (is != null) {
 
             validatorFileCache.put(fileName, retList);
         } else {
-            retList = (List) validatorFileCache.get(fileName);
+            retList = validatorFileCache.get(fileName);
         }
 
         return retList;

src/java/com/opensymphony/xwork2/validator/DelegatingValidatorContext.java

      */
     public DelegatingValidatorContext(Class clazz) {
         localeProvider = new ActionContextLocaleProvider();
-        textProvider = new TextProviderSupport(clazz, localeProvider);
+        textProvider = TextProviderFactory.getInstance(clazz, localeProvider);
         validationAware = new LoggingValidationAware(clazz);
     }
 
         if (object instanceof TextProvider) {
             return (TextProvider) object;
         } else {
-            return new TextProviderSupport(object.getClass(), localeProvider);
+            return TextProviderFactory.getInstance(object.getClass(), localeProvider);
         }
     }
 

src/java/com/opensymphony/xwork2/validator/ValidationInterceptor.java

  *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
  * &lt;/action&gt;
  * 
- * 
+ * &lt;-- in the following case only annotated methods of the action class will
+ *        be validated --&gt;
+ * &lt;action name="someAction" class="com.examples.SomeAction"&gt;
+ *     &lt;interceptor-ref name="params"/&gt;
+ *     &lt;interceptor-ref name="validation"&gt;
+ *         &lt;param name="validateAnnotatedMethodOnly"&gt;true&lt;/param&gt;
+ *     &lt;/interceptor-ref&gt;
+ *     &lt;interceptor-ref name="workflow"/&gt;
+ *     &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
+ * &lt;/action&gt;
+ *
+ *
  * <!-- END SNIPPET: example -->
  * </pre>
  *
  * @version $Date$ $Id$
  */
 public class ValidationInterceptor extends MethodFilterInterceptor {
+
+    private boolean validateAnnotatedMethodOnly;
+
+    public boolean isValidateAnnotatedMethodOnly() {
+        return validateAnnotatedMethodOnly;
+    }
+
+    /**
+     * Determine if <code>validate()</code> should always be called or only per annotated method.
+     * Default to "false".
+     *
+     * @param validateAnnotatedMethodOnly
+     */
+    public void setValidateAnnotatedMethodOnly(String validateAnnotatedMethodOnly) {
+        this.validateAnnotatedMethodOnly = Boolean.parseBoolean(validateAnnotatedMethodOnly);
+    }
+
     /**
      * Gets the current action and its context and calls {@link DefaultActionValidatorManager#validate(Object, String)}.
      *
     protected void doBeforeInvocation(ActionInvocation invocation) throws Exception {
         Object action = invocation.getAction();
         String context = invocation.getProxy().getActionName();
+        String method = invocation.getProxy().getMethod();
 
         if (log.isDebugEnabled()) {
             log.debug("Validating "
-                    + invocation.getProxy().getNamespace() + "/" + invocation.getProxy().getActionName() + " with method "+invocation.getProxy().getMethod()+".");
+                    + invocation.getProxy().getNamespace() + "/" + invocation.getProxy().getActionName() + " with method "+ method +".");
+
+        }
+
+        if (validateAnnotatedMethodOnly) {
+            ActionValidatorManagerFactory.getInstance().validate(action, context, method);
+        } else {
+            ActionValidatorManagerFactory.getInstance().validate(action, context);
         }
 
-        ActionValidatorManagerFactory.getInstance().validate(action, context);
     }
 
     protected String doIntercept(ActionInvocation invocation) throws Exception {

src/java/com/opensymphony/xwork2/validator/ValidatorFactory.java

  * <p><b>Non Field Validators</b>
  * <!-- START SNIPPET: nonFieldValidators -->
  * Non-field validators only add action level messages. Non-field validators 
- * are mostly domain specific and therefore often custom implementations. 
+ * are mostly domain specific and therefore offer custom implementations. 
  * The most important standard non-field validator provided by XWork
  * is ExpressionValidator.
  * <!-- END SNIPPET: nonFieldValidators -->
  * 
  *
  * <p>If the validator fails, the validator is pushed onto the ValueStack and the 
- * message� either the default or the locale-specific one if the key attribute is
- * defined (and such a message exists)� is parsed for ${...} sections which are 
+ * message - either the default or the locale-specific one if the key attribute is
+ * defined (and such a message exists) - is parsed for ${...} sections which are 
  * replaced with the evaluated value of the string between the ${ and }. This 
  * allows you to parameterize your messages with values from the validator, the 
  * Action, or both. </p>

src/java/xwork-default.xml

             <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
             <interceptor name="static-params" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
             <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
+            <interceptor name="filter-params" class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/>
+            <interceptor name="remove-params" class="com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"/>
             <interceptor name="model-driven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
             <interceptor name="scoped-model-driven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
             <interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
             <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
             <interceptor name="conversionError"  class="com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor"/>
 			<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
-  
+			<interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
+			<interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
+
   			<!-- END SNIPPET: xwork2-default-interceptors -->
   
   

src/test/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptorTest.java

+package com.opensymphony.xwork2.interceptor;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.easymock.MockControl;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionSupport;
+
+import junit.framework.TestCase;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class ParameterRemoverInterceptorTest extends TestCase {
+
+	protected Map contextMap;
+	protected ActionContext context;
+	protected MockControl actionInvocationControl;
+	protected ActionInvocation actionInvocation;
+	
+	protected void setUp() throws Exception {
+		contextMap = new LinkedHashMap();
+		context = new ActionContext(contextMap);
+		
+		actionInvocationControl = MockControl.createControl(ActionInvocation.class);
+		actionInvocation = (ActionInvocation) actionInvocationControl.getMock();
+		actionInvocationControl.expectAndDefaultReturn(actionInvocation.getAction(),  new SampleAction());
+		actionInvocationControl.expectAndDefaultReturn(actionInvocation.getInvocationContext(), context);
+		actionInvocationControl.expectAndDefaultReturn(actionInvocation.invoke(), "success");
+	}
+	
+	public void testInterception1() throws Exception {
+		contextMap.put(ActionContext.PARAMETERS, new LinkedHashMap() {
+			private static final long serialVersionUID = 0L;
+			{
+				put("param1", new String[] { "paramValue1" });
+				put("param2", new String[] { "paramValue2" });
+				put("param3", new String[] { "paramValue3" });
+				put("param", new String[] { "paramValue" });
+			}
+		});
+		
+		actionInvocationControl.replay();
+		
+		ParameterRemoverInterceptor interceptor = new ParameterRemoverInterceptor();
+		interceptor.setParamNames("param1,param2");
+		interceptor.setParamValues("paramValue1,paramValue2");
+		interceptor.intercept(actionInvocation);
+		
+		Map params = (Map) contextMap.get(ActionContext.PARAMETERS);
+		assertEquals(params.size(), 2);
+		assertTrue(params.containsKey("param3"));
+		assertTrue(params.containsKey("param"));
+		assertEquals(((String[])params.get("param3"))[0], "paramValue3");
+		assertEquals(((String[])params.get("param"))[0], "paramValue");
+		
+		actionInvocationControl.verify();
+	}
+	
+	
+	public void testInterception2() throws Exception {
+		contextMap.put(ActionContext.PARAMETERS, new LinkedHashMap() {
+			private static final long serialVersionUID = 0L;
+			{
+				put("param1", new String[] { "paramValue2" });
+				put("param2", new String[] { "paramValue1" });
+			}
+		});
+		
+		actionInvocationControl.replay();
+		
+		ParameterRemoverInterceptor interceptor = new ParameterRemoverInterceptor();
+		interceptor.setParamNames("param1,param2");
+		interceptor.setParamValues("paramValue1,paramValue2");
+		interceptor.intercept(actionInvocation);
+		
+		Map params = (Map) contextMap.get(ActionContext.PARAMETERS);
+		assertEquals(params.size(), 0);
+		
+		actionInvocationControl.verify();
+	}
+	
+	
+	public void testInterception3() throws Exception {
+		contextMap.put(ActionContext.PARAMETERS, new LinkedHashMap() {
+			private static final long serialVersionUID = 0L;
+			{
+				put("param1", new String[] { "paramValueOne" });
+				put("param2", new String[] { "paramValueTwo" });
+			}
+		});
+		
+		actionInvocationControl.replay();
+		
+		ParameterRemoverInterceptor interceptor = new ParameterRemoverInterceptor();
+		interceptor.setParamNames("param1,param2");
+		interceptor.setParamValues("paramValue1,paramValue2");
+		interceptor.intercept(actionInvocation);
+		
+		Map params = (Map) contextMap.get(ActionContext.PARAMETERS);
+		assertEquals(params.size(), 2);
+		assertTrue(params.containsKey("param1"));
+		assertTrue(params.containsKey("param2"));
+		assertEquals(((String[])params.get("param1"))[0], "paramValueOne");
+		assertEquals(((String[])params.get("param2"))[0], "paramValueTwo");
+		
+		actionInvocationControl.verify();
+	}
+	
+	class SampleAction extends ActionSupport {
+		private static final long serialVersionUID = 7489487258845368260L;
+	}
+}