From 7deb4812982af9ee073eead29cc359d0db57bebf Mon Sep 17 00:00:00 2001 From: Kusal Kithul-Godage Date: Thu, 17 Oct 2024 13:12:57 +1100 Subject: [PATCH 1/3] WW-3714 Deprecate and migrate Action, Interceptor, Result --- .../java/com/opensymphony/xwork2/Action.java | 70 +----- .../java/com/opensymphony/xwork2/Result.java | 30 +-- .../xwork2/interceptor/Interceptor.java | 202 +--------------- .../main/java/org/apache/struts2/Action.java | 88 +++++++ .../main/java/org/apache/struts2/Result.java | 53 +++++ .../struts2/interceptor/Interceptor.java | 222 ++++++++++++++++++ ...onfigurationProviderOgnlAllowlistTest.java | 15 +- 7 files changed, 388 insertions(+), 292 deletions(-) create mode 100644 core/src/main/java/org/apache/struts2/Action.java create mode 100644 core/src/main/java/org/apache/struts2/Result.java create mode 100644 core/src/main/java/org/apache/struts2/interceptor/Interceptor.java 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 as Action.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/Result.java b/core/src/main/java/com/opensymphony/xwork2/Result.java index 8c1687e5a6..ccd238751a 100644 --- a/core/src/main/java/com/opensymphony/xwork2/Result.java +++ b/core/src/main/java/com/opensymphony/xwork2/Result.java @@ -18,33 +18,11 @@ */ package com.opensymphony.xwork2; -import java.io.Serializable; - /** - * All results (except for Action.NONE) of an {@link Action} are mapped to a View implementation. - * - *

- * Examples of Views might be: - *

- * - * + * {@inheritDoc} * - * @author plightbo + * @deprecated since 6.7.0, use {@link org.apache.struts2.Result} instead. */ -public interface Result extends Serializable { - - /** - * Represents a generic interface for all action execution results. - * Whether that be displaying a webpage, generating an email, sending a JMS message, etc. - * - * @param invocation the invocation context. - * @throws Exception can be thrown. - */ - void execute(ActionInvocation invocation) throws Exception; - +@Deprecated +public interface Result extends org.apache.struts2.Result { } diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java index cafa08fc0f..87041a269e 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/Interceptor.java @@ -18,205 +18,11 @@ */ package com.opensymphony.xwork2.interceptor; -import com.opensymphony.xwork2.ActionInvocation; - -import java.io.Serializable; - /** - * - * - *

- * 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 - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Interceptorproperty
Interceptor1param1
Interceptor2param2
Interceptor3param3
Interceptor4param4
- * - *

- * 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 as Action.ERROR. + */ + String execute() throws Exception; + +} diff --git a/core/src/main/java/org/apache/struts2/Result.java b/core/src/main/java/org/apache/struts2/Result.java new file mode 100644 index 0000000000..4dc9127727 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/Result.java @@ -0,0 +1,53 @@ +/* + * 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 java.io.Serializable; + +/** + * All results (except for Action.NONE) of an {@link Action} are mapped to a View implementation. + * + *

+ * Examples of Views might be: + *

+ * + * + * + * @author plightbo + */ +public interface Result extends Serializable { + + /** + * Represents a generic interface for all action execution results. + * Whether that be displaying a webpage, generating an email, sending a JMS message, etc. + * + * @param invocation the invocation context. + * @throws Exception can be thrown. + */ + void execute(ActionInvocation invocation) throws Exception; + +} diff --git a/core/src/main/java/org/apache/struts2/interceptor/Interceptor.java b/core/src/main/java/org/apache/struts2/interceptor/Interceptor.java new file mode 100644 index 0000000000..9c36bde770 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/interceptor/Interceptor.java @@ -0,0 +1,222 @@ +/* + * 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.interceptor; + +import com.opensymphony.xwork2.ActionInvocation; + +import java.io.Serializable; + +/** + * + * + *

+ * 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 + *

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Interceptorproperty
Interceptor1param1
Interceptor2param2
Interceptor3param3
Interceptor4param4
+ * + *

+ * 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..77d6bbb226 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,10 @@ 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.Result"), + Class.forName("org.apache.struts2.Action") ); } @@ -85,7 +88,10 @@ 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.Result"), + Class.forName("org.apache.struts2.Action") ); } @@ -108,7 +114,10 @@ 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.Result"), + Class.forName("org.apache.struts2.Action") ); } } From 8da6a79926b5bf04cc376fb639c1da1a0d587b48 Mon Sep 17 00:00:00 2001 From: Kusal Kithul-Godage Date: Thu, 17 Oct 2024 13:13:28 +1100 Subject: [PATCH 2/3] WW-3714 Deprecate and migrate ActionContext --- .../opensymphony/xwork2/ActionContext.java | 467 +++------------ .../org/apache/struts2/ActionContext.java | 554 ++++++++++++++++++ 2 files changed, 648 insertions(+), 373 deletions(-) create mode 100644 core/src/main/java/org/apache/struts2/ActionContext.java 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 ThreadLocal actionContext = new ThreadLocal<>(); - - /** - * Constant for the name of the action being executed. - */ - private static final String ACTION_NAME = "org.apache.struts2.ActionContext.name"; - - /** - * Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}. - */ - private static final String VALUE_STACK = ValueStack.VALUE_STACK; - - /** - * Constant for the action's session. - */ - private static final String SESSION = "org.apache.struts2.ActionContext.session"; - - /** - * Constant for the action's application context. - */ - private static final String APPLICATION = "org.apache.struts2.ActionContext.application"; - - /** - * Constant for the action's parameters. - */ - private static final String PARAMETERS = "org.apache.struts2.ActionContext.parameters"; - - /** - * Constant for the action's locale. - */ - private static final String LOCALE = "org.apache.struts2.ActionContext.locale"; - - /** - * Constant for the action's {@link com.opensymphony.xwork2.ActionInvocation invocation} context. - */ - private static final String ACTION_INVOCATION = "org.apache.struts2.ActionContext.actionInvocation"; - - /** - * Constant for the map of type conversion errors. - */ - private static final String CONVERSION_ERRORS = "org.apache.struts2.ActionContext.conversionErrors"; - - /** - * Constant for the container - */ - private static final String CONTAINER = "org.apache.struts2.ActionContext.container"; - - private final Map context; - - /** - * Creates a new ActionContext initialized with another context. - * - * @param context a context map. - */ - protected ActionContext(Map context) { - this.context = context; - } - - /** - * Creates a new ActionContext based on passed in Map - * - * @param context a map with context values - * @return new ActionContext - */ +@Deprecated +public class ActionContext extends org.apache.struts2.ActionContext { + + private ActionContext(org.apache.struts2.ActionContext actualContext) { + super(actualContext.getContextMap()); + } + + private static ActionContext adapt(org.apache.struts2.ActionContext actualContext) { + return actualContext != null ? new ActionContext(actualContext) : null; + } + public static ActionContext of(Map context) { - if (context == null) { - throw new IllegalArgumentException("Context cannot be null!"); - } - return new ActionContext(context); + return adapt(org.apache.struts2.ActionContext.of(context)); } - /** - * Creates a new ActionContext based on empty Map - * - * @return new ActionContext - */ public static ActionContext of() { - return of(new HashMap<>()); + return adapt(org.apache.struts2.ActionContext.of()); } - /** - * Binds the provided context with the current thread - * - * @param actionContext context to bind to the thread - * @return context which was bound to the thread - */ public static ActionContext bind(ActionContext actionContext) { - ActionContext.setContext(actionContext); - return ActionContext.getContext(); + return adapt(org.apache.struts2.ActionContext.bind(actionContext)); } public static boolean containsValueStack(Map context) { - return context != null && context.containsKey(VALUE_STACK); - } - - /** - * Binds this context with the current thread - * - * @return this context which was bound to the thread - */ - public ActionContext bind() { - ActionContext.setContext(this); - return ActionContext.getContext(); + return org.apache.struts2.ActionContext.containsValueStack(context); } - /** - * Wipes out current ActionContext, use wisely! - */ public static void clear() { - actionContext.remove(); + org.apache.struts2.ActionContext.clear(); } - /** - * Sets the action context for the current thread. - * - * @param context the action context. - */ - private static void setContext(ActionContext context) { - actionContext.set(context); + public static ActionContext getContext() { + return adapt(org.apache.struts2.ActionContext.getContext()); } - /** - * Returns the ActionContext specific to the current thread. - * - * @return the ActionContext for the current thread, is never null. - */ - public static ActionContext getContext() { - return actionContext.get(); + @Override + public ActionContext bind() { + super.bind(); + return this; } - /** - * Sets the action invocation (the execution state). - * - * @param actionInvocation the action execution state. - */ + @Override public ActionContext withActionInvocation(ActionInvocation actionInvocation) { - put(ACTION_INVOCATION, actionInvocation); + super.withActionInvocation(actionInvocation); return this; } - /** - * Gets the action invocation (the execution state). - * - * @return the action invocation (the execution state). - */ + @Override public ActionInvocation getActionInvocation() { - return (ActionInvocation) get(ACTION_INVOCATION); + return super.getActionInvocation(); } - /** - * Sets the action's application context. - * - * @param application the action's application context. - */ + @Override public ActionContext withApplication(Map application) { - put(APPLICATION, application); + super.withApplication(application); return this; } - /** - * Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise. - * - * @return a Map of ServletContext or generic application level Map - */ - @SuppressWarnings("unchecked") + @Override public Map getApplication() { - return (Map) get(APPLICATION); + return super.getApplication(); } - /** - * Gets the context map. - * - * @return the context map. - */ + @Override public Map getContextMap() { - return context; + return super.getContextMap(); } - /** - * Sets conversion errors which occurred when executing the action. - * - * @param conversionErrors a Map of errors which occurred when executing the action. - */ + @Override public ActionContext withConversionErrors(Map conversionErrors) { - put(CONVERSION_ERRORS, conversionErrors); + super.withConversionErrors(conversionErrors); return this; } - /** - * Gets the map of conversion errors which occurred when executing the action. - * - * @return the map of conversion errors which occurred when executing the action or an empty map if - * there were no errors. - */ - @SuppressWarnings("unchecked") + @Override public Map getConversionErrors() { - Map errors = (Map) get(CONVERSION_ERRORS); - - if (errors == null) { - errors = withConversionErrors(new HashMap<>()).getConversionErrors(); - } - - return errors; + return super.getConversionErrors(); } - /** - * Sets the Locale for the current action. - * - * @param locale the Locale for the current action. - */ + @Override public ActionContext withLocale(Locale locale) { - put(LOCALE, locale); + super.withLocale(locale); return this; } - /** - * Gets the Locale of the current action. If no locale was ever specified the platform's - * {@link java.util.Locale#getDefault() default locale} is used. - * - * @return the Locale of the current action. - */ + @Override public Locale getLocale() { - Locale locale = (Locale) get(LOCALE); - - if (locale == null) { - locale = Locale.getDefault(); - withLocale(locale); - } - - return locale; + return super.getLocale(); } - /** - * Sets the name of the current Action in the ActionContext. - * - * @param actionName the name of the current action. - */ + @Override public ActionContext withActionName(String actionName) { - put(ACTION_NAME, actionName); + super.withActionName(actionName); return this; } - /** - * Gets the name of the current Action. - * - * @return the name of the current action. - */ + @Override public String getActionName() { - return (String) get(ACTION_NAME); + return super.getActionName(); } - /** - * Sets the action parameters. - * - * @param parameters the parameters for the current action. - */ + @Override public ActionContext withParameters(HttpParameters parameters) { - put(PARAMETERS, parameters); + super.withParameters(parameters); return this; } - /** - * Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of - * parameters otherwise. - * - * @return a Map of HttpServletRequest parameters or a multipart map when in a servlet environment, or a - * generic Map of parameters otherwise. - */ + @Override public HttpParameters getParameters() { - return (HttpParameters) get(PARAMETERS); + return super.getParameters(); } - /** - * Sets a map of action session values. - * - * @param session the session values. - */ + @Override public ActionContext withSession(Map session) { - put(SESSION, session); + super.withSession(session); return this; } - /** - * Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise. - * - * @return the Map of HttpSession values when in a servlet environment or a generic session map otherwise. - */ - @SuppressWarnings("unchecked") + @Override public Map getSession() { - return (Map) get(SESSION); + return super.getSession(); } - /** - * Sets the OGNL value stack. - * - * @param valueStack the OGNL value stack. - */ + @Override public ActionContext withValueStack(ValueStack valueStack) { - put(VALUE_STACK, valueStack); + super.withValueStack(valueStack); return this; } - /** - * Gets the OGNL value stack. - * - * @return the OGNL value stack. - */ + @Override public ValueStack getValueStack() { - return (ValueStack) get(VALUE_STACK); + return super.getValueStack(); } - /** - * Gets the container for this request - * - * @param container The container - */ + @Override public ActionContext withContainer(Container container) { - put(CONTAINER, container); + super.withContainer(container); return this; } - /** - * Sets the container for this request - * - * @return The container - */ + @Override public Container getContainer() { - return (Container) get(CONTAINER); + return super.getContainer(); } + @Override public T getInstance(Class type) { - Container cont = getContainer(); - if (cont != null) { - return cont.getInstance(type); - } else { - throw new StrutsException("Cannot find an initialized container for this request."); - } - } - - /** - * Returns a value that is stored in the current ActionContext by doing a lookup using the value's key. - * - * @param key the key used to find the value. - * @return the value that was found using the key or null if the key was not found. - */ + return super.getInstance(type); + } + + @Override public Object get(String key) { - return context.get(key); + return super.get(key); } - /** - * Stores a value in the current ActionContext. The value can be looked up using the key. - * - * @param key the key of the value. - * @param value the value to be stored. - */ + @Override public void put(String key, Object value) { - context.put(key, value); + super.put(key, value); } - /** - * Gets ServletContext associated with current action - * - * @return current ServletContext - */ + @Override public ServletContext getServletContext() { - return (ServletContext) get(StrutsStatics.SERVLET_CONTEXT); + return super.getServletContext(); } - /** - * Assigns ServletContext to action context - * - * @param servletContext associated with current request - * @return ActionContext - */ + @Override public ActionContext withServletContext(ServletContext servletContext) { - put(StrutsStatics.SERVLET_CONTEXT, servletContext); + super.withServletContext(servletContext); return this; } - /** - * Gets ServletRequest associated with current action - * - * @return current ServletRequest - */ + @Override public HttpServletRequest getServletRequest() { - return (HttpServletRequest) get(StrutsStatics.HTTP_REQUEST); + return super.getServletRequest(); } - /** - * Assigns ServletRequest to action context - * - * @param request associated with current request - * @return ActionContext - */ + @Override public ActionContext withServletRequest(HttpServletRequest request) { - put(StrutsStatics.HTTP_REQUEST, request); + super.withServletRequest(request); return this; } - /** - * Gets ServletResponse associated with current action - * - * @return current ServletResponse - */ + @Override public HttpServletResponse getServletResponse() { - return (HttpServletResponse) get(StrutsStatics.HTTP_RESPONSE); + return super.getServletResponse(); } - /** - * Assigns ServletResponse to action context - * - * @param response associated with current request - * @return ActionContext - */ + @Override public ActionContext withServletResponse(HttpServletResponse response) { - put(StrutsStatics.HTTP_RESPONSE, response); + super.withServletResponse(response); return this; } - /** - * Gets PageContext associated with current action - * - * @return current PageContext - */ + @Override public PageContext getPageContext() { - return (PageContext) get(StrutsStatics.PAGE_CONTEXT); + return super.getPageContext(); } - /** - * Assigns PageContext to action context - * - * @param pageContext associated with current request - * @return ActionContext - */ + @Override public ActionContext withPageContext(PageContext pageContext) { - put(StrutsStatics.PAGE_CONTEXT, pageContext); + super.withPageContext(pageContext); return this; } - /** - * Gets ActionMapping associated with current action - * - * @return current ActionMapping - */ + @Override public ActionMapping getActionMapping() { - return (ActionMapping) get(StrutsStatics.ACTION_MAPPING); + return super.getActionMapping(); } - /** - * Assigns ActionMapping to action context - * - * @param actionMapping associated with current request - * @return ActionContext - */ + @Override public ActionContext withActionMapping(ActionMapping actionMapping) { - put(StrutsStatics.ACTION_MAPPING, actionMapping); + super.withActionMapping(actionMapping); return this; } - /** - * Assigns an extra context map to action context - * - * @param extraContext to add to the current action context - * @return ActionContext - */ + @Override public ActionContext withExtraContext(Map extraContext) { - if (extraContext != null) { - context.putAll(extraContext); - } + super.withExtraContext(extraContext); return this; } - /** - * Adds arbitrary key to action context - * - * @param key a string - * @param value an object - * @return ActionContext - */ + @Override public ActionContext with(String key, Object value) { - put(key, value); + super.with(key, value); return this; } } 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 ThreadLocal actionContext = new ThreadLocal<>(); + + /** + * Constant for the name of the action being executed. + */ + private static final String ACTION_NAME = "org.apache.struts2.ActionContext.name"; + + /** + * Constant for the {@link ValueStack OGNL value stack}. + */ + private static final String VALUE_STACK = ValueStack.VALUE_STACK; + + /** + * Constant for the action's session. + */ + private static final String SESSION = "org.apache.struts2.ActionContext.session"; + + /** + * Constant for the action's application context. + */ + private static final String APPLICATION = "org.apache.struts2.ActionContext.application"; + + /** + * Constant for the action's parameters. + */ + private static final String PARAMETERS = "org.apache.struts2.ActionContext.parameters"; + + /** + * Constant for the action's locale. + */ + private static final String LOCALE = "org.apache.struts2.ActionContext.locale"; + + /** + * Constant for the action's {@link ActionInvocation invocation} context. + */ + private static final String ACTION_INVOCATION = "org.apache.struts2.ActionContext.actionInvocation"; + + /** + * Constant for the map of type conversion errors. + */ + private static final String CONVERSION_ERRORS = "org.apache.struts2.ActionContext.conversionErrors"; + + /** + * Constant for the container + */ + private static final String CONTAINER = "org.apache.struts2.ActionContext.container"; + + private final Map context; + + /** + * Creates a new ActionContext initialized with another context. + * + * @param context a context map. + */ + protected ActionContext(Map context) { + this.context = context; + } + + /** + * Creates a new ActionContext based on passed in Map + * + * @param context a map with context values + * @return new ActionContext + */ + public static ActionContext of(Map context) { + if (context == null) { + throw new IllegalArgumentException("Context cannot be null!"); + } + return new ActionContext(context); + } + + /** + * Creates a new ActionContext based on empty Map + * + * @return new ActionContext + */ + public static ActionContext of() { + return of(new HashMap<>()); + } + + /** + * Binds the provided context with the current thread + * + * @param actionContext context to bind to the thread + * @return context which was bound to the thread + */ + public static ActionContext bind(ActionContext actionContext) { + ActionContext.setContext(actionContext); + return ActionContext.getContext(); + } + + public static boolean containsValueStack(Map context) { + return context != null && context.containsKey(VALUE_STACK); + } + + /** + * Binds this context with the current thread + * + * @return this context which was bound to the thread + */ + public ActionContext bind() { + ActionContext.setContext(this); + return ActionContext.getContext(); + } + + /** + * Wipes out current ActionContext, use wisely! + */ + public static void clear() { + actionContext.remove(); + } + + /** + * Sets the action context for the current thread. + * + * @param context the action context. + */ + private static void setContext(ActionContext context) { + actionContext.set(context); + } + + /** + * Returns the ActionContext specific to the current thread. + * + * @return the ActionContext for the current thread, is never null. + */ + public static ActionContext getContext() { + return actionContext.get(); + } + + /** + * Sets the action invocation (the execution state). + * + * @param actionInvocation the action execution state. + */ + public ActionContext withActionInvocation(ActionInvocation actionInvocation) { + put(ACTION_INVOCATION, actionInvocation); + return this; + } + + /** + * Gets the action invocation (the execution state). + * + * @return the action invocation (the execution state). + */ + public ActionInvocation getActionInvocation() { + return (ActionInvocation) get(ACTION_INVOCATION); + } + + /** + * Sets the action's application context. + * + * @param application the action's application context. + */ + public ActionContext withApplication(Map application) { + put(APPLICATION, application); + return this; + } + + /** + * Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise. + * + * @return a Map of ServletContext or generic application level Map + */ + @SuppressWarnings("unchecked") + public Map getApplication() { + return (Map) get(APPLICATION); + } + + /** + * Gets the context map. + * + * @return the context map. + */ + public Map getContextMap() { + return context; + } + + /** + * Sets conversion errors which occurred when executing the action. + * + * @param conversionErrors a Map of errors which occurred when executing the action. + */ + public ActionContext withConversionErrors(Map conversionErrors) { + put(CONVERSION_ERRORS, conversionErrors); + return this; + } + + /** + * Gets the map of conversion errors which occurred when executing the action. + * + * @return the map of conversion errors which occurred when executing the action or an empty map if + * there were no errors. + */ + @SuppressWarnings("unchecked") + public Map getConversionErrors() { + Map errors = (Map) get(CONVERSION_ERRORS); + + if (errors == null) { + errors = withConversionErrors(new HashMap<>()).getConversionErrors(); + } + + return errors; + } + + /** + * Sets the Locale for the current action. + * + * @param locale the Locale for the current action. + */ + public ActionContext withLocale(Locale locale) { + put(LOCALE, locale); + return this; + } + + /** + * Gets the Locale of the current action. If no locale was ever specified the platform's + * {@link Locale#getDefault() default locale} is used. + * + * @return the Locale of the current action. + */ + public Locale getLocale() { + Locale locale = (Locale) get(LOCALE); + + if (locale == null) { + locale = Locale.getDefault(); + withLocale(locale); + } + + return locale; + } + + /** + * Sets the name of the current Action in the ActionContext. + * + * @param actionName the name of the current action. + */ + public ActionContext withActionName(String actionName) { + put(ACTION_NAME, actionName); + return this; + } + + /** + * Gets the name of the current Action. + * + * @return the name of the current action. + */ + public String getActionName() { + return (String) get(ACTION_NAME); + } + + /** + * Sets the action parameters. + * + * @param parameters the parameters for the current action. + */ + public ActionContext withParameters(HttpParameters parameters) { + put(PARAMETERS, parameters); + return this; + } + + /** + * Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of + * parameters otherwise. + * + * @return a Map of HttpServletRequest parameters or a multipart map when in a servlet environment, or a + * generic Map of parameters otherwise. + */ + public HttpParameters getParameters() { + return (HttpParameters) get(PARAMETERS); + } + + /** + * Sets a map of action session values. + * + * @param session the session values. + */ + public ActionContext withSession(Map session) { + put(SESSION, session); + return this; + } + + /** + * Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise. + * + * @return the Map of HttpSession values when in a servlet environment or a generic session map otherwise. + */ + @SuppressWarnings("unchecked") + public Map getSession() { + return (Map) get(SESSION); + } + + /** + * Sets the OGNL value stack. + * + * @param valueStack the OGNL value stack. + */ + public ActionContext withValueStack(ValueStack valueStack) { + put(VALUE_STACK, valueStack); + return this; + } + + /** + * Gets the OGNL value stack. + * + * @return the OGNL value stack. + */ + public ValueStack getValueStack() { + return (ValueStack) get(VALUE_STACK); + } + + /** + * Gets the container for this request + * + * @param container The container + */ + public ActionContext withContainer(Container container) { + put(CONTAINER, container); + return this; + } + + /** + * Sets the container for this request + * + * @return The container + */ + public Container getContainer() { + return (Container) get(CONTAINER); + } + + public T getInstance(Class type) { + Container cont = getContainer(); + if (cont != null) { + return cont.getInstance(type); + } else { + throw new StrutsException("Cannot find an initialized container for this request."); + } + } + + /** + * Returns a value that is stored in the current ActionContext by doing a lookup using the value's key. + * + * @param key the key used to find the value. + * @return the value that was found using the key or null if the key was not found. + */ + public Object get(String key) { + return context.get(key); + } + + /** + * Stores a value in the current ActionContext. The value can be looked up using the key. + * + * @param key the key of the value. + * @param value the value to be stored. + */ + public void put(String key, Object value) { + context.put(key, value); + } + + /** + * Gets ServletContext associated with current action + * + * @return current ServletContext + */ + public ServletContext getServletContext() { + return (ServletContext) get(StrutsStatics.SERVLET_CONTEXT); + } + + /** + * Assigns ServletContext to action context + * + * @param servletContext associated with current request + * @return ActionContext + */ + public ActionContext withServletContext(ServletContext servletContext) { + put(StrutsStatics.SERVLET_CONTEXT, servletContext); + return this; + } + + /** + * Gets ServletRequest associated with current action + * + * @return current ServletRequest + */ + public HttpServletRequest getServletRequest() { + return (HttpServletRequest) get(StrutsStatics.HTTP_REQUEST); + } + + /** + * Assigns ServletRequest to action context + * + * @param request associated with current request + * @return ActionContext + */ + public ActionContext withServletRequest(HttpServletRequest request) { + put(StrutsStatics.HTTP_REQUEST, request); + return this; + } + + /** + * Gets ServletResponse associated with current action + * + * @return current ServletResponse + */ + public HttpServletResponse getServletResponse() { + return (HttpServletResponse) get(StrutsStatics.HTTP_RESPONSE); + } + + /** + * Assigns ServletResponse to action context + * + * @param response associated with current request + * @return ActionContext + */ + public ActionContext withServletResponse(HttpServletResponse response) { + put(StrutsStatics.HTTP_RESPONSE, response); + return this; + } + + /** + * Gets PageContext associated with current action + * + * @return current PageContext + */ + public PageContext getPageContext() { + return (PageContext) get(StrutsStatics.PAGE_CONTEXT); + } + + /** + * Assigns PageContext to action context + * + * @param pageContext associated with current request + * @return ActionContext + */ + public ActionContext withPageContext(PageContext pageContext) { + put(StrutsStatics.PAGE_CONTEXT, pageContext); + return this; + } + + /** + * Gets ActionMapping associated with current action + * + * @return current ActionMapping + */ + public ActionMapping getActionMapping() { + return (ActionMapping) get(StrutsStatics.ACTION_MAPPING); + } + + /** + * Assigns ActionMapping to action context + * + * @param actionMapping associated with current request + * @return ActionContext + */ + public ActionContext withActionMapping(ActionMapping actionMapping) { + put(StrutsStatics.ACTION_MAPPING, actionMapping); + return this; + } + + /** + * Assigns an extra context map to action context + * + * @param extraContext to add to the current action context + * @return ActionContext + */ + public ActionContext withExtraContext(Map extraContext) { + if (extraContext != null) { + context.putAll(extraContext); + } + return this; + } + + /** + * Adds arbitrary key to action context + * + * @param key a string + * @param value an object + * @return ActionContext + */ + public ActionContext with(String key, Object value) { + put(key, value); + return this; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ActionContext)) { + return false; + } + ActionContext other = (ActionContext) obj; + return Objects.equals(getContextMap(), other.getContextMap()); + } +} From ae9dc42da76bd3128f59945f60710ea4173d89d9 Mon Sep 17 00:00:00 2001 From: Kusal Kithul-Godage Date: Thu, 17 Oct 2024 14:19:18 +1100 Subject: [PATCH 3/3] WW-3714 Deprecate and migrate ConditionalInterceptor --- .../interceptor/ConditionalInterceptor.java | 19 ++------- .../interceptor/ConditionalInterceptor.java | 39 +++++++++++++++++++ ...onfigurationProviderOgnlAllowlistTest.java | 3 ++ 3 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 core/src/main/java/org/apache/struts2/interceptor/ConditionalInterceptor.java diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConditionalInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ConditionalInterceptor.java index 12752fce82..40d856f48a 100644 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConditionalInterceptor.java +++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ConditionalInterceptor.java @@ -18,22 +18,11 @@ */ package com.opensymphony.xwork2.interceptor; -import com.opensymphony.xwork2.ActionInvocation; - /** - * A marking interface, when implemented allows to conditionally execute a given interceptor - * within the current action invocation. + * {@inheritDoc} * - * @since Struts 6.1.1 + * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.Interceptor} instead. */ -public interface ConditionalInterceptor extends Interceptor { - - /** - * Determines if a given interceptor should be executed in the current processing of action invocation. - * - * @param invocation current {@link ActionInvocation} to determine if the interceptor should be executed - * @return true if the given interceptor should be included in the current action invocation - * @since 6.1.1 - */ - boolean shouldIntercept(ActionInvocation invocation); +@Deprecated +public interface ConditionalInterceptor extends org.apache.struts2.interceptor.ConditionalInterceptor, Interceptor { } diff --git a/core/src/main/java/org/apache/struts2/interceptor/ConditionalInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/ConditionalInterceptor.java new file mode 100644 index 0000000000..a6071327cd --- /dev/null +++ b/core/src/main/java/org/apache/struts2/interceptor/ConditionalInterceptor.java @@ -0,0 +1,39 @@ +/* + * 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.interceptor; + +import com.opensymphony.xwork2.ActionInvocation; + +/** + * A marking interface, when implemented allows to conditionally execute a given interceptor + * within the current action invocation. + * + * @since Struts 6.1.1 + */ +public interface ConditionalInterceptor extends Interceptor { + + /** + * Determines if a given interceptor should be executed in the current processing of action invocation. + * + * @param invocation current {@link ActionInvocation} to determine if the interceptor should be executed + * @return true if the given interceptor should be included in the current action invocation + * @since 6.1.1 + */ + boolean shouldIntercept(ActionInvocation invocation); +} 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 77d6bbb226..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 @@ -63,6 +63,7 @@ public void allowlist() throws Exception { Class.forName("com.opensymphony.xwork2.Result"), 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") ); @@ -90,6 +91,7 @@ public void allowlist_1only() throws Exception { Class.forName("com.opensymphony.xwork2.Result"), 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") ); @@ -116,6 +118,7 @@ public void allowlist_2only() throws Exception { Class.forName("com.opensymphony.xwork2.interceptor.AbstractInterceptor"), 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") );