You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2011/12/02 17:33:45 UTC
svn commit: r1209569 [22/50] - in /struts/struts2/branches/STRUTS_3_X:
apps/blank/src/main/java/example/ apps/blank/src/test/java/example/
apps/jboss-blank/src/main/java/example/
apps/jboss-blank/src/test/java/example/ apps/mailreader/src/main/java/mai...
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ModelDrivenInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ModelDrivenInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ModelDrivenInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ModelDrivenInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.ModelDriven;
+import org.apache.struts2.xwork2.util.CompoundRoot;
+import org.apache.struts2.xwork2.util.ValueStack;
+
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * Watches for {@link ModelDriven} actions and adds the action's model on to the value stack.
+ *
+ * <p/> <b>Note:</b> The ModelDrivenInterceptor must come before the both {@link StaticParametersInterceptor} and
+ * {@link ParametersInterceptor} if you want the parameters to be applied to the model.
+ *
+ * <p/> <b>Note:</b> The ModelDrivenInterceptor will only push the model into the stack when the
+ * model is not null, else it will be ignored.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <p/> <u>Interceptor parameters:</u>
+ *
+ * <!-- START SNIPPET: parameters -->
+ *
+ * <ul>
+ *
+ * <li>refreshModelBeforeResult - set to true if you want the model to be refreshed on the value stack after action
+ * execution and before result execution. The setting is useful if you want to change the model instance during the
+ * action execution phase, like when loading it from the data layer. This will result in getModel() being called at
+ * least twice.</li>
+ *
+ * </ul>
+ *
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <p/> <u>Extending the interceptor:</u>
+ *
+ * <p/>
+ *
+ * <!-- START SNIPPET: extending -->
+ *
+ * There are no known extension points to this interceptor.
+ *
+ * <!-- END SNIPPET: extending -->
+ *
+ * <p/> <u>Example code:</u>
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * <action name="someAction" class="com.examples.SomeAction">
+ * <interceptor-ref name="modelDriven"/>
+ * <interceptor-ref name="basicStack"/>
+ * <result name="success">good_result.ftl</result>
+ * </action>
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @author tm_jee
+ * @version $Date: 2011-12-02 12:24:48 +0100 (Fri, 02 Dec 2011) $ $Id: ModelDrivenInterceptor.java 1209415 2011-12-02 11:24:48Z lukaszlenart $
+ */
+public class ModelDrivenInterceptor extends AbstractInterceptor {
+
+ protected boolean refreshModelBeforeResult = false;
+
+ public void setRefreshModelBeforeResult(boolean val) {
+ this.refreshModelBeforeResult = val;
+ }
+
+ @Override
+ public String intercept(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+
+ if (action instanceof ModelDriven) {
+ ModelDriven modelDriven = (ModelDriven) action;
+ ValueStack stack = invocation.getStack();
+ Object model = modelDriven.getModel();
+ if (model != null) {
+ stack.push(model);
+ }
+ if (refreshModelBeforeResult) {
+ invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model));
+ }
+ }
+ return invocation.invoke();
+ }
+
+ /**
+ * Refreshes the model instance on the value stack, if it has changed
+ */
+ protected static class RefreshModelBeforeResult implements PreResultListener {
+ private Object originalModel = null;
+ protected ModelDriven action;
+
+
+ public RefreshModelBeforeResult(ModelDriven action, Object model) {
+ this.originalModel = model;
+ this.action = action;
+ }
+
+ public void beforeResult(ActionInvocation invocation, String resultCode) {
+ ValueStack stack = invocation.getStack();
+ CompoundRoot root = stack.getRoot();
+
+ boolean needsRefresh = true;
+ Object newModel = action.getModel();
+
+ // Check to see if the new model instance is already on the stack
+ for (Object item : root) {
+ if (item.equals(newModel)) {
+ needsRefresh = false;
+ }
+ }
+
+ // Add the new model on the stack
+ if (needsRefresh) {
+
+ // Clear off the old model instance
+ if (originalModel != null) {
+ root.remove(originalModel);
+ }
+ if (newModel != null) {
+ stack.push(newModel);
+ }
+ }
+ }
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/NoParameters.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/NoParameters.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/NoParameters.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/NoParameters.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+
+/**
+ * Marker interface to incidate no auto setting of parameters.
+ * <p/>
+ * This marker interface should be implemented by actions that do not want any
+ * request parameters set on them automatically (by the ParametersInterceptor).
+ * This may be useful if one is using the action tag and want to supply
+ * the parameters to the action manually using the param tag.
+ * It may also be useful if one for security reasons wants to make sure that
+ * parameters cannot be set by malicious users.
+ *
+ * @author Dick Zetterberg (dick@transitor.se)
+ */
+public interface NoParameters {
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterFilterInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterFilterInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterFilterInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterFilterInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.util.TextParseUtil;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * The Parameter Filter Interceptor blocks parameters from getting
+ * to the rest of the stack or your action. You can use multiple
+ * parameter filter interceptors for a given action, so, for example,
+ * you could use one in your default stack that filtered parameters
+ * you wanted blocked from every action and those you wanted blocked
+ * from an individual action you could add an additional interceptor
+ * for each action.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <!-- START SNIPPET: parameters -->
+ *
+ * <ul>
+ * <li>allowed - a comma delimited list of parameter prefixes
+ * that are allowed to pass to the action</li>
+ * <li>blocked - a comma delimited list of parameter prefixes
+ * that are not allowed to pass to the action</li>
+ * <li>defaultBlock - boolean (default to false) whether by
+ * default a given parameter is blocked. If true, then a parameter
+ * must have a prefix in the allowed list in order to be able
+ * to pass to the action
+ * </ul>
+ *
+ * <p>The way parameters are filtered for the least configuration is that
+ * if a string is in the allowed or blocked lists, then any parameter
+ * that is a member of the object represented by the parameter is allowed
+ * or blocked respectively.</p>
+ *
+ * <p>For example, if the parameters are:
+ * <ul>
+ * <li>blocked: person,person.address.createDate,personDao</li>
+ * <li>allowed: person.address</li>
+ * <li>defaultBlock: false</li>
+ * </ul>
+ * <br>
+ * The parameters person.name, person.phoneNum etc would be blocked
+ * because 'person' is in the blocked list. However, person.address.street
+ * and person.address.city would be allowed because person.address is
+ * in the allowed list (the longer string determines permissions).</p>
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <!-- START SNIPPET: extending -->
+ * There are no known extension points to this interceptor.
+ * <!-- END SNIPPET: extending -->
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * <interceptors>
+ * ...
+ * <interceptor name="parameterFilter" class="org.apache.struts2.xwork2.interceptor.ParameterFilterInterceptor"/>
+ * ...
+ * </interceptors>
+ *
+ * <action ....>
+ * ...
+ * <interceptor-ref name="parameterFilter">
+ * <param name="blocked">person,person.address.createDate,personDao</param>
+ * </interceptor-ref>
+ * ...
+ * </action>
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @author Gabe
+ */
+public class ParameterFilterInterceptor extends AbstractInterceptor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ParameterFilterInterceptor.class);
+
+ private Collection<String> allowed;
+ private Collection<String> blocked;
+ private Map<String, Boolean> includesExcludesMap;
+ private boolean defaultBlock = false;
+
+ @Override
+ public String intercept(ActionInvocation invocation) throws Exception {
+
+ Map<String, Object> parameters = invocation.getInvocationContext().getParameters();
+ HashSet<String> paramsToRemove = new HashSet<String>();
+
+ Map<String, Boolean> includesExcludesMap = getIncludesExcludesMap();
+
+ for (String param : parameters.keySet()) {
+ boolean currentAllowed = !isDefaultBlock();
+
+ for (String currRule : includesExcludesMap.keySet()) {
+ if (param.startsWith(currRule)
+ && (param.length() == currRule.length()
+ || isPropSeperator(param.charAt(currRule.length())))) {
+ currentAllowed = includesExcludesMap.get(currRule).booleanValue();
+ }
+ }
+ if (!currentAllowed) {
+ paramsToRemove.add(param);
+ }
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Params to remove: " + paramsToRemove);
+ }
+
+ for (Object aParamsToRemove : paramsToRemove) {
+ parameters.remove(aParamsToRemove);
+ }
+
+ return invocation.invoke();
+ }
+
+ /**
+ * Tests if the given char is a property seperator char <code>.([</code>.
+ *
+ * @param c the char
+ * @return <tt>true</tt>, if char is property separator, <tt>false</tt> otherwise.
+ */
+ private static boolean isPropSeperator(char c) {
+ return c == '.' || c == '(' || c == '[';
+ }
+
+ private Map<String, Boolean> getIncludesExcludesMap() {
+ if (this.includesExcludesMap == null) {
+ this.includesExcludesMap = new TreeMap<String, Boolean>();
+
+ if (getAllowedCollection() != null) {
+ for (String e : getAllowedCollection()) {
+ this.includesExcludesMap.put(e, Boolean.TRUE);
+ }
+ }
+ if (getBlockedCollection() != null) {
+ for (String b : getBlockedCollection()) {
+ this.includesExcludesMap.put(b, Boolean.FALSE);
+ }
+ }
+ }
+
+ return this.includesExcludesMap;
+ }
+
+ /**
+ * @return Returns the defaultBlock.
+ */
+ public boolean isDefaultBlock() {
+ return defaultBlock;
+ }
+
+ /**
+ * @param defaultExclude The defaultExclude to set.
+ */
+ public void setDefaultBlock(boolean defaultExclude) {
+ this.defaultBlock = defaultExclude;
+ }
+
+ /**
+ * @return Returns the blocked.
+ */
+ public Collection<String> getBlockedCollection() {
+ return blocked;
+ }
+
+ /**
+ * @param blocked The blocked to set.
+ */
+ public void setBlockedCollection(Collection<String> blocked) {
+ this.blocked = blocked;
+ }
+
+ /**
+ * @param blocked The blocked paramters as comma separated String.
+ */
+ public void setBlocked(String blocked) {
+ setBlockedCollection(asCollection(blocked));
+ }
+
+ /**
+ * @return Returns the allowed.
+ */
+ public Collection<String> getAllowedCollection() {
+ return allowed;
+ }
+
+ /**
+ * @param allowed The allowed to set.
+ */
+ public void setAllowedCollection(Collection<String> allowed) {
+ this.allowed = allowed;
+ }
+
+ /**
+ * @param allowed The allowed paramters as comma separated String.
+ */
+ public void setAllowed(String allowed) {
+ setAllowedCollection(asCollection(allowed));
+ }
+
+ /**
+ * Return a collection from the comma delimited String.
+ *
+ * @param commaDelim the comma delimited String.
+ * @return A collection from the comma delimited String. Returns <tt>null</tt> if the string is empty.
+ */
+ private Collection<String> asCollection(String commaDelim) {
+ if (commaDelim == null || commaDelim.trim().length() == 0) {
+ return null;
+ }
+ return TextParseUtil.commaDelimitedStringToSet(commaDelim);
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterNameAware.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterNameAware.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterNameAware.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterNameAware.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+/**
+ * <!-- START SNIPPET: javadoc -->
+ *
+ * This interface is implemented by actions that want to declare acceptable parameters. Works in conjunction with {@link
+ * ParametersInterceptor}. For example, actions may want to create a whitelist of parameters they will accept or a
+ * blacklist of paramters they will reject to prevent clients from setting other unexpected (and possibly dangerous)
+ * parameters.
+ *
+ * <!-- END SNIPPET: javadoc -->
+ *
+ * @author Bob Lee (crazybob@google.com)
+ */
+public interface ParameterNameAware {
+
+ /**
+ * Tests if the the action will accept the parameter with the given name.
+ *
+ * @param parameterName the parameter name
+ * @return <tt> if accepted, <tt>false</tt> otherwise
+ */
+ boolean acceptableParameterName(String parameterName);
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterRemoverInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterRemoverInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterRemoverInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParameterRemoverInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionContext;
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.util.TextParseUtil;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <!-- 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 -->
+ *
+ * <action name="sample" class="org.martingilday.Sample">
+ * <interceptor-ref name="paramRemover">
+ * <param name="paramNames">aParam,anotherParam</param>
+ * <param name="paramValues">--,-1</param>
+ * </interceptor-ref>
+ * <interceptor-ref name="defaultStack" />
+ * ...
+ * </action>
+ *
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ *
+ * @author martin.gilday
+ */
+public class ParameterRemoverInterceptor extends AbstractInterceptor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ParameterRemoverInterceptor.class);
+
+ private static final long serialVersionUID = 1;
+
+ private Set<String> paramNames = Collections.emptySet();
+
+ private Set<String> paramValues = Collections.emptySet();
+
+
+ /**
+ * Decide if the parameter should be removed from the parameter map based on
+ * <code>paramNames</code> and <code>paramValues</code>.
+ *
+ * @see AbstractInterceptor
+ */
+ @Override
+ public String intercept(ActionInvocation invocation) throws Exception {
+ if (!(invocation.getAction() instanceof NoParameters)
+ && (null != this.paramNames)) {
+ ActionContext ac = invocation.getInvocationContext();
+ final Map<String, Object> parameters = ac.getParameters();
+
+ if (parameters != null) {
+ for (String removeName : paramNames) {
+ // 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);
+ }
+}
+
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParametersInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParametersInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParametersInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ParametersInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,436 @@
+/*
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionContext;
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.ValidationAware;
+import org.apache.struts2.xwork2.inject.Inject;
+import org.apache.struts2.xwork2.util.ClearableValueStack;
+import org.apache.struts2.xwork2.util.LocalizedTextUtil;
+import org.apache.struts2.xwork2.util.MemberAccessValueStack;
+import org.apache.struts2.xwork2.util.TextParseUtil;
+import org.apache.struts2.xwork2.util.ValueStack;
+import org.apache.struts2.xwork2.util.ValueStackFactory;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.xwork2.util.reflection.ReflectionContextState;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * <!-- START SNIPPET: description -->
+ * This interceptor sets all parameters on the value stack.
+ * <p/>
+ * This interceptor gets all parameters from {@link ActionContext#getParameters()} and sets them on the value stack by
+ * calling {@link ValueStack#setValue(String, Object)}, typically resulting in the values submitted in a form
+ * request being applied to an action in the value stack. Note that the parameter map must contain a String key and
+ * often containers a String[] for the value.
+ * <p/>
+ * <p/> The interceptor takes one parameter named 'ordered'. When set to true action properties are guaranteed to be
+ * set top-down which means that top action's properties are set first. Then it's subcomponents properties are set.
+ * The reason for this order is to enable a 'factory' pattern. For example, let's assume that one has an action
+ * that contains a property named 'modelClass' that allows to choose what is the underlying implementation of model.
+ * By assuring that modelClass property is set before any model properties are set, it's possible to choose model
+ * implementation during action.setModelClass() call. Similiarily it's possible to use action.setPrimaryKey()
+ * property set call to actually load the model class from persistent storage. Without any assumption on parameter
+ * order you have to use patterns like 'Preparable'.
+ * <p/>
+ * <p/> Because parameter names are effectively OGNL statements, it is important that security be taken in to account.
+ * This interceptor will not apply any values in the parameters map if the expression contains an assignment (=),
+ * multiple expressions (,), or references any objects in the context (#). This is all done in the {@link
+ * #acceptableName(String)} method. In addition to this method, if the action being invoked implements the {@link
+ * ParameterNameAware} interface, the action will be consulted to determine if the parameter should be set.
+ * <p/>
+ * <p/> In addition to these restrictions, a flag ({@link org.apache.struts2.xwork2.util.reflection.ReflectionContextState#DENY_METHOD_EXECUTION}) is set such that
+ * no methods are allowed to be invoked. That means that any expression such as <i>person.doSomething()</i> or
+ * <i>person.getName()</i> will be explicitely forbidden. This is needed to make sure that your application is not
+ * exposed to attacks by malicious users.
+ * <p/>
+ * <p/> While this interceptor is being invoked, a flag ({@link org.apache.struts2.xwork2.util.reflection.ReflectionContextState#CREATE_NULL_OBJECTS}) is turned
+ * on to ensure that any null reference is automatically created - if possible. See the type conversion documentation
+ * and the {@link org.apache.struts2.xwork2.conversion.impl.InstantiatingNullHandler} javadocs for more information.
+ * <p/>
+ * <p/> Finally, a third flag ({@link org.apache.struts2.xwork2.conversion.impl.XWorkConverter#REPORT_CONVERSION_ERRORS}) is set that indicates any errors when
+ * converting the the values to their final data type (String[] -> int) an unrecoverable error occured. With this
+ * flag set, the type conversion errors will be reported in the action context. See the type conversion documentation
+ * and the {@link org.apache.struts2.xwork2.conversion.impl.XWorkConverter} javadocs for more information.
+ * <p/>
+ * <p/> If you are looking for detailed logging information about your parameters, turn on DEBUG level logging for this
+ * interceptor. A detailed log of all the parameter keys and values will be reported.
+ * <p/>
+ * <p/>
+ * <b>Note:</b> Since XWork 2.0.2, this interceptor extends {@link MethodFilterInterceptor}, therefore being
+ * able to deal with excludeMethods / includeMethods parameters. See [Workflow Interceptor]
+ * (class {@link DefaultWorkflowInterceptor}) for documentation and examples on how to use this feature.
+ * <p/>
+ * <!-- END SNIPPET: description -->
+ * <p/>
+ * <p/> <u>Interceptor parameters:</u>
+ * <p/>
+ * <!-- START SNIPPET: parameters -->
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li>ordered - set to true if you want the top-down property setter behaviour</li>
+ * <p/>
+ * </ul>
+ * <p/>
+ * <!-- END SNIPPET: parameters -->
+ * <p/>
+ * <p/> <u>Extending the interceptor:</u>
+ * <p/>
+ * <!-- START SNIPPET: extending -->
+ * <p/>
+ * <p/> The best way to add behavior to this interceptor is to utilize the {@link ParameterNameAware} interface in your
+ * actions. However, if you wish to apply a global rule that isn't implemented in your action, then you could extend
+ * this interceptor and override the {@link #acceptableName(String)} method.
+ * <p/>
+ * <!-- END SNIPPET: extending -->
+ * <p/>
+ * <p/> <u>Example code:</u>
+ * <p/>
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * <action name="someAction" class="com.examples.SomeAction">
+ * <interceptor-ref name="params"/>
+ * <result name="success">good_result.ftl</result>
+ * </action>
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @author Patrick Lightbody
+ */
+public class ParametersInterceptor extends MethodFilterInterceptor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ParametersInterceptor.class);
+
+ boolean ordered = false;
+ Set<Pattern> excludeParams = Collections.emptySet();
+ Set<Pattern> acceptParams = Collections.emptySet();
+ static boolean devMode = false;
+
+ // Allowed names of parameters
+ private String acceptedParamNames = "[a-zA-Z0-9\\.\\]\\[\\(\\)_'\\s]+";
+ private Pattern acceptedPattern = Pattern.compile(acceptedParamNames);
+
+ private ValueStackFactory valueStackFactory;
+
+ @Inject
+ public void setValueStackFactory(ValueStackFactory valueStackFactory) {
+ this.valueStackFactory = valueStackFactory;
+ }
+
+ @Inject("devMode")
+ public static void setDevMode(String mode) {
+ devMode = "true".equals(mode);
+ }
+
+ public void setAcceptParamNames(String commaDelim) {
+ Collection<String> acceptPatterns = asCollection(commaDelim);
+ if (acceptPatterns != null) {
+ acceptParams = new HashSet<Pattern>();
+ for (String pattern : acceptPatterns) {
+ acceptParams.add(Pattern.compile(pattern));
+ }
+ }
+ }
+
+ static private int countOGNLCharacters(String s) {
+ int count = 0;
+ for (int i = s.length() - 1; i >= 0; i--) {
+ char c = s.charAt(i);
+ if (c == '.' || c == '[') count++;
+ }
+ return count;
+ }
+
+ /**
+ * Compares based on number of '.' and '[' characters (fewer is higher)
+ */
+ static final Comparator<String> rbCollator = new Comparator<String>() {
+ public int compare(String s1, String s2) {
+ int l1 = countOGNLCharacters(s1),
+ l2 = countOGNLCharacters(s2);
+ return l1 < l2 ? -1 : (l2 < l1 ? 1 : s1.compareTo(s2));
+ }
+
+ };
+
+ @Override
+ public String doIntercept(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+ if (!(action instanceof NoParameters)) {
+ ActionContext ac = invocation.getInvocationContext();
+ final Map<String, Object> parameters = retrieveParameters(ac);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Setting params " + getParameterLogMap(parameters));
+ }
+
+ if (parameters != null) {
+ Map<String, Object> contextMap = ac.getContextMap();
+ try {
+ ReflectionContextState.setCreatingNullObjects(contextMap, true);
+ ReflectionContextState.setDenyMethodExecution(contextMap, true);
+ ReflectionContextState.setReportingConversionErrors(contextMap, true);
+
+ ValueStack stack = ac.getValueStack();
+ setParameters(action, stack, parameters);
+ } finally {
+ ReflectionContextState.setCreatingNullObjects(contextMap, false);
+ ReflectionContextState.setDenyMethodExecution(contextMap, false);
+ ReflectionContextState.setReportingConversionErrors(contextMap, false);
+ }
+ }
+ }
+ return invocation.invoke();
+ }
+
+ /**
+ * Gets the parameter map to apply from wherever appropriate
+ *
+ * @param ac The action context
+ * @return The parameter map to apply
+ */
+ protected Map<String, Object> retrieveParameters(ActionContext ac) {
+ return ac.getParameters();
+ }
+
+
+ /**
+ * Adds the parameters into context's ParameterMap
+ *
+ * @param ac The action context
+ * @param newParams The parameter map to apply
+ * <p/>
+ * In this class this is a no-op, since the parameters were fetched from the same location.
+ * In subclasses both retrieveParameters() and addParametersToContext() should be overridden.
+ */
+ protected void addParametersToContext(ActionContext ac, Map<String, Object> newParams) {
+ }
+
+ protected void setParameters(Object action, ValueStack stack, final Map<String, Object> parameters) {
+ ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware)
+ ? (ParameterNameAware) action : null;
+
+ Map<String, Object> params;
+ Map<String, Object> acceptableParameters;
+ if (ordered) {
+ params = new TreeMap<String, Object>(getOrderedComparator());
+ acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());
+ params.putAll(parameters);
+ } else {
+ params = new TreeMap<String, Object>(parameters);
+ acceptableParameters = new TreeMap<String, Object>();
+ }
+
+ for (Map.Entry<String, Object> entry : params.entrySet()) {
+ String name = entry.getKey();
+
+ boolean acceptableName = acceptableName(name)
+ && (parameterNameAware == null
+ || parameterNameAware.acceptableParameterName(name));
+
+ if (acceptableName) {
+ acceptableParameters.put(name, entry.getValue());
+ }
+ }
+
+ ValueStack newStack = valueStackFactory.createValueStack(stack);
+ boolean clearableStack = newStack instanceof ClearableValueStack;
+ if (clearableStack) {
+ //if the stack's context can be cleared, do that to prevent OGNL
+ //from having access to objects in the stack, see XW-641
+ ((ClearableValueStack)newStack).clearContextValues();
+ Map<String, Object> context = newStack.getContext();
+ ReflectionContextState.setCreatingNullObjects(context, true);
+ ReflectionContextState.setDenyMethodExecution(context, true);
+ ReflectionContextState.setReportingConversionErrors(context, true);
+
+ //keep locale from original context
+ context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
+ }
+
+ boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
+ if (memberAccessStack) {
+ //block or allow access to properties
+ //see WW-2761 for more details
+ MemberAccessValueStack accessValueStack = (MemberAccessValueStack) newStack;
+ accessValueStack.setAcceptProperties(acceptParams);
+ accessValueStack.setExcludeProperties(excludeParams);
+ }
+
+ for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {
+ String name = entry.getKey();
+ Object value = entry.getValue();
+ try {
+ newStack.setValue(name, value);
+ } catch (RuntimeException e) {
+ if (devMode) {
+ String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{
+ "Unexpected Exception caught setting '" + name + "' on '" + action.getClass() + ": " + e.getMessage()
+ });
+ LOG.error(developerNotification);
+ if (action instanceof ValidationAware) {
+ ((ValidationAware) action).addActionMessage(developerNotification);
+ }
+ }
+ }
+ }
+
+ if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))
+ stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS));
+
+ addParametersToContext(ActionContext.getContext(), acceptableParameters);
+ }
+
+ /**
+ * Gets an instance of the comparator to use for the ordered sorting. Override this
+ * method to customize the ordering of the parameters as they are set to the
+ * action.
+ *
+ * @return A comparator to sort the parameters
+ */
+ protected Comparator<String> getOrderedComparator() {
+ return rbCollator;
+ }
+
+ private String getParameterLogMap(Map<String, Object> parameters) {
+ if (parameters == null) {
+ return "NONE";
+ }
+
+ StringBuilder logEntry = new StringBuilder();
+ for (Map.Entry entry : parameters.entrySet()) {
+ logEntry.append(String.valueOf(entry.getKey()));
+ logEntry.append(" => ");
+ if (entry.getValue() instanceof Object[]) {
+ Object[] valueArray = (Object[]) entry.getValue();
+ logEntry.append("[ ");
+ if (valueArray.length > 0 ) {
+ for (int indexA = 0; indexA < (valueArray.length - 1); indexA++) {
+ Object valueAtIndex = valueArray[indexA];
+ logEntry.append(String.valueOf(valueAtIndex));
+ logEntry.append(", ");
+ }
+ logEntry.append(String.valueOf(valueArray[valueArray.length - 1]));
+ }
+ logEntry.append(" ] ");
+ } else {
+ logEntry.append(String.valueOf(entry.getValue()));
+ }
+ }
+
+ return logEntry.toString();
+ }
+
+ protected boolean acceptableName(String name) {
+ return isAccepted(name) && !isExcluded(name);
+ }
+
+ protected boolean isAccepted(String paramName) {
+ if (!this.acceptParams.isEmpty()) {
+ for (Pattern pattern : acceptParams) {
+ Matcher matcher = pattern.matcher(paramName);
+ if (matcher.matches()) {
+ return true;
+ }
+ }
+ return false;
+ } else
+ return acceptedPattern.matcher(paramName).matches();
+ }
+
+ protected boolean isExcluded(String paramName) {
+ if (!this.excludeParams.isEmpty()) {
+ for (Pattern pattern : excludeParams) {
+ Matcher matcher = pattern.matcher(paramName);
+ if (matcher.matches()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Whether to order the parameters or not
+ *
+ * @return True to order
+ */
+ public boolean isOrdered() {
+ return ordered;
+ }
+
+ /**
+ * Set whether to order the parameters by object depth or not
+ *
+ * @param ordered True to order them
+ */
+ public void setOrdered(boolean ordered) {
+ this.ordered = ordered;
+ }
+
+ /**
+ * Gets a set of regular expressions of parameters to remove
+ * from the parameter map
+ *
+ * @return A set of compiled regular expression patterns
+ */
+ protected Set getExcludeParamsSet() {
+ return excludeParams;
+ }
+
+ /**
+ * Sets a comma-delimited list of regular expressions to match
+ * parameters that should be removed from the parameter map.
+ *
+ * @param commaDelim A comma-delimited list of regular expressions
+ */
+ public void setExcludeParams(String commaDelim) {
+ Collection<String> excludePatterns = asCollection(commaDelim);
+ if (excludePatterns != null) {
+ excludeParams = new HashSet<Pattern>();
+ for (String pattern : excludePatterns) {
+ excludeParams.add(Pattern.compile(pattern));
+ }
+ }
+ }
+
+ /**
+ * Return a collection from the comma delimited String.
+ *
+ * @param commaDelim the comma delimited String.
+ * @return A collection from the comma delimited String. Returns <tt>null</tt> if the string is empty.
+ */
+ private Collection<String> asCollection(String commaDelim) {
+ if (commaDelim == null || commaDelim.trim().length() == 0) {
+ return null;
+ }
+ return TextParseUtil.commaDelimitedStringToSet(commaDelim);
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PreResultListener.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PreResultListener.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PreResultListener.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PreResultListener.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionInvocation;
+
+
+/**
+ * PreResultListeners may be registered with an {@link ActionInvocation} to get a callback after the
+ * {@link org.apache.struts2.xwork2.Action} has been executed but before the {@link org.apache.struts2.xwork2.Result}
+ * is executed.
+ *
+ * @author Jason Carreira
+ */
+public interface PreResultListener {
+
+ /**
+ * This callback method will be called after the {@link org.apache.struts2.xwork2.Action} execution and
+ * before the {@link org.apache.struts2.xwork2.Result} execution.
+ *
+ * @param invocation the action invocation
+ * @param resultCode the result code returned by the action (eg. <code>success</code>).
+ */
+ void beforeResult(ActionInvocation invocation, String resultCode);
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrefixMethodInvocationUtil.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrefixMethodInvocationUtil.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrefixMethodInvocationUtil.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrefixMethodInvocationUtil.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * A utility class for invoking prefixed methods in action class.
+ *
+ * Interceptors that made use of this class are:
+ * <ul>
+ * <li>DefaultWorkflowInterceptor</li>
+ * <li>PrepareInterceptor</li>
+ * </ul>
+ *
+ * <p/>
+ *
+ * <!-- START SNIPPET: javadocDefaultWorkflowInterceptor -->
+ *
+ * <b>In DefaultWorkflowInterceptor</b>
+ * <p>applies only when action implements {@link org.apache.struts2.xwork2.Validateable}</p>
+ * <ol>
+ * <li>if the action class have validate{MethodName}(), it will be invoked</li>
+ * <li>else if the action class have validateDo{MethodName}(), it will be invoked</li>
+ * <li>no matter if 1] or 2] is performed, if alwaysInvokeValidate property of the interceptor is "true" (which is by default "true"), validate() will be invoked.</li>
+ * </ol>
+ *
+ * <!-- END SNIPPET: javadocDefaultWorkflowInterceptor -->
+ *
+ *
+ * <!-- START SNIPPET: javadocPrepareInterceptor -->
+ *
+ * <b>In PrepareInterceptor</b>
+ * <p>Applies only when action implements Preparable</p>
+ * <ol>
+ * <li>if the action class have prepare{MethodName}(), it will be invoked</li>
+ * <li>else if the action class have prepareDo(MethodName()}(), it will be invoked</li>
+ * <li>no matter if 1] or 2] is performed, if alwaysinvokePrepare property of the interceptor is "true" (which is by default "true"), prepare() will be invoked.</li>
+ * </ol>
+ *
+ * <!-- END SNIPPET: javadocPrepareInterceptor -->
+ *
+ * @author Philip Luppens
+ * @author tm_jee
+ */
+public class PrefixMethodInvocationUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PrefixMethodInvocationUtil.class);
+
+ private static final String DEFAULT_INVOCATION_METHODNAME = "execute";
+
+ private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+
+ /**
+ * This method will prefix <code>actionInvocation</code>'s <code>ActionProxy</code>'s
+ * <code>method</code> with <code>prefixes</code> before invoking the prefixed method.
+ * Order of the <code>prefixes</code> is important, as this method will return once
+ * a prefixed method is found in the action class.
+ *
+ * <p/>
+ *
+ * For example, with
+ * <pre>
+ * invokePrefixMethod(actionInvocation, new String[] { "prepare", "prepareDo" });
+ * </pre>
+ *
+ * Assuming <code>actionInvocation.getProxy(),getMethod()</code> returns "submit",
+ * the order of invocation would be as follows:-
+ * <ol>
+ * <li>prepareSubmit()</li>
+ * <li>prepareDoSubmit()</li>
+ * </ol>
+ *
+ * If <code>prepareSubmit()</code> exists, it will be invoked and this method
+ * will return, <code>prepareDoSubmit()</code> will NOT be invoked.
+ *
+ * <p/>
+ *
+ * On the other hand, if <code>prepareDoSubmit()</code> does not exists, and
+ * <code>prepareDoSubmit()</code> exists, it will be invoked.
+ *
+ * <p/>
+ *
+ * If none of those two methods exists, nothing will be invoked.
+ *
+ * @param actionInvocation the action invocation
+ * @param prefixes prefixes for method names
+ * @throws InvocationTargetException is thrown if invocation of a method failed.
+ * @throws IllegalAccessException is thrown if invocation of a method failed.
+ */
+ public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException {
+ Object action = actionInvocation.getAction();
+
+ String methodName = actionInvocation.getProxy().getMethod();
+
+ if (methodName == null) {
+ // if null returns (possible according to the docs), use the default execute
+ methodName = DEFAULT_INVOCATION_METHODNAME;
+ }
+
+ Method method = getPrefixedMethod(prefixes, methodName, action);
+ if (method != null) {
+ method.invoke(action, new Object[0]);
+ }
+ }
+
+
+ /**
+ * This method returns a {@link Method} in <code>action</code>. The method
+ * returned is found by searching for method in <code>action</code> whose method name
+ * is equals to the result of appending each <code>prefixes</code>
+ * to <code>methodName</code>. Only the first method found will be returned, hence
+ * the order of <code>prefixes</code> is important. If none is found this method
+ * will return null.
+ *
+ * @param prefixes the prefixes to prefix the <code>methodName</code>
+ * @param methodName the method name to be prefixed with <code>prefixes</code>
+ * @param action the action class of which the prefixed method is to be search for.
+ * @return a {@link Method} if one is found, else <tt>null</tt>.
+ */
+ public static Method getPrefixedMethod(String[] prefixes, String methodName, Object action) {
+ assert(prefixes != null);
+ String capitalizedMethodName = capitalizeMethodName(methodName);
+ for (String prefixe : prefixes) {
+ String prefixedMethodName = prefixe + capitalizedMethodName;
+ try {
+ return action.getClass().getMethod(prefixedMethodName, EMPTY_CLASS_ARRAY);
+ }
+ catch (NoSuchMethodException e) {
+ // hmm -- OK, try next prefix
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("cannot find method [" + prefixedMethodName + "] in action [" + action + "]");
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * This method capitalized the first character of <code>methodName</code>.
+ * <br/>
+ * eg. <code>capitalizeMethodName("someMethod");</code> will return <code>"SomeMethod"</code>.
+ *
+ * @param methodName the method name
+ * @return capitalized method name
+ */
+ public static String capitalizeMethodName(String methodName) {
+ assert(methodName != null);
+ return methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrepareInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrepareInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrepareInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/PrepareInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,172 @@
+/*
+ * $Id: PrepareInterceptor.java 1209415 2011-12-02 11:24:48Z lukaszlenart $
+ * Copyright 2002-2007,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.Preparable;
+
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * This interceptor calls <code>prepare()</code> on actions which implement
+ * {@link org.apache.struts2.xwork2.Preparable}. This interceptor is very useful for any situation where
+ * you need to ensure some logic runs before the actual execute method runs.
+ *
+ * <p/> A typical use of this is to run some logic to load an object from the
+ * database so that when parameters are set they can be set on this object. For
+ * example, suppose you have a User object with two properties: <i>id</i> and
+ * <i>name</i>. Provided that the params interceptor is called twice (once
+ * before and once after this interceptor), you can load the User object using
+ * the id property, and then when the second params interceptor is called the
+ * parameter <i>user.name</i> will be set, as desired, on the actual object
+ * loaded from the database. See the example for more info.
+ *
+ * <p/>
+ * <b>Note:</b> Since XWork 2.0.2, this interceptor extends {@link MethodFilterInterceptor}, therefore being
+ * able to deal with excludeMethods / includeMethods parameters. See [Workflow Interceptor]
+ * (class {@link DefaultWorkflowInterceptor}) for documentation and examples on how to use this feature.
+ *
+ * <p/><b>Update</b>: Added logic to execute a prepare{MethodName} and conditionally
+ * the a general prepare() Method, depending on the 'alwaysInvokePrepare' parameter/property
+ * which is by default true. This allows us to run some logic based on the method
+ * name we specify in the {@link org.apache.struts2.xwork2.ActionProxy}. For example, you can specify a
+ * prepareInput() method that will be run before the invocation of the input method.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <p/> <u>Interceptor parameters:</u>
+ *
+ * <!-- START SNIPPET: parameters -->
+ *
+ * <ul>
+ *
+ * <li>alwaysInvokePrepare - Default to true. If true, prepare will always be invoked,
+ * otherwise it will not.</li>
+ *
+ * </ul>
+ *
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <p/> <u>Extending the interceptor:</u>
+ *
+ * <p/>
+ *
+ * <!-- START SNIPPET: extending -->
+ *
+ * There are no known extension points to this interceptor.
+ *
+ * <!-- END SNIPPET: extending -->
+ *
+ * <p/> <u>Example code:</u>
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * <!-- Calls the params interceptor twice, allowing you to
+ * pre-load data for the second time parameters are set -->
+ * <action name="someAction" class="com.examples.SomeAction">
+ * <interceptor-ref name="params"/>
+ * <interceptor-ref name="prepare"/>
+ * <interceptor-ref name="basicStack"/>
+ * <result name="success">good_result.ftl</result>
+ * </action>
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @author Jason Carreira
+ * @author Philip Luppens
+ * @author tm_jee
+ * @see org.apache.struts2.xwork2.Preparable
+ */
+public class PrepareInterceptor extends MethodFilterInterceptor {
+
+ private static final long serialVersionUID = -5216969014510719786L;
+
+ private final static String PREPARE_PREFIX = "prepare";
+ private final static String ALT_PREPARE_PREFIX = "prepareDo";
+
+ private boolean alwaysInvokePrepare = true;
+ private boolean firstCallPrepareDo = false;
+
+ /**
+ * Sets if the <code>preapare</code> method should always be executed.
+ * <p/>
+ * Default is <tt>true</tt>.
+ *
+ * @param alwaysInvokePrepare if <code>prepare</code> should always be executed or not.
+ */
+ public void setAlwaysInvokePrepare(String alwaysInvokePrepare) {
+ this.alwaysInvokePrepare = Boolean.parseBoolean(alwaysInvokePrepare);
+ }
+
+ /**
+ * Sets if the <code>prepareDoXXX</code> method should be called first
+ * <p/>
+ * Default is <tt>false</tt> for backward compatibility
+ *
+ * @param firstCallPrepareDo if <code>prepareDoXXX</code> should be called first
+ */
+ public void setFirstCallPrepareDo(String firstCallPrepareDo) {
+ this.firstCallPrepareDo = Boolean.parseBoolean(firstCallPrepareDo);
+ }
+
+ @Override
+ public String doIntercept(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+
+ if (action instanceof Preparable) {
+ try {
+ String[] prefixes;
+ if (firstCallPrepareDo) {
+ prefixes = new String[] {ALT_PREPARE_PREFIX, PREPARE_PREFIX};
+ } else {
+ prefixes = new String[] {PREPARE_PREFIX, ALT_PREPARE_PREFIX};
+ }
+ PrefixMethodInvocationUtil.invokePrefixMethod(invocation, prefixes);
+ }
+ catch (InvocationTargetException e) {
+ /*
+ * The invoked method threw an exception and reflection wrapped it
+ * in an InvocationTargetException.
+ * If possible re-throw the original exception so that normal
+ * exception handling will take place.
+ */
+ Throwable cause = e.getCause();
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ } else if(cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ /*
+ * The cause is not an Exception or Error (must be Throwable) so
+ * just re-throw the wrapped exception.
+ */
+ throw e;
+ }
+ }
+
+ if (alwaysInvokePrepare) {
+ ((Preparable) action).prepare();
+ }
+ }
+
+ return invocation.invoke();
+ }
+
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDriven.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDriven.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDriven.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDriven.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ModelDriven;
+
+/**
+ * Adds the ability to set a model, probably retrieved from a given state.
+ */
+public interface ScopedModelDriven<T> extends ModelDriven<T> {
+
+ /**
+ * Sets the model
+ */
+ void setModel(T model);
+
+ /**
+ * Sets the key under which the model is stored
+ * @param key The model key
+ */
+ void setScopeKey(String key);
+
+ /**
+ * Gets the key under which the model is stored
+ */
+ String getScopeKey();
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDrivenInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDrivenInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDrivenInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/ScopedModelDrivenInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionContext;
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.ObjectFactory;
+import org.apache.struts2.xwork2.XWorkException;
+import org.apache.struts2.xwork2.config.entities.ActionConfig;
+import org.apache.struts2.xwork2.inject.Inject;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * An interceptor that enables scoped model-driven actions.
+ *
+ * <p/>This interceptor only activates on actions that implement the {@link ScopedModelDriven} interface. If
+ * detected, it will retrieve the model class from the configured scope, then provide it to the Action.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <p/> <u>Interceptor parameters:</u>
+ *
+ * <!-- START SNIPPET: parameters -->
+ *
+ * <ul>
+ *
+ * <li>className - The model class name. Defaults to the class name of the object returned by the getModel() method.</li>
+ *
+ * <li>name - The key to use when storing or retrieving the instance in a scope. Defaults to the model
+ * class name.</li>
+ *
+ * <li>scope - The scope to store and retrieve the model. Defaults to 'request' but can also be 'session'.</li>
+ * </ul>
+ *
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <p/> <u>Extending the interceptor:</u>
+ *
+ * <p/>
+ *
+ * <!-- START SNIPPET: extending -->
+ *
+ * There are no known extension points for this interceptor.
+ *
+ * <!-- END SNIPPET: extending -->
+ *
+ * <p/> <u>Example code:</u>
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ *
+ * <-- Basic usage -->
+ * <interceptor name="scopedModelDriven" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor" />
+ *
+ * <-- Using all available parameters -->
+ * <interceptor name="gangsterForm" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor">
+ * <param name="scope">session</param>
+ * <param name="name">gangsterForm</param>
+ * <param name="className">com.opensymphony.example.GangsterForm</param>
+ * </interceptor>
+ *
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ */
+public class ScopedModelDrivenInterceptor extends AbstractInterceptor {
+
+ private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+
+ private static final String GET_MODEL = "getModel";
+ private String scope;
+ private String name;
+ private String className;
+ private ObjectFactory objectFactory;
+
+ @Inject
+ public void setObjectFactory(ObjectFactory factory) {
+ this.objectFactory = factory;
+ }
+
+ protected Object resolveModel(ObjectFactory factory, ActionContext actionContext, String modelClassName, String modelScope, String modelName) throws Exception {
+ Object model = null;
+ Map<String, Object> scopeMap = actionContext.getContextMap();
+ if ("session".equals(modelScope)) {
+ scopeMap = actionContext.getSession();
+ }
+
+ model = scopeMap.get(modelName);
+ if (model == null) {
+ model = factory.buildBean(modelClassName, null);
+ scopeMap.put(modelName, model);
+ }
+ return model;
+ }
+
+ @Override
+ public String intercept(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+
+ if (action instanceof ScopedModelDriven) {
+ ScopedModelDriven modelDriven = (ScopedModelDriven) action;
+ if (modelDriven.getModel() == null) {
+ ActionContext ctx = ActionContext.getContext();
+ ActionConfig config = invocation.getProxy().getConfig();
+
+ String cName = className;
+ if (cName == null) {
+ try {
+ Method method = action.getClass().getMethod(GET_MODEL, EMPTY_CLASS_ARRAY);
+ Class cls = method.getReturnType();
+ cName = cls.getName();
+ } catch (NoSuchMethodException e) {
+ throw new XWorkException("The " + GET_MODEL + "() is not defined in action " + action.getClass() + "", config);
+ }
+ }
+ String modelName = name;
+ if (modelName == null) {
+ modelName = cName;
+ }
+ Object model = resolveModel(objectFactory, ctx, cName, scope, modelName);
+ modelDriven.setModel(model);
+ modelDriven.setScopeKey(modelName);
+ }
+ }
+ return invocation.invoke();
+ }
+
+ /**
+ * @param className the className to set
+ */
+ public void setClassName(String className) {
+ this.className = className;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @param scope the scope to set
+ */
+ public void setScope(String scope) {
+ this.scope = scope;
+ }
+}
Added: struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/StaticParametersInterceptor.java
URL: http://svn.apache.org/viewvc/struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/StaticParametersInterceptor.java?rev=1209569&view=auto
==============================================================================
--- struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/StaticParametersInterceptor.java (added)
+++ struts/struts2/branches/STRUTS_3_X/xwork-core/src/main/java/org/apache/struts2/xwork2/interceptor/StaticParametersInterceptor.java Fri Dec 2 16:33:03 2011
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.xwork2.interceptor;
+
+import org.apache.struts2.xwork2.ActionContext;
+import org.apache.struts2.xwork2.ActionInvocation;
+import org.apache.struts2.xwork2.ValidationAware;
+import org.apache.struts2.xwork2.inject.Inject;
+import org.apache.struts2.xwork2.config.entities.ActionConfig;
+import org.apache.struts2.xwork2.config.entities.Parameterizable;
+import org.apache.struts2.xwork2.util.ClearableValueStack;
+import org.apache.struts2.xwork2.util.LocalizedTextUtil;
+import org.apache.struts2.xwork2.util.reflection.ReflectionContextState;
+import org.apache.struts2.xwork2.util.logging.Logger;
+import org.apache.struts2.xwork2.util.logging.LoggerFactory;
+import org.apache.struts2.xwork2.util.TextParseUtil;
+import org.apache.struts2.xwork2.util.ValueStack;
+import org.apache.struts2.xwork2.util.ValueStackFactory;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * This interceptor populates the action with the static parameters defined in the action configuration. If the action
+ * implements {@link org.apache.struts2.xwork2.config.entities.Parameterizable}, a map of the static parameters will be also be passed directly to the action.
+ * The static params will be added to the request params map, unless "merge" is set to false.
+ *
+ * <p/> Parameters are typically defined with <param> elements within xwork.xml.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <p/> <u>Interceptor parameters:</u>
+ *
+ * <!-- START SNIPPET: parameters -->
+ *
+ * <ul>
+ *
+ * <li>None</li>
+ *
+ * </ul>
+ *
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <p/> <u>Extending the interceptor:</u>
+ *
+ * <!-- START SNIPPET: extending -->
+ *
+ * <p/>There are no extension points to this interceptor.
+ *
+ * <!-- END SNIPPET: extending -->
+ *
+ * <p/> <u>Example code:</u>
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ * <action name="someAction" class="com.examples.SomeAction">
+ * <interceptor-ref name="staticParams">
+ * <param name="parse">true</param>
+ * <param name="overwrite">false</param>
+ * </interceptor-ref>
+ * <result name="success">good_result.ftl</result>
+ * </action>
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @author Patrick Lightbody
+ */
+public class StaticParametersInterceptor extends AbstractInterceptor {
+
+ private boolean parse;
+ private boolean overwrite;
+ private boolean merge = true;
+
+ static boolean devMode = false;
+
+ private static final Logger LOG = LoggerFactory.getLogger(StaticParametersInterceptor.class);
+
+ private ValueStackFactory valueStackFactory;
+
+ @Inject
+ public void setValueStackFactory(ValueStackFactory valueStackFactory) {
+ this.valueStackFactory = valueStackFactory;
+ }
+
+ @Inject("devMode")
+ public static void setDevMode(String mode) {
+ devMode = "true".equals(mode);
+ }
+
+ public void setParse(String value) {
+ this.parse = Boolean.valueOf(value).booleanValue();
+ }
+
+ public void setMerge(String value) {
+ this.merge = Boolean.valueOf(value).booleanValue();
+ }
+
+ /**
+ * Overwrites already existing parameters from other sources.
+ * Static parameters are the successor over previously set parameters, if true.
+ *
+ * @param value
+ */
+ public void setOverwrite(String value) {
+ this.overwrite = Boolean.valueOf(value).booleanValue();
+ }
+
+ @Override
+ public String intercept(ActionInvocation invocation) throws Exception {
+ ActionConfig config = invocation.getProxy().getConfig();
+ Object action = invocation.getAction();
+
+ final Map<String, String> parameters = config.getParams();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Setting static parameters " + parameters);
+ }
+
+ // for actions marked as Parameterizable, pass the static parameters directly
+ if (action instanceof Parameterizable) {
+ ((Parameterizable) action).setParams(parameters);
+ }
+
+ if (parameters != null) {
+ ActionContext ac = ActionContext.getContext();
+ Map<String, Object> contextMap = ac.getContextMap();
+ try {
+ ReflectionContextState.setCreatingNullObjects(contextMap, true);
+ ReflectionContextState.setReportingConversionErrors(contextMap, true);
+ final ValueStack stack = ac.getValueStack();
+
+ ValueStack newStack = valueStackFactory.createValueStack(stack);
+ boolean clearableStack = newStack instanceof ClearableValueStack;
+ if (clearableStack) {
+ //if the stack's context can be cleared, do that to prevent OGNL
+ //from having access to objects in the stack, see XW-641
+ ((ClearableValueStack)newStack).clearContextValues();
+ Map<String, Object> context = newStack.getContext();
+ ReflectionContextState.setCreatingNullObjects(context, true);
+ ReflectionContextState.setDenyMethodExecution(context, true);
+ ReflectionContextState.setReportingConversionErrors(context, true);
+
+ //keep locale from original context
+ context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
+ }
+
+ for (Map.Entry<String, String> entry : parameters.entrySet()) {
+ Object val = entry.getValue();
+ if (parse && val instanceof String) {
+ val = TextParseUtil.translateVariables(val.toString(), stack);
+ }
+ try {
+ newStack.setValue(entry.getKey(), val);
+ } catch (RuntimeException e) {
+ if (devMode) {
+ String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{
+ "Unexpected Exception caught setting '" + entry.getKey() + "' on '" + action.getClass() + ": " + e.getMessage()
+ });
+ LOG.error(developerNotification);
+ if (action instanceof ValidationAware) {
+ ((ValidationAware) action).addActionMessage(developerNotification);
+ }
+ }
+ }
+ }
+
+ if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))
+ stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS));
+
+ if (merge)
+ addParametersToContext(ac, parameters);
+ } finally {
+ ReflectionContextState.setCreatingNullObjects(contextMap, false);
+ ReflectionContextState.setReportingConversionErrors(contextMap, false);
+ }
+ }
+ return invocation.invoke();
+ }
+
+
+ /**
+ * @param ac The action context
+ * @return the parameters from the action mapping in the context. If none found, returns
+ * an empty map.
+ */
+ protected Map<String, String> retrieveParameters(ActionContext ac) {
+ ActionConfig config = ac.getActionInvocation().getProxy().getConfig();
+ if (config != null) {
+ return config.getParams();
+ } else {
+ return Collections.emptyMap();
+ }
+ }
+
+ /**
+ * Adds the parameters into context's ParameterMap.
+ * As default, static parameters will not overwrite existing paramaters from other sources.
+ * If you want the static parameters as successor over already existing parameters, set overwrite to <tt>true</tt>.
+ *
+ * @param ac The action context
+ * @param newParams The parameter map to apply
+ */
+ protected void addParametersToContext(ActionContext ac, Map<String, ?> newParams) {
+ Map<String, Object> previousParams = ac.getParameters();
+
+ Map<String, Object> combinedParams;
+ if ( overwrite ) {
+ if (previousParams != null) {
+ combinedParams = new TreeMap<String, Object>(previousParams);
+ } else {
+ combinedParams = new TreeMap<String, Object>();
+ }
+ if ( newParams != null) {
+ combinedParams.putAll(newParams);
+ }
+ } else {
+ if (newParams != null) {
+ combinedParams = new TreeMap<String, Object>(newParams);
+ } else {
+ combinedParams = new TreeMap<String, Object>();
+ }
+ if ( previousParams != null) {
+ combinedParams.putAll(previousParams);
+ }
+ }
+ ac.setParameters(combinedParams);
+ }
+}