diff --git a/core/src/main/java/com/opensymphony/xwork2/Action.java b/core/src/main/java/com/opensymphony/xwork2/Action.java
index 4c96617c49..57d7678341 100644
--- a/core/src/main/java/com/opensymphony/xwork2/Action.java
+++ b/core/src/main/java/com/opensymphony/xwork2/Action.java
@@ -19,70 +19,10 @@
package com.opensymphony.xwork2;
/**
- * All actions may implement this interface, which exposes the execute()
method.
- *
- * However, as of XWork 1.1, this is not required and is only here to assist users. You are free to create POJOs - * that honor the same contract defined by this interface without actually implementing the interface. - *
+ * {@inheritDoc} + * + * @deprecated since 6.7.0, use {@link org.apache.struts2.Action} instead. */ -public interface Action { - - /** - * The action execution was successful. Show result - * view to the end user. - */ - public static final String SUCCESS = "success"; - - /** - * The action execution was successful but do not - * show a view. This is useful for actions that are - * handling the view in another fashion like redirect. - */ - public static final String NONE = "none"; - - /** - * The action execution was a failure. - * Show an error view, possibly asking the - * user to retry entering data. - */ - public static final String ERROR = "error"; - - /** - *- * The action execution require more input - * in order to succeed. - * This result is typically used if a form - * handling action has been executed so as - * to provide defaults for a form. The - * form associated with the handler should be - * shown to the end user. - *
- * - *- * This result is also used if the given input - * params are invalid, meaning the user - * should try providing input again. - *
- */ - public static final String INPUT = "input"; - - /** - * The action could not execute, since the - * user most was not logged in. The login view - * should be shown. - */ - public static final String LOGIN = "login"; - - - /** - * Where the logic of the action is executed. - * - * @return a string representing the logical result of the execution. - * See constants in this interface for a list of standard result values. - * @throws Exception thrown if a system level exception occurs. - * Note: Application level exceptions should be handled by returning - * an error value, such asAction.ERROR
.
- */
- public String execute() throws Exception;
-
+@Deprecated
+public interface Action extends org.apache.struts2.Action {
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
index fb7b0abcb0..c2a4a39c26 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java
@@ -21,8 +21,6 @@
import com.opensymphony.xwork2.conversion.impl.ConversionData;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.struts2.StrutsException;
-import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
@@ -30,515 +28,238 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
-import java.io.Serializable;
-import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
- * - * The ActionContext is the context in which an {@link Action} is executed. Each context is basically a - * container of objects an action needs for execution like the session, parameters, locale, etc. - *
+ * {@inheritDoc} * - *- * The ActionContext is thread local which means that values stored in the ActionContext are - * unique per thread. See the {@link ThreadLocal} class for more information. The benefit of - * this is you don't need to worry about a user specific action context, you just get it: - *
- * - *ActionContext context = ActionContext.getContext();
- *
- * - * Finally, because of the thread local usage you don't need to worry about making your actions thread safe. - *
- * - * @author Patrick Lightbody - * @author Bill Lynch (docs) + * @deprecated since 6.7.0, use {@link org.apache.struts2.ActionContext} instead. */ -public class ActionContext implements Serializable { - - private static final ThreadLocalAction.NONE
) of an {@link Action} are mapped to a View implementation.
- *
- * - * Examples of Views might be: - *
- * - *- * An interceptor is a stateless class that follows the interceptor pattern, as - * found in {@link javax.servlet.Filter} and in AOP languages. - *
- * - *- * Interceptors are objects that dynamically intercept Action invocations. - * They provide the developer with the opportunity to define code that can be executed - * before and/or after the execution of an action. They also have the ability - * to prevent an action from executing. Interceptors provide developers a way to - * encapsulate common functionality in a re-usable form that can be applied to - * one or more Actions. - *
- * - *- * Interceptors must be stateless and not assume that a new instance will be created for each request or Action. - * Interceptors may choose to either short-circuit the {@link ActionInvocation} execution and return a return code - * (such as {@link com.opensymphony.xwork2.Action#SUCCESS}), or it may choose to do some processing before - * and/or after delegating the rest of the procesing using {@link ActionInvocation#invoke()}. - *
- * - * - * - *- * Interceptor's parameter could be overridden through the following ways :- - *
- - * Method 1: - *- * <action name="myAction" class="myActionClass"> - * <interceptor-ref name="exception"/> - * <interceptor-ref name="alias"/> - * <interceptor-ref name="params"/> - * <interceptor-ref name="servletConfig"/> - * <interceptor-ref name="prepare"/> - * <interceptor-ref name="i18n"/> - * <interceptor-ref name="chain"/> - * <interceptor-ref name="modelDriven"/> - * <interceptor-ref name="fileUpload"/> - * <interceptor-ref name="staticParams"/> - * <interceptor-ref name="params"/> - * <interceptor-ref name="conversionError"/> - * <interceptor-ref name="validation"> - * <param name="excludeMethods">myValidationExcudeMethod</param> - * </interceptor-ref> - * <interceptor-ref name="workflow"> - * <param name="excludeMethods">myWorkflowExcludeMethod</param> - * </interceptor-ref> - * </action> - *- * - * Method 2: - *
- * <action name="myAction" class="myActionClass"> - * <interceptor-ref name="defaultStack"> - * <param name="validation.excludeMethods">myValidationExcludeMethod</param> - * <param name="workflow.excludeMethods">myWorkflowExcludeMethod</param> - * </interceptor-ref> - * </action> - *- * - *
- * In the first method, the whole default stack is copied and the parameter then - * changed accordingly. - *
- * - *- * In the second method, the 'interceptor-ref' refer to an existing - * interceptor-stack, namely defaultStack in this example, and override the validator - * and workflow interceptor excludeMethods typically in this case. Note that in the - * 'param' tag, the name attribute contains a dot (.) the word before the dot(.) - * specifies the interceptor name whose parameter is to be overridden and the word after - * the dot (.) specifies the parameter itself. Essetially it is as follows :- - *
- * - *- * <interceptor-name>.<parameter-name> - *- *
- * Note also that in this case the 'interceptor-ref' name attribute - * is used to indicate an interceptor stack which makes sense as if it is referring - * to the interceptor itself it would be just using Method 1 describe above. - *
- * - * - *- * Nested Interceptor param overriding - *
+ * {@inheritDoc} * - * - *- * Interceptor stack parameter overriding could be nested into as many level as possible, though it would - * be advisable not to nest it too deep as to avoid confusion, For example, - *
- *- * <interceptor name="interceptor1" class="foo.bar.Interceptor1" /> - * <interceptor name="interceptor2" class="foo.bar.Interceptor2" /> - * <interceptor name="interceptor3" class="foo.bar.Interceptor3" /> - * <interceptor name="interceptor4" class="foo.bar.Interceptor4" /> - * <interceptor-stack name="stack1"> - * <interceptor-ref name="interceptor1" /> - * </interceptor-stack> - * <interceptor-stack name="stack2"> - * <interceptor-ref name="intercetor2" /> - * <interceptor-ref name="stack1" /> - * </interceptor-stack> - * <interceptor-stack name="stack3"> - * <interceptor-ref name="interceptor3" /> - * <interceptor-ref name="stack2" /> - * </interceptor-stack> - * <interceptor-stack name="stack4"> - * <interceptor-ref name="interceptor4" /> - * <interceptor-ref name="stack3" /> - * </interceptor-stack> - *- * - *
- * Assuming the interceptor has the following properties - *
- * - *Interceptor | - *property | - *
Interceptor1 | - *param1 | - *
Interceptor2 | - *param2 | - *
Interceptor3 | - *param3 | - *
Interceptor4 | - *param4 | - *
- * We could override them as follows : - *
- * - *- * <action ... > - * <!-- to override parameters of interceptor located directly in the stack --> - * <interceptor-ref name="stack4"> - * <param name="interceptor4.param4"> ... </param> - * </interceptor-ref> - * </action> - * - * <action ... > - * <!-- to override parameters of interceptor located under nested stack --> - * <interceptor-ref name="stack4"> - * <param name="stack3.interceptor3.param3"> ... </param> - * <param name="stack3.stack2.interceptor2.param2"> ... </param> - * <param name="stack3.stack2.stack1.interceptor1.param1"> ... </param> - * </interceptor-ref> - * </action> - *- * - * - * - * @author Jason Carreira - * @author tmjee + * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.Interceptor} instead. */ -public interface Interceptor extends Serializable { - - /** - * Called to let an interceptor clean up any resources it has allocated. - */ - void destroy(); - - /** - * Called after an interceptor is created, but before any requests are processed using - * {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving - * the Interceptor a chance to initialize any needed resources. - */ - void init(); - - /** - * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the - * request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code. - * - * @param invocation the action invocation - * @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself. - * @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}. - */ - String intercept(ActionInvocation invocation) throws Exception; - +@Deprecated +public interface Interceptor extends org.apache.struts2.interceptor.Interceptor { } diff --git a/core/src/main/java/org/apache/struts2/Action.java b/core/src/main/java/org/apache/struts2/Action.java new file mode 100644 index 0000000000..cc3fb83ac1 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/Action.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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; + +/** + * All actions may implement this interface, which exposes the
execute()
method.
+ * + * However, as of XWork 1.1, this is not required and is only here to assist users. You are free to create POJOs + * that honor the same contract defined by this interface without actually implementing the interface. + *
+ */ +public interface Action { + + /** + * The action execution was successful. Show result + * view to the end user. + */ + String SUCCESS = "success"; + + /** + * The action execution was successful but do not + * show a view. This is useful for actions that are + * handling the view in another fashion like redirect. + */ + String NONE = "none"; + + /** + * The action execution was a failure. + * Show an error view, possibly asking the + * user to retry entering data. + */ + String ERROR = "error"; + + /** + *+ * The action execution require more input + * in order to succeed. + * This result is typically used if a form + * handling action has been executed so as + * to provide defaults for a form. The + * form associated with the handler should be + * shown to the end user. + *
+ * + *+ * This result is also used if the given input + * params are invalid, meaning the user + * should try providing input again. + *
+ */ + String INPUT = "input"; + + /** + * The action could not execute, since the + * user most was not logged in. The login view + * should be shown. + */ + String LOGIN = "login"; + + + /** + * Where the logic of the action is executed. + * + * @return a string representing the logical result of the execution. + * See constants in this interface for a list of standard result values. + * @throws Exception thrown if a system level exception occurs. + * Note: Application level exceptions should be handled by returning + * an error value, such asAction.ERROR
.
+ */
+ String execute() throws Exception;
+
+}
diff --git a/core/src/main/java/org/apache/struts2/ActionContext.java b/core/src/main/java/org/apache/struts2/ActionContext.java
new file mode 100644
index 0000000000..8f155cc068
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/ActionContext.java
@@ -0,0 +1,554 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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;
+
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.dispatcher.HttpParameters;
+import org.apache.struts2.dispatcher.mapper.ActionMapping;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.PageContext;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * + * The ActionContext is the context in which an {@link Action} is executed. Each context is basically a + * container of objects an action needs for execution like the session, parameters, locale, etc. + *
+ * + *+ * The ActionContext is thread local which means that values stored in the ActionContext are + * unique per thread. See the {@link ThreadLocal} class for more information. The benefit of + * this is you don't need to worry about a user specific action context, you just get it: + *
+ * + *ActionContext context = ActionContext.getContext();
+ *
+ * + * Finally, because of the thread local usage you don't need to worry about making your actions thread safe. + *
+ * + * @author Patrick Lightbody + * @author Bill Lynch (docs) + */ +public class ActionContext implements Serializable { + + private static final ThreadLocalAction.NONE
) of an {@link Action} are mapped to a View implementation.
+ *
+ * + * Examples of Views might be: + *
+ * + *+ * An interceptor is a stateless class that follows the interceptor pattern, as + * found in {@link javax.servlet.Filter} and in AOP languages. + *
+ * + *+ * Interceptors are objects that dynamically intercept Action invocations. + * They provide the developer with the opportunity to define code that can be executed + * before and/or after the execution of an action. They also have the ability + * to prevent an action from executing. Interceptors provide developers a way to + * encapsulate common functionality in a re-usable form that can be applied to + * one or more Actions. + *
+ * + *+ * Interceptors must be stateless and not assume that a new instance will be created for each request or Action. + * Interceptors may choose to either short-circuit the {@link ActionInvocation} execution and return a return code + * (such as {@link com.opensymphony.xwork2.Action#SUCCESS}), or it may choose to do some processing before + * and/or after delegating the rest of the procesing using {@link ActionInvocation#invoke()}. + *
+ * + * + * + *+ * Interceptor's parameter could be overridden through the following ways :- + *
+ + * Method 1: + *+ * <action name="myAction" class="myActionClass"> + * <interceptor-ref name="exception"/> + * <interceptor-ref name="alias"/> + * <interceptor-ref name="params"/> + * <interceptor-ref name="servletConfig"/> + * <interceptor-ref name="prepare"/> + * <interceptor-ref name="i18n"/> + * <interceptor-ref name="chain"/> + * <interceptor-ref name="modelDriven"/> + * <interceptor-ref name="fileUpload"/> + * <interceptor-ref name="staticParams"/> + * <interceptor-ref name="params"/> + * <interceptor-ref name="conversionError"/> + * <interceptor-ref name="validation"> + * <param name="excludeMethods">myValidationExcudeMethod</param> + * </interceptor-ref> + * <interceptor-ref name="workflow"> + * <param name="excludeMethods">myWorkflowExcludeMethod</param> + * </interceptor-ref> + * </action> + *+ * + * Method 2: + *
+ * <action name="myAction" class="myActionClass"> + * <interceptor-ref name="defaultStack"> + * <param name="validation.excludeMethods">myValidationExcludeMethod</param> + * <param name="workflow.excludeMethods">myWorkflowExcludeMethod</param> + * </interceptor-ref> + * </action> + *+ * + *
+ * In the first method, the whole default stack is copied and the parameter then + * changed accordingly. + *
+ * + *+ * In the second method, the 'interceptor-ref' refer to an existing + * interceptor-stack, namely defaultStack in this example, and override the validator + * and workflow interceptor excludeMethods typically in this case. Note that in the + * 'param' tag, the name attribute contains a dot (.) the word before the dot(.) + * specifies the interceptor name whose parameter is to be overridden and the word after + * the dot (.) specifies the parameter itself. Essetially it is as follows :- + *
+ * + *+ * <interceptor-name>.<parameter-name> + *+ *
+ * Note also that in this case the 'interceptor-ref' name attribute + * is used to indicate an interceptor stack which makes sense as if it is referring + * to the interceptor itself it would be just using Method 1 describe above. + *
+ * + * + *+ * Nested Interceptor param overriding + *
+ * + * + *+ * Interceptor stack parameter overriding could be nested into as many level as possible, though it would + * be advisable not to nest it too deep as to avoid confusion, For example, + *
+ *+ * <interceptor name="interceptor1" class="foo.bar.Interceptor1" /> + * <interceptor name="interceptor2" class="foo.bar.Interceptor2" /> + * <interceptor name="interceptor3" class="foo.bar.Interceptor3" /> + * <interceptor name="interceptor4" class="foo.bar.Interceptor4" /> + * <interceptor-stack name="stack1"> + * <interceptor-ref name="interceptor1" /> + * </interceptor-stack> + * <interceptor-stack name="stack2"> + * <interceptor-ref name="intercetor2" /> + * <interceptor-ref name="stack1" /> + * </interceptor-stack> + * <interceptor-stack name="stack3"> + * <interceptor-ref name="interceptor3" /> + * <interceptor-ref name="stack2" /> + * </interceptor-stack> + * <interceptor-stack name="stack4"> + * <interceptor-ref name="interceptor4" /> + * <interceptor-ref name="stack3" /> + * </interceptor-stack> + *+ * + *
+ * Assuming the interceptor has the following properties + *
+ * + *Interceptor | + *property | + *
Interceptor1 | + *param1 | + *
Interceptor2 | + *param2 | + *
Interceptor3 | + *param3 | + *
Interceptor4 | + *param4 | + *
+ * We could override them as follows : + *
+ * + *+ * <action ... > + * <!-- to override parameters of interceptor located directly in the stack --> + * <interceptor-ref name="stack4"> + * <param name="interceptor4.param4"> ... </param> + * </interceptor-ref> + * </action> + * + * <action ... > + * <!-- to override parameters of interceptor located under nested stack --> + * <interceptor-ref name="stack4"> + * <param name="stack3.interceptor3.param3"> ... </param> + * <param name="stack3.stack2.interceptor2.param2"> ... </param> + * <param name="stack3.stack2.stack1.interceptor1.param1"> ... </param> + * </interceptor-ref> + * </action> + *+ * + * + * + * @author Jason Carreira + * @author tmjee + */ +public interface Interceptor extends Serializable { + + /** + * Called to let an interceptor clean up any resources it has allocated. + */ + void destroy(); + + /** + * Called after an interceptor is created, but before any requests are processed using + * {@link #intercept(ActionInvocation) intercept} , giving + * the Interceptor a chance to initialize any needed resources. + */ + void init(); + + /** + * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the + * request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code. + * + * @param invocation the action invocation + * @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself. + * @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}. + */ + String intercept(ActionInvocation invocation) throws Exception; + +} diff --git a/core/src/test/java/com/opensymphony/xwork2/config/providers/ConfigurationProviderOgnlAllowlistTest.java b/core/src/test/java/com/opensymphony/xwork2/config/providers/ConfigurationProviderOgnlAllowlistTest.java index 4fa4aad8ba..0349f6812b 100644 --- a/core/src/test/java/com/opensymphony/xwork2/config/providers/ConfigurationProviderOgnlAllowlistTest.java +++ b/core/src/test/java/com/opensymphony/xwork2/config/providers/ConfigurationProviderOgnlAllowlistTest.java @@ -61,7 +61,11 @@ public void allowlist() throws Exception { Class.forName("com.opensymphony.xwork2.Action"), Class.forName("com.opensymphony.xwork2.interceptor.AbstractInterceptor"), Class.forName("com.opensymphony.xwork2.Result"), - Class.forName("com.opensymphony.xwork2.SimpleAction") + Class.forName("com.opensymphony.xwork2.SimpleAction"), + Class.forName("org.apache.struts2.interceptor.Interceptor"), + Class.forName("org.apache.struts2.interceptor.ConditionalInterceptor"), + Class.forName("org.apache.struts2.Result"), + Class.forName("org.apache.struts2.Action") ); } @@ -85,7 +89,11 @@ public void allowlist_1only() throws Exception { Class.forName("com.opensymphony.xwork2.Action"), Class.forName("com.opensymphony.xwork2.interceptor.AbstractInterceptor"), Class.forName("com.opensymphony.xwork2.Result"), - Class.forName("com.opensymphony.xwork2.SimpleAction") + Class.forName("com.opensymphony.xwork2.SimpleAction"), + Class.forName("org.apache.struts2.interceptor.Interceptor"), + Class.forName("org.apache.struts2.interceptor.ConditionalInterceptor"), + Class.forName("org.apache.struts2.Result"), + Class.forName("org.apache.struts2.Action") ); } @@ -108,7 +116,11 @@ public void allowlist_2only() throws Exception { Class.forName("com.opensymphony.xwork2.Validateable"), Class.forName("com.opensymphony.xwork2.Action"), Class.forName("com.opensymphony.xwork2.interceptor.AbstractInterceptor"), - Class.forName("com.opensymphony.xwork2.Result") + Class.forName("com.opensymphony.xwork2.Result"), + Class.forName("org.apache.struts2.interceptor.Interceptor"), + Class.forName("org.apache.struts2.interceptor.ConditionalInterceptor"), + Class.forName("org.apache.struts2.Result"), + Class.forName("org.apache.struts2.Action") ); } }