From a623842bcee720e48c2f142d9854048f39b3ba4a Mon Sep 17 00:00:00 2001
From: Kusal Kithul-Godage
Date: Thu, 17 Oct 2024 16:19:33 +1100
Subject: [PATCH 1/6] WW-3714 Deprecate and migrate ActionSupport
---
.../opensymphony/xwork2/ActionSupport.java | 339 +---------------
.../org/apache/struts2/ActionSupport.java | 371 ++++++++++++++++++
...onfigurationProviderOgnlAllowlistTest.java | 3 +
3 files changed, 377 insertions(+), 336 deletions(-)
create mode 100644 core/src/main/java/org/apache/struts2/ActionSupport.java
diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java b/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
index ab1a18099..a775c9bb7 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
@@ -18,342 +18,9 @@
*/
package com.opensymphony.xwork2;
-import com.opensymphony.xwork2.conversion.impl.ConversionData;
-import com.opensymphony.xwork2.inject.Container;
-import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.interceptor.ValidationAware;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.struts2.StrutsConstants;
-
-import java.io.Serializable;
-import java.util.*;
-
/**
- * Provides a default implementation for the most common actions.
- * See the documentation for all the interfaces this class implements for more detailed information.
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.ActionSupport} instead.
*/
-public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
-
- private static final Logger LOG = LogManager.getLogger(ActionSupport.class);
-
- private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
-
- private transient TextProvider textProvider;
- private transient LocaleProvider localeProvider;
-
- protected Container container;
-
- @Override
- public void setActionErrors(Collection errorMessages) {
- validationAware.setActionErrors(errorMessages);
- }
-
- @Override
- public Collection getActionErrors() {
- return validationAware.getActionErrors();
- }
-
- @Override
- public void setActionMessages(Collection messages) {
- validationAware.setActionMessages(messages);
- }
-
- @Override
- public Collection getActionMessages() {
- return validationAware.getActionMessages();
- }
-
- @Override
- public void setFieldErrors(Map> errorMap) {
- validationAware.setFieldErrors(errorMap);
- }
-
- @Override
- public Map> getFieldErrors() {
- return validationAware.getFieldErrors();
- }
-
- @Override
- public Locale getLocale() {
- return getLocaleProvider().getLocale();
- }
-
- @Override
- public boolean isValidLocaleString(String localeStr) {
- return getLocaleProvider().isValidLocaleString(localeStr);
- }
-
- @Override
- public boolean isValidLocale(Locale locale) {
- return getLocaleProvider().isValidLocale(locale);
- }
-
- @Override
- public Locale toLocale(String localeStr) {
- return getLocaleProvider().toLocale(localeStr);
- }
-
- @Override
- public boolean hasKey(String key) {
- return getTextProvider().hasKey(key);
- }
-
- @Override
- public String getText(String aTextName) {
- return getTextProvider().getText(aTextName);
- }
-
- @Override
- public String getText(String aTextName, String defaultValue) {
- return getTextProvider().getText(aTextName, defaultValue);
- }
-
- @Override
- public String getText(String aTextName, String defaultValue, String obj) {
- return getTextProvider().getText(aTextName, defaultValue, obj);
- }
-
- @Override
- public String getText(String aTextName, List> args) {
- return getTextProvider().getText(aTextName, args);
- }
-
- @Override
- public String getText(String key, String[] args) {
- return getTextProvider().getText(key, args);
- }
-
- @Override
- public String getText(String aTextName, String defaultValue, List> args) {
- return getTextProvider().getText(aTextName, defaultValue, args);
- }
-
- @Override
- public String getText(String key, String defaultValue, String[] args) {
- return getTextProvider().getText(key, defaultValue, args);
- }
-
- @Override
- public String getText(String key, String defaultValue, List> args, ValueStack stack) {
- return getTextProvider().getText(key, defaultValue, args, stack);
- }
-
- @Override
- public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
- return getTextProvider().getText(key, defaultValue, args, stack);
- }
-
- /**
- * Dedicated method to support I10N and conversion errors
- *
- * @param key message which contains formatting string
- * @param expr that should be formatted
- * @return formatted expr with format specified by key
- */
- public String getFormatted(String key, String expr) {
- Map conversionErrors = ActionContext.getContext().getConversionErrors();
- if (conversionErrors.containsKey(expr)) {
- String[] vals = (String[]) conversionErrors.get(expr).getValue();
- return vals[0];
- } else {
- final ValueStack valueStack = ActionContext.getContext().getValueStack();
- final Object val = valueStack.findValue(expr);
- return getText(key, Arrays.asList(val));
- }
- }
-
- @Override
- public ResourceBundle getTexts() {
- return getTextProvider().getTexts();
- }
-
- @Override
- public ResourceBundle getTexts(String aBundleName) {
- return getTextProvider().getTexts(aBundleName);
- }
-
- @Override
- public void addActionError(String anErrorMessage) {
- validationAware.addActionError(anErrorMessage);
- }
-
- @Override
- public void addActionMessage(String aMessage) {
- validationAware.addActionMessage(aMessage);
- }
-
- @Override
- public void addFieldError(String fieldName, String errorMessage) {
- validationAware.addFieldError(fieldName, errorMessage);
- }
-
- public String input() throws Exception {
- return INPUT;
- }
-
- /**
- * A default implementation that does nothing an returns "success".
- *
- *
- * Subclasses should override this method to provide their business logic.
- *
- *
- *
- * See also {@link com.opensymphony.xwork2.Action#execute()}.
- *
- *
- * @return returns {@link #SUCCESS}
- * @throws Exception can be thrown by subclasses.
- */
- @Override
- public String execute() throws Exception {
- return SUCCESS;
- }
-
- @Override
- public boolean hasActionErrors() {
- return validationAware.hasActionErrors();
- }
-
- @Override
- public boolean hasActionMessages() {
- return validationAware.hasActionMessages();
- }
-
- @Override
- public boolean hasErrors() {
- return validationAware.hasErrors();
- }
-
- @Override
- public boolean hasFieldErrors() {
- return validationAware.hasFieldErrors();
- }
-
- /**
- * Clears field errors. Useful for Continuations and other situations
- * where you might want to clear parts of the state on the same action.
- */
- public void clearFieldErrors() {
- validationAware.clearFieldErrors();
- }
-
- /**
- * Clears action errors. Useful for Continuations and other situations
- * where you might want to clear parts of the state on the same action.
- */
- public void clearActionErrors() {
- validationAware.clearActionErrors();
- }
-
- /**
- * Clears messages. Useful for Continuations and other situations
- * where you might want to clear parts of the state on the same action.
- */
- public void clearMessages() {
- validationAware.clearMessages();
- }
-
- /**
- * Clears all errors. Useful for Continuations and other situations
- * where you might want to clear parts of the state on the same action.
- */
- public void clearErrors() {
- validationAware.clearErrors();
- }
-
- /**
- * Clears all errors and messages. Useful for Continuations and other situations
- * where you might want to clear parts of the state on the same action.
- */
- public void clearErrorsAndMessages() {
- validationAware.clearErrorsAndMessages();
- }
-
- /**
- * A default implementation that validates nothing.
- * Subclasses should override this method to provide validations.
- */
- @Override
- public void validate() {
- // A default implementation that validates nothing
- }
-
- @Override
- public Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
-
- /**
- *
- * Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return
- * the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc.
- *
- *
- * The next time this action is invoked (and using the same continuation ID), the method will resume immediately
- * after where this method was called, with the entire call stack in the execute method restored.
- *
- *
- *
- * Note: this method can only be called within the {@link #execute()} method.
- *
- *
- *
- *
- * @param result the result to return - the same type of return value in the {@link #execute()} method.
- */
- public void pause(String result) {
- }
-
- /**
- * If called first time it will create {@link com.opensymphony.xwork2.TextProviderFactory},
- * inject dependency (if {@link com.opensymphony.xwork2.inject.Container} is accesible) into in,
- * then will create new {@link com.opensymphony.xwork2.TextProvider} and store it in a field
- * for future references and at the returns reference to that field
- *
- * @return reference to field with TextProvider
- */
- protected TextProvider getTextProvider() {
- if (textProvider == null) {
- final TextProviderFactory tpf = getContainer().getInstance(TextProviderFactory.class);
- textProvider = tpf.createInstance(getClass());
- }
- return textProvider;
- }
-
- protected LocaleProvider getLocaleProvider() {
- if (localeProvider == null) {
- final LocaleProviderFactory localeProviderFactory = getContainer().getInstance(LocaleProviderFactory.class);
- localeProvider = localeProviderFactory.createLocaleProvider();
- }
- return localeProvider;
- }
-
- /**
- * TODO: This a temporary solution, maybe we should consider stop injecting container into beans
- */
- protected Container getContainer() {
- if (container == null) {
- container = ActionContext.getContext().getContainer();
- if (container != null) {
- boolean devMode = Boolean.parseBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_DEVMODE));
- if (devMode) {
- LOG.warn("Container is null, action was created manually? Fallback to ActionContext");
- } else {
- LOG.debug("Container is null, action was created manually? Fallback to ActionContext");
- }
- } else {
- LOG.warn("Container is null, action was created out of ActionContext scope?!?");
- }
- }
- return container;
- }
-
- @Inject
- public void setContainer(Container container) {
- this.container = container;
- }
-
+@Deprecated
+public class ActionSupport extends org.apache.struts2.ActionSupport {
}
diff --git a/core/src/main/java/org/apache/struts2/ActionSupport.java b/core/src/main/java/org/apache/struts2/ActionSupport.java
new file mode 100644
index 000000000..3f2715731
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/ActionSupport.java
@@ -0,0 +1,371 @@
+/*
+ * 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.ActionContext;
+import com.opensymphony.xwork2.LocaleProvider;
+import com.opensymphony.xwork2.LocaleProviderFactory;
+import com.opensymphony.xwork2.TextProvider;
+import com.opensymphony.xwork2.TextProviderFactory;
+import com.opensymphony.xwork2.Validateable;
+import com.opensymphony.xwork2.ValidationAwareSupport;
+import com.opensymphony.xwork2.conversion.impl.ConversionData;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.ValidationAware;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+/**
+ * Provides a default implementation for the most common actions.
+ * See the documentation for all the interfaces this class implements for more detailed information.
+ */
+public class ActionSupport implements com.opensymphony.xwork2.Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
+
+ private static final Logger LOG = LogManager.getLogger(ActionSupport.class);
+
+ private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
+
+ private transient TextProvider textProvider;
+ private transient LocaleProvider localeProvider;
+
+ protected Container container;
+
+ @Override
+ public void setActionErrors(Collection errorMessages) {
+ validationAware.setActionErrors(errorMessages);
+ }
+
+ @Override
+ public Collection getActionErrors() {
+ return validationAware.getActionErrors();
+ }
+
+ @Override
+ public void setActionMessages(Collection messages) {
+ validationAware.setActionMessages(messages);
+ }
+
+ @Override
+ public Collection getActionMessages() {
+ return validationAware.getActionMessages();
+ }
+
+ @Override
+ public void setFieldErrors(Map> errorMap) {
+ validationAware.setFieldErrors(errorMap);
+ }
+
+ @Override
+ public Map> getFieldErrors() {
+ return validationAware.getFieldErrors();
+ }
+
+ @Override
+ public Locale getLocale() {
+ return getLocaleProvider().getLocale();
+ }
+
+ @Override
+ public boolean isValidLocaleString(String localeStr) {
+ return getLocaleProvider().isValidLocaleString(localeStr);
+ }
+
+ @Override
+ public boolean isValidLocale(Locale locale) {
+ return getLocaleProvider().isValidLocale(locale);
+ }
+
+ @Override
+ public Locale toLocale(String localeStr) {
+ return getLocaleProvider().toLocale(localeStr);
+ }
+
+ @Override
+ public boolean hasKey(String key) {
+ return getTextProvider().hasKey(key);
+ }
+
+ @Override
+ public String getText(String aTextName) {
+ return getTextProvider().getText(aTextName);
+ }
+
+ @Override
+ public String getText(String aTextName, String defaultValue) {
+ return getTextProvider().getText(aTextName, defaultValue);
+ }
+
+ @Override
+ public String getText(String aTextName, String defaultValue, String obj) {
+ return getTextProvider().getText(aTextName, defaultValue, obj);
+ }
+
+ @Override
+ public String getText(String aTextName, List> args) {
+ return getTextProvider().getText(aTextName, args);
+ }
+
+ @Override
+ public String getText(String key, String[] args) {
+ return getTextProvider().getText(key, args);
+ }
+
+ @Override
+ public String getText(String aTextName, String defaultValue, List> args) {
+ return getTextProvider().getText(aTextName, defaultValue, args);
+ }
+
+ @Override
+ public String getText(String key, String defaultValue, String[] args) {
+ return getTextProvider().getText(key, defaultValue, args);
+ }
+
+ @Override
+ public String getText(String key, String defaultValue, List> args, ValueStack stack) {
+ return getTextProvider().getText(key, defaultValue, args, stack);
+ }
+
+ @Override
+ public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
+ return getTextProvider().getText(key, defaultValue, args, stack);
+ }
+
+ /**
+ * Dedicated method to support I10N and conversion errors
+ *
+ * @param key message which contains formatting string
+ * @param expr that should be formatted
+ * @return formatted expr with format specified by key
+ */
+ public String getFormatted(String key, String expr) {
+ Map conversionErrors = com.opensymphony.xwork2.ActionContext.getContext().getConversionErrors();
+ if (conversionErrors.containsKey(expr)) {
+ String[] vals = (String[]) conversionErrors.get(expr).getValue();
+ return vals[0];
+ } else {
+ final ValueStack valueStack = com.opensymphony.xwork2.ActionContext.getContext().getValueStack();
+ final Object val = valueStack.findValue(expr);
+ return getText(key, Arrays.asList(val));
+ }
+ }
+
+ @Override
+ public ResourceBundle getTexts() {
+ return getTextProvider().getTexts();
+ }
+
+ @Override
+ public ResourceBundle getTexts(String aBundleName) {
+ return getTextProvider().getTexts(aBundleName);
+ }
+
+ @Override
+ public void addActionError(String anErrorMessage) {
+ validationAware.addActionError(anErrorMessage);
+ }
+
+ @Override
+ public void addActionMessage(String aMessage) {
+ validationAware.addActionMessage(aMessage);
+ }
+
+ @Override
+ public void addFieldError(String fieldName, String errorMessage) {
+ validationAware.addFieldError(fieldName, errorMessage);
+ }
+
+ public String input() throws Exception {
+ return INPUT;
+ }
+
+ /**
+ * A default implementation that does nothing an returns "success".
+ *
+ *
+ * Subclasses should override this method to provide their business logic.
+ *
+ *
+ *
+ * See also {@link Action#execute()}.
+ *
+ *
+ * @return returns {@link #SUCCESS}
+ * @throws Exception can be thrown by subclasses.
+ */
+ @Override
+ public String execute() throws Exception {
+ return SUCCESS;
+ }
+
+ @Override
+ public boolean hasActionErrors() {
+ return validationAware.hasActionErrors();
+ }
+
+ @Override
+ public boolean hasActionMessages() {
+ return validationAware.hasActionMessages();
+ }
+
+ @Override
+ public boolean hasErrors() {
+ return validationAware.hasErrors();
+ }
+
+ @Override
+ public boolean hasFieldErrors() {
+ return validationAware.hasFieldErrors();
+ }
+
+ /**
+ * Clears field errors. Useful for Continuations and other situations
+ * where you might want to clear parts of the state on the same action.
+ */
+ public void clearFieldErrors() {
+ validationAware.clearFieldErrors();
+ }
+
+ /**
+ * Clears action errors. Useful for Continuations and other situations
+ * where you might want to clear parts of the state on the same action.
+ */
+ public void clearActionErrors() {
+ validationAware.clearActionErrors();
+ }
+
+ /**
+ * Clears messages. Useful for Continuations and other situations
+ * where you might want to clear parts of the state on the same action.
+ */
+ public void clearMessages() {
+ validationAware.clearMessages();
+ }
+
+ /**
+ * Clears all errors. Useful for Continuations and other situations
+ * where you might want to clear parts of the state on the same action.
+ */
+ public void clearErrors() {
+ validationAware.clearErrors();
+ }
+
+ /**
+ * Clears all errors and messages. Useful for Continuations and other situations
+ * where you might want to clear parts of the state on the same action.
+ */
+ public void clearErrorsAndMessages() {
+ validationAware.clearErrorsAndMessages();
+ }
+
+ /**
+ * A default implementation that validates nothing.
+ * Subclasses should override this method to provide validations.
+ */
+ @Override
+ public void validate() {
+ // A default implementation that validates nothing
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ /**
+ *
+ * Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return
+ * the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc.
+ *
+ *
+ * The next time this action is invoked (and using the same continuation ID), the method will resume immediately
+ * after where this method was called, with the entire call stack in the execute method restored.
+ *
+ *
+ *
+ * Note: this method can only be called within the {@link #execute()} method.
+ *
+ *
+ *
+ *
+ * @param result the result to return - the same type of return value in the {@link #execute()} method.
+ */
+ public void pause(String result) {
+ }
+
+ /**
+ * If called first time it will create {@link TextProviderFactory},
+ * inject dependency (if {@link Container} is accesible) into in,
+ * then will create new {@link TextProvider} and store it in a field
+ * for future references and at the returns reference to that field
+ *
+ * @return reference to field with TextProvider
+ */
+ protected TextProvider getTextProvider() {
+ if (textProvider == null) {
+ final TextProviderFactory tpf = getContainer().getInstance(TextProviderFactory.class);
+ textProvider = tpf.createInstance(getClass());
+ }
+ return textProvider;
+ }
+
+ protected LocaleProvider getLocaleProvider() {
+ if (localeProvider == null) {
+ final LocaleProviderFactory localeProviderFactory = getContainer().getInstance(LocaleProviderFactory.class);
+ localeProvider = localeProviderFactory.createLocaleProvider();
+ }
+ return localeProvider;
+ }
+
+ /**
+ * TODO: This a temporary solution, maybe we should consider stop injecting container into beans
+ */
+ protected Container getContainer() {
+ if (container == null) {
+ container = ActionContext.getContext().getContainer();
+ if (container != null) {
+ boolean devMode = Boolean.parseBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_DEVMODE));
+ if (devMode) {
+ LOG.warn("Container is null, action was created manually? Fallback to ActionContext");
+ } else {
+ LOG.debug("Container is null, action was created manually? Fallback to ActionContext");
+ }
+ } else {
+ LOG.warn("Container is null, action was created out of ActionContext scope?!?");
+ }
+ }
+ return container;
+ }
+
+ @Inject
+ public void setContainer(Container container) {
+ this.container = container;
+ }
+
+}
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 2379216bc..b3f65973d 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
@@ -50,6 +50,7 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
Class.forName("java.io.Serializable"),
Class.forName("com.opensymphony.xwork2.mock.MockResult"),
Class.forName("com.opensymphony.xwork2.interceptor.ConditionalInterceptor"),
+ Class.forName("org.apache.struts2.ActionSupport"),
Class.forName("com.opensymphony.xwork2.ActionSupport"),
Class.forName("com.opensymphony.xwork2.ActionChainResult"),
Class.forName("com.opensymphony.xwork2.TextProvider"),
@@ -82,6 +83,7 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
Class.forName("java.io.Serializable"),
Class.forName("com.opensymphony.xwork2.mock.MockResult"),
Class.forName("com.opensymphony.xwork2.interceptor.ConditionalInterceptor"),
+ Class.forName("org.apache.struts2.ActionSupport"),
Class.forName("com.opensymphony.xwork2.ActionSupport"),
Class.forName("com.opensymphony.xwork2.TextProvider"),
Class.forName("com.opensymphony.xwork2.interceptor.Interceptor"),
@@ -111,6 +113,7 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
Class.forName("com.opensymphony.xwork2.LocaleProvider"),
Class.forName("java.io.Serializable"),
Class.forName("com.opensymphony.xwork2.interceptor.ConditionalInterceptor"),
+ Class.forName("org.apache.struts2.ActionSupport"),
Class.forName("com.opensymphony.xwork2.ActionSupport"),
Class.forName("com.opensymphony.xwork2.ActionChainResult"),
Class.forName("com.opensymphony.xwork2.TextProvider"),
From 9e23fbe665540a050b64975c690196dd291339ac Mon Sep 17 00:00:00 2001
From: Kusal Kithul-Godage
Date: Thu, 17 Oct 2024 16:26:01 +1100
Subject: [PATCH 2/6] WW-3714 Deprecate and migrate AbstractInterceptor and
MethodFilterInterceptor
---
.../interceptor/AbstractInterceptor.java | 32 +---
.../interceptor/MethodFilterInterceptor.java | 45 +++---
.../MethodFilterInterceptorUtil.java | 128 +--------------
.../interceptor/AbstractInterceptor.java | 61 ++++++++
.../interceptor/MethodFilterInterceptor.java | 123 +++++++++++++++
.../MethodFilterInterceptorUtil.java | 148 ++++++++++++++++++
...onfigurationProviderOgnlAllowlistTest.java | 3 +
7 files changed, 369 insertions(+), 171 deletions(-)
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/AbstractInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptorUtil.java
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java
index 21e459c29..69c667462 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java
@@ -21,41 +21,23 @@ package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
/**
- * Provides default implementations of optional lifecycle methods
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.AbstractInterceptor} instead.
*/
-public abstract class AbstractInterceptor implements ConditionalInterceptor {
-
- private boolean disabled;
-
- /**
- * Does nothing
- */
- public void init() {
- }
-
- /**
- * Does nothing
- */
- public void destroy() {
- }
+@Deprecated
+public abstract class AbstractInterceptor extends org.apache.struts2.interceptor.AbstractInterceptor implements ConditionalInterceptor {
/**
* Override to handle interception
*/
public abstract String intercept(ActionInvocation invocation) throws Exception;
- /**
- * Allows to skip executing a given interceptor, just define {@code true}
- * or use other way to override interceptor's parameters, see
- * docs.
- * @param disable if set to true, execution of a given interceptor will be skipped.
- */
- public void setDisabled(String disable) {
- this.disabled = Boolean.parseBoolean(disable);
+ @Override
+ public String intercept(org.apache.struts2.ActionInvocation invocation) throws Exception {
+ return intercept(ActionInvocation.adapt(invocation));
}
@Override
public boolean shouldIntercept(ActionInvocation invocation) {
- return !this.disabled;
+ return shouldIntercept((org.apache.struts2.ActionInvocation) invocation);
}
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptor.java
index e96951cfa..bcce3da12 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptor.java
@@ -31,56 +31,59 @@ import java.util.Set;
*
*
* MethodFilterInterceptor is an abstract Interceptor used as
- * a base class for interceptors that will filter execution based on method
+ * a base class for interceptors that will filter execution based on method
* names according to specified included/excluded method lists.
- *
+ *
*
- *
+ *
* Settable parameters are as follows:
- *
+ *
*
*
excludeMethods - method names to be excluded from interceptor processing
*
includeMethods - method names to be included in interceptor processing
*
- *
+ *
*
- *
- * NOTE: If method name are available in both includeMethods and
- * excludeMethods, it will be considered as an included method:
+ *
+ * NOTE: If method name are available in both includeMethods and
+ * excludeMethods, it will be considered as an included method:
* includeMethods takes precedence over excludeMethods.
- *
+ *
*
- *
+ *
* Interceptors that extends this capability include:
- *
+ *
*
*
TokenInterceptor
*
TokenSessionStoreInterceptor
*
DefaultWorkflowInterceptor
*
ValidationInterceptor
*
- *
+ *
*
- *
+ *
* @author Alexandru Popescu
* @author Rainer Hermanns
- *
+ *
* @see org.apache.struts2.interceptor.TokenInterceptor
* @see org.apache.struts2.interceptor.TokenSessionStoreInterceptor
* @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
* @see com.opensymphony.xwork2.validator.ValidationInterceptor
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.MethodFilterInterceptor} instead.
*/
+@Deprecated
public abstract class MethodFilterInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(MethodFilterInterceptor.class);
-
+
protected Set excludeMethods = Collections.emptySet();
protected Set includeMethods = Collections.emptySet();
public void setExcludeMethods(String excludeMethods) {
this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
}
-
+
public Set getExcludeMethodsSet() {
return excludeMethods;
}
@@ -88,7 +91,7 @@ public abstract class MethodFilterInterceptor extends AbstractInterceptor {
public void setIncludeMethods(String includeMethods) {
this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
}
-
+
public Set getIncludeMethodsSet() {
return includeMethods;
}
@@ -97,7 +100,7 @@ public abstract class MethodFilterInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
if (applyInterceptor(invocation)) {
return doIntercept(invocation);
- }
+ }
return invocation.invoke();
}
@@ -110,14 +113,14 @@ public abstract class MethodFilterInterceptor extends AbstractInterceptor {
}
return applyMethod;
}
-
+
/**
* Subclasses must override to implement the interceptor logic.
- *
+ *
* @param invocation the action invocation
* @return the result of invocation
* @throws Exception in case of any errors
*/
protected abstract String doIntercept(ActionInvocation invocation) throws Exception;
-
+
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptorUtil.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptorUtil.java
index beacb8784..7e1a2c434 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptorUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptorUtil.java
@@ -18,131 +18,9 @@
*/
package com.opensymphony.xwork2.interceptor;
-import com.opensymphony.xwork2.util.TextParseUtil;
-import com.opensymphony.xwork2.util.WildcardHelper;
-
-import java.util.HashMap;
-import java.util.Set;
-
/**
- * Utility class contains common methods used by
- * {@link com.opensymphony.xwork2.interceptor.MethodFilterInterceptor}.
- *
- * @author tm_jee
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.MethodFilterInterceptorUtil} instead.
*/
-public class MethodFilterInterceptorUtil {
-
- /**
- * Static method to decide if the specified method should be
- * apply (not filtered) depending on the set of excludeMethods and
- * includeMethods.
- *
- *
- *
- * includeMethods takes precedence over excludeMethods
- *
- *
- * Note: Supports wildcard listings in includeMethods/excludeMethods
- *
- * @param excludeMethods list of methods to exclude.
- * @param includeMethods list of methods to include.
- * @param method the specified method to check
- * @return true if the method should be applied.
- */
- public static boolean applyMethod(Set excludeMethods, Set includeMethods, String method) {
-
- // quick check to see if any actual pattern matching is needed
- boolean needsPatternMatch = false;
- for (String includeMethod : includeMethods) {
- if (!"*".equals(includeMethod) && includeMethod.contains("*")) {
- needsPatternMatch = true;
- break;
- }
- }
-
- for (String excludeMethod : excludeMethods) {
- if (!"*".equals(excludeMethod) && excludeMethod.contains("*")) {
- needsPatternMatch = true;
- break;
- }
- }
-
- // this section will try to honor the original logic, while
- // still allowing for wildcards later
- if (!needsPatternMatch && (includeMethods.contains("*") || includeMethods.size() == 0) ) {
- if (excludeMethods != null
- && excludeMethods.contains(method)
- && !includeMethods.contains(method) ) {
- return false;
- }
- }
-
- // test the methods using pattern matching
- WildcardHelper wildcard = new WildcardHelper();
- String methodCopy ;
- if (method == null ) { // no method specified
- methodCopy = "";
- }
- else {
- methodCopy = new String(method);
- }
- for (String pattern : includeMethods) {
- if (pattern.contains("*")) {
- int[] compiledPattern = wildcard.compilePattern(pattern);
- HashMap matchedPatterns = new HashMap<>();
- boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern);
- if (matches) {
- return true; // run it, includeMethods takes precedence
- }
- }
- else {
- if (pattern.equals(methodCopy)) {
- return true; // run it, includeMethods takes precedence
- }
- }
- }
- if (excludeMethods.contains("*") ) {
- return false;
- }
-
- // CHECK ME: Previous implementation used include method
- for ( String pattern : excludeMethods) {
- if (pattern.contains("*")) {
- int[] compiledPattern = wildcard.compilePattern(pattern);
- HashMap matchedPatterns = new HashMap<>();
- boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern);
- if (matches) {
- // if found, and wasn't included earlier, don't run it
- return false;
- }
- }
- else {
- if (pattern.equals(methodCopy)) {
- // if found, and wasn't included earlier, don't run it
- return false;
- }
- }
- }
-
-
- // default fall-back from before changes
- return includeMethods.size() == 0 || includeMethods.contains(method) || includeMethods.contains("*");
- }
-
- /**
- * Same as {@link #applyMethod(Set, Set, String)}, except that excludeMethods
- * and includeMethods are supplied as comma separated string.
- *
- * @param excludeMethods comma seperated string of methods to exclude.
- * @param includeMethods comma seperated string of methods to include.
- * @param method the specified method to check
- * @return true if the method should be applied.
- */
- public static boolean applyMethod(String excludeMethods, String includeMethods, String method) {
- Set includeMethodsSet = TextParseUtil.commaDelimitedStringToSet(includeMethods == null? "" : includeMethods);
- Set excludeMethodsSet = TextParseUtil.commaDelimitedStringToSet(excludeMethods == null? "" : excludeMethods);
-
- return applyMethod(excludeMethodsSet, includeMethodsSet, method);
- }
-
+@Deprecated
+public class MethodFilterInterceptorUtil extends org.apache.struts2.interceptor.MethodFilterInterceptorUtil {
}
diff --git a/core/src/main/java/org/apache/struts2/interceptor/AbstractInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/AbstractInterceptor.java
new file mode 100644
index 000000000..ddb48a0d7
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/interceptor/AbstractInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.apache.struts2.ActionInvocation;
+
+/**
+ * Provides default implementations of optional lifecycle methods
+ */
+public abstract class AbstractInterceptor implements ConditionalInterceptor {
+
+ private boolean disabled;
+
+ /**
+ * Does nothing
+ */
+ public void init() {
+ }
+
+ /**
+ * Does nothing
+ */
+ public void destroy() {
+ }
+
+ /**
+ * Override to handle interception
+ */
+ public abstract String intercept(ActionInvocation invocation) throws Exception;
+
+ /**
+ * Allows to skip executing a given interceptor, just define {@code true}
+ * or use other way to override interceptor's parameters, see
+ * docs.
+ * @param disable if set to true, execution of a given interceptor will be skipped.
+ */
+ public void setDisabled(String disable) {
+ this.disabled = Boolean.parseBoolean(disable);
+ }
+
+ @Override
+ public boolean shouldIntercept(ActionInvocation invocation) {
+ return !this.disabled;
+ }
+}
diff --git a/core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptor.java
new file mode 100644
index 000000000..1ffe68261
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptor.java
@@ -0,0 +1,123 @@
+/*
+ * 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.util.TextParseUtil;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ActionInvocation;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ *
+ *
+ *
+ * MethodFilterInterceptor is an abstract Interceptor used as
+ * a base class for interceptors that will filter execution based on method
+ * names according to specified included/excluded method lists.
+ *
+ *
+ *
+ * Settable parameters are as follows:
+ *
+ *
+ *
excludeMethods - method names to be excluded from interceptor processing
+ *
includeMethods - method names to be included in interceptor processing
+ *
+ *
+ *
+ *
+ * NOTE: If method name are available in both includeMethods and
+ * excludeMethods, it will be considered as an included method:
+ * includeMethods takes precedence over excludeMethods.
+ *
+ *
+ *
+ * Interceptors that extends this capability include:
+ *
+ *
+ *
TokenInterceptor
+ *
TokenSessionStoreInterceptor
+ *
DefaultWorkflowInterceptor
+ *
ValidationInterceptor
+ *
+ *
+ *
+ *
+ * @author Alexandru Popescu
+ * @author Rainer Hermanns
+ *
+ * @see TokenInterceptor
+ * @see TokenSessionStoreInterceptor
+ * @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
+ * @see com.opensymphony.xwork2.validator.ValidationInterceptor
+ */
+public abstract class MethodFilterInterceptor extends AbstractInterceptor {
+
+ private static final Logger LOG = LogManager.getLogger(MethodFilterInterceptor.class);
+
+ protected Set excludeMethods = Collections.emptySet();
+ protected Set includeMethods = Collections.emptySet();
+
+ public void setExcludeMethods(String excludeMethods) {
+ this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
+ }
+
+ public Set getExcludeMethodsSet() {
+ return excludeMethods;
+ }
+
+ public void setIncludeMethods(String includeMethods) {
+ this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
+ }
+
+ public Set getIncludeMethodsSet() {
+ return includeMethods;
+ }
+
+ @Override
+ public String intercept(ActionInvocation invocation) throws Exception {
+ if (applyInterceptor(invocation)) {
+ return doIntercept(invocation);
+ }
+ return invocation.invoke();
+ }
+
+ protected boolean applyInterceptor(ActionInvocation invocation) {
+ String method = invocation.getProxy().getMethod();
+ // ValidationInterceptor
+ boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method);
+ if (!applyMethod) {
+ LOG.debug("Skipping Interceptor... Method [{}] found in exclude list.", method);
+ }
+ return applyMethod;
+ }
+
+ /**
+ * Subclasses must override to implement the interceptor logic.
+ *
+ * @param invocation the action invocation
+ * @return the result of invocation
+ * @throws Exception in case of any errors
+ */
+ protected abstract String doIntercept(ActionInvocation invocation) throws Exception;
+
+}
diff --git a/core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptorUtil.java b/core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptorUtil.java
new file mode 100644
index 000000000..2a43ba2ff
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/interceptor/MethodFilterInterceptorUtil.java
@@ -0,0 +1,148 @@
+/*
+ * 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.util.TextParseUtil;
+import com.opensymphony.xwork2.util.WildcardHelper;
+
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * Utility class contains common methods used by
+ * {@link MethodFilterInterceptor}.
+ *
+ * @author tm_jee
+ */
+public class MethodFilterInterceptorUtil {
+
+ /**
+ * Static method to decide if the specified method should be
+ * apply (not filtered) depending on the set of excludeMethods and
+ * includeMethods.
+ *
+ *
+ *
+ * includeMethods takes precedence over excludeMethods
+ *
+ *
+ * Note: Supports wildcard listings in includeMethods/excludeMethods
+ *
+ * @param excludeMethods list of methods to exclude.
+ * @param includeMethods list of methods to include.
+ * @param method the specified method to check
+ * @return true if the method should be applied.
+ */
+ public static boolean applyMethod(Set excludeMethods, Set includeMethods, String method) {
+
+ // quick check to see if any actual pattern matching is needed
+ boolean needsPatternMatch = false;
+ for (String includeMethod : includeMethods) {
+ if (!"*".equals(includeMethod) && includeMethod.contains("*")) {
+ needsPatternMatch = true;
+ break;
+ }
+ }
+
+ for (String excludeMethod : excludeMethods) {
+ if (!"*".equals(excludeMethod) && excludeMethod.contains("*")) {
+ needsPatternMatch = true;
+ break;
+ }
+ }
+
+ // this section will try to honor the original logic, while
+ // still allowing for wildcards later
+ if (!needsPatternMatch && (includeMethods.contains("*") || includeMethods.size() == 0) ) {
+ if (excludeMethods != null
+ && excludeMethods.contains(method)
+ && !includeMethods.contains(method) ) {
+ return false;
+ }
+ }
+
+ // test the methods using pattern matching
+ WildcardHelper wildcard = new WildcardHelper();
+ String methodCopy ;
+ if (method == null ) { // no method specified
+ methodCopy = "";
+ }
+ else {
+ methodCopy = new String(method);
+ }
+ for (String pattern : includeMethods) {
+ if (pattern.contains("*")) {
+ int[] compiledPattern = wildcard.compilePattern(pattern);
+ HashMap matchedPatterns = new HashMap<>();
+ boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern);
+ if (matches) {
+ return true; // run it, includeMethods takes precedence
+ }
+ }
+ else {
+ if (pattern.equals(methodCopy)) {
+ return true; // run it, includeMethods takes precedence
+ }
+ }
+ }
+ if (excludeMethods.contains("*") ) {
+ return false;
+ }
+
+ // CHECK ME: Previous implementation used include method
+ for ( String pattern : excludeMethods) {
+ if (pattern.contains("*")) {
+ int[] compiledPattern = wildcard.compilePattern(pattern);
+ HashMap matchedPatterns = new HashMap<>();
+ boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern);
+ if (matches) {
+ // if found, and wasn't included earlier, don't run it
+ return false;
+ }
+ }
+ else {
+ if (pattern.equals(methodCopy)) {
+ // if found, and wasn't included earlier, don't run it
+ return false;
+ }
+ }
+ }
+
+
+ // default fall-back from before changes
+ return includeMethods.size() == 0 || includeMethods.contains(method) || includeMethods.contains("*");
+ }
+
+ /**
+ * Same as {@link #applyMethod(Set, Set, String)}, except that excludeMethods
+ * and includeMethods are supplied as comma separated string.
+ *
+ * @param excludeMethods comma seperated string of methods to exclude.
+ * @param includeMethods comma seperated string of methods to include.
+ * @param method the specified method to check
+ * @return true if the method should be applied.
+ */
+ public static boolean applyMethod(String excludeMethods, String includeMethods, String method) {
+ Set includeMethodsSet = TextParseUtil.commaDelimitedStringToSet(includeMethods == null? "" : includeMethods);
+ Set excludeMethodsSet = TextParseUtil.commaDelimitedStringToSet(excludeMethods == null? "" : excludeMethods);
+
+ return applyMethod(excludeMethodsSet, includeMethodsSet, method);
+ }
+
+}
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 b3f65973d..51d2f96f2 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,6 +61,7 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
Class.forName("com.opensymphony.xwork2.mock.MockInterceptor"),
Class.forName("com.opensymphony.xwork2.Action"),
Class.forName("com.opensymphony.xwork2.interceptor.AbstractInterceptor"),
+ Class.forName("org.apache.struts2.interceptor.AbstractInterceptor"),
Class.forName("com.opensymphony.xwork2.Result"),
Class.forName("com.opensymphony.xwork2.SimpleAction"),
Class.forName("org.apache.struts2.interceptor.Interceptor"),
@@ -92,6 +93,7 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
Class.forName("com.opensymphony.xwork2.mock.MockInterceptor"),
Class.forName("com.opensymphony.xwork2.Action"),
Class.forName("com.opensymphony.xwork2.interceptor.AbstractInterceptor"),
+ Class.forName("org.apache.struts2.interceptor.AbstractInterceptor"),
Class.forName("com.opensymphony.xwork2.Result"),
Class.forName("com.opensymphony.xwork2.SimpleAction"),
Class.forName("org.apache.struts2.interceptor.Interceptor"),
@@ -123,6 +125,7 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
Class.forName("com.opensymphony.xwork2.Validateable"),
Class.forName("com.opensymphony.xwork2.Action"),
Class.forName("com.opensymphony.xwork2.interceptor.AbstractInterceptor"),
+ Class.forName("org.apache.struts2.interceptor.AbstractInterceptor"),
Class.forName("com.opensymphony.xwork2.Result"),
Class.forName("org.apache.struts2.interceptor.Interceptor"),
Class.forName("org.apache.struts2.interceptor.ConditionalInterceptor"),
From f95f9a7cd3ff0710cd7d4e0d2054fbf562fbf7e9 Mon Sep 17 00:00:00 2001
From: Kusal Kithul-Godage
Date: Tue, 22 Oct 2024 10:57:57 +1100
Subject: [PATCH 3/6] WW-3714 Add alternative constructors in
InterceptorMapping
---
.../xwork2/config/entities/InterceptorMapping.java | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java
index 260ae325b..6625bc7a1 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java
@@ -36,8 +36,16 @@ public class InterceptorMapping implements Serializable {
private Interceptor interceptor;
private final Map params;
+ public InterceptorMapping(String name, org.apache.struts2.interceptor.Interceptor interceptor) {
+ this(name, Interceptor.adapt(interceptor));
+ }
+
+ public InterceptorMapping(String name, org.apache.struts2.interceptor.Interceptor interceptor, Map params) {
+ this(name, Interceptor.adapt(interceptor), params);
+ }
+
public InterceptorMapping(String name, Interceptor interceptor) {
- this(name, interceptor, new HashMap());
+ this(name, interceptor, new HashMap<>());
}
public InterceptorMapping(String name, Interceptor interceptor, Map params) {
From deb6c09bce253f25f8d47a5eac2552b05ba38d71 Mon Sep 17 00:00:00 2001
From: Kusal Kithul-Godage
Date: Tue, 22 Oct 2024 10:58:50 +1100
Subject: [PATCH 4/6] WW-3714 Replace deprecated APIs in new ActionSupport
---
.../java/com/opensymphony/xwork2/ActionSupport.java | 4 +++-
.../main/java/org/apache/struts2/ActionSupport.java | 11 ++++-------
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java b/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
index a775c9bb7..be9cc29ca 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java
@@ -18,9 +18,11 @@
*/
package com.opensymphony.xwork2;
+import com.opensymphony.xwork2.interceptor.ValidationAware;
+
/**
* @deprecated since 6.7.0, use {@link org.apache.struts2.ActionSupport} instead.
*/
@Deprecated
-public class ActionSupport extends org.apache.struts2.ActionSupport {
+public class ActionSupport extends org.apache.struts2.ActionSupport implements Action, Validateable, ValidationAware {
}
diff --git a/core/src/main/java/org/apache/struts2/ActionSupport.java b/core/src/main/java/org/apache/struts2/ActionSupport.java
index 3f2715731..04c513f3a 100644
--- a/core/src/main/java/org/apache/struts2/ActionSupport.java
+++ b/core/src/main/java/org/apache/struts2/ActionSupport.java
@@ -18,21 +18,18 @@
*/
package org.apache.struts2;
-import com.opensymphony.xwork2.Action;
-import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.LocaleProvider;
import com.opensymphony.xwork2.LocaleProviderFactory;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.TextProviderFactory;
-import com.opensymphony.xwork2.Validateable;
import com.opensymphony.xwork2.ValidationAwareSupport;
import com.opensymphony.xwork2.conversion.impl.ConversionData;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.apache.struts2.interceptor.ValidationAware;
import java.io.Serializable;
import java.util.Arrays;
@@ -46,7 +43,7 @@ import java.util.ResourceBundle;
* Provides a default implementation for the most common actions.
* See the documentation for all the interfaces this class implements for more detailed information.
*/
-public class ActionSupport implements com.opensymphony.xwork2.Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
+public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
private static final Logger LOG = LogManager.getLogger(ActionSupport.class);
@@ -165,12 +162,12 @@ public class ActionSupport implements com.opensymphony.xwork2.Action, Validateab
* @return formatted expr with format specified by key
*/
public String getFormatted(String key, String expr) {
- Map conversionErrors = com.opensymphony.xwork2.ActionContext.getContext().getConversionErrors();
+ Map conversionErrors = ActionContext.getContext().getConversionErrors();
if (conversionErrors.containsKey(expr)) {
String[] vals = (String[]) conversionErrors.get(expr).getValue();
return vals[0];
} else {
- final ValueStack valueStack = com.opensymphony.xwork2.ActionContext.getContext().getValueStack();
+ final ValueStack valueStack = ValueStack.adapt(ActionContext.getContext().getValueStack());
final Object val = valueStack.findValue(expr);
return getText(key, Arrays.asList(val));
}
From 45a1f5efc6e5997e7f1e3106dfd03a52f6091c7f Mon Sep 17 00:00:00 2001
From: Kusal Kithul-Godage
Date: Thu, 17 Oct 2024 17:53:30 +1100
Subject: [PATCH 5/6] WW-3714 Deprecate and migrate assorted Interceptors
---
.../xwork2/interceptor/AliasInterceptor.java | 3 +
.../interceptor/ChainingInterceptor.java | 3 +
.../ConversionErrorInterceptor.java | 7 +-
.../DefaultWorkflowInterceptor.java | 5 +-
.../ExceptionMappingInterceptor.java | 5 +-
.../interceptor/LoggingInterceptor.java | 3 +
.../interceptor/ModelDrivenInterceptor.java | 5 +-
.../ParameterRemoverInterceptor.java | 3 +
.../PrefixMethodInvocationUtil.java | 51 +--
.../interceptor/PrepareInterceptor.java | 3 +
.../ScopedModelDrivenInterceptor.java | 25 +-
.../StaticParametersInterceptor.java | 3 +
.../struts2/interceptor/AliasInterceptor.java | 293 ++++++++++++++++
.../interceptor/ChainingInterceptor.java | 275 +++++++++++++++
.../ConversionErrorInterceptor.java | 149 ++++++++
.../DefaultWorkflowInterceptor.java | 245 +++++++++++++
.../ExceptionMappingInterceptor.java | 324 ++++++++++++++++++
.../interceptor/LoggingInterceptor.java | 90 +++++
.../interceptor/ModelDrivenInterceptor.java | 148 ++++++++
.../ParameterRemoverInterceptor.java | 124 +++++++
.../interceptor/PrepareInterceptor.java | 177 ++++++++++
.../ScopedModelDrivenInterceptor.java | 165 +++++++++
.../StaticParametersInterceptor.java | 242 +++++++++++++
23 files changed, 2308 insertions(+), 40 deletions(-)
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/AliasInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/ChainingInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/ConversionErrorInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/DefaultWorkflowInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/ExceptionMappingInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/LoggingInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/ModelDrivenInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/ParameterRemoverInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/PrepareInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/ScopedModelDrivenInterceptor.java
create mode 100644 core/src/main/java/org/apache/struts2/interceptor/StaticParametersInterceptor.java
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java
index 334525d27..943aaacf4 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java
@@ -91,7 +91,10 @@ import java.util.Map;
*
*
* @author Matthew Payne
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.AliasInterceptor} instead.
*/
+@Deprecated
public class AliasInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(AliasInterceptor.class);
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
index 7284dc037..a21d18c56 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java
@@ -118,7 +118,10 @@ import java.util.Map;
* @author mrdon
* @author tm_jee ( tm_jee(at)yahoo.co.uk )
* @see com.opensymphony.xwork2.ActionChainResult
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ChainingInterceptor} instead.
*/
+@Deprecated
public class ChainingInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(ChainingInterceptor.class);
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java
index b549cc019..21e3d9f65 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java
@@ -42,13 +42,13 @@ import java.util.Map;
* display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to
* the user).
*
- *
+ *
*
* Note: Since 2.5.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.
*
- *
+ *
*
*
*
Interceptor parameters:
@@ -85,7 +85,10 @@ import java.util.Map;
*
*
* @author Jason Carreira
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ConversionErrorInterceptor} instead.
*/
+@Deprecated
public class ConversionErrorInterceptor extends MethodFilterInterceptor {
public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override";
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
index 05749ae19..d238e1ceb 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/DefaultWorkflowInterceptor.java
@@ -32,7 +32,7 @@ import org.apache.struts2.interceptor.ValidationWorkflowAware;
/**
*
*
- * An interceptor that makes sure there are not validation, conversion or action errors before allowing the interceptor chain to continue.
+ * An interceptor that makes sure there are not validation, conversion or action errors before allowing the interceptor chain to continue.
* If a single FieldError or ActionError (including the ones replicated by the Message Store Interceptor in a redirection) is found, the INPUT result will be triggered.
* This interceptor does not perform any validation.
*
@@ -132,7 +132,10 @@ import org.apache.struts2.interceptor.ValidationWorkflowAware;
* @author Alexandru Popescu
* @author Philip Luppens
* @author tm_jee
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.DefaultWorkflowInterceptor} instead.
*/
+@Deprecated
public class DefaultWorkflowInterceptor extends MethodFilterInterceptor {
private static final long serialVersionUID = 7563014655616490865L;
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java
index e60550ca6..3bb70bcb8 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java
@@ -20,8 +20,8 @@ package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
-import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.apache.struts2.dispatcher.HttpParameters;
import java.util.List;
@@ -153,7 +153,10 @@ import java.util.Map;
*
* @author Matthew E. Porter (matthew dot porter at metissian dot com)
* @author Claus Ibsen
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ExceptionMappingInterceptor} instead.
*/
+@Deprecated
public class ExceptionMappingInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(ExceptionMappingInterceptor.class);
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/LoggingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/LoggingInterceptor.java
index 6ba498b3c..3f012288c 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/LoggingInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/LoggingInterceptor.java
@@ -59,7 +59,10 @@ import org.apache.logging.log4j.Logger;
*
*
* @author Jason Carreira
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.LoggingInterceptor} instead.
*/
+@Deprecated
public class LoggingInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(LoggingInterceptor.class);
private static final String FINISH_MESSAGE = "Finishing execution stack for action ";
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptor.java
index f513deb1c..84170b669 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptor.java
@@ -71,10 +71,13 @@ import org.apache.struts2.ModelDriven;
* </action>
*
*
- *
+ *
* @author tm_jee
* @version $Date$ $Id$
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ModelDrivenInterceptor} instead.
*/
+@Deprecated
public class ModelDrivenInterceptor extends AbstractInterceptor {
protected boolean refreshModelBeforeResult = false;
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java
index c0f83765c..f33ebf6e2 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java
@@ -66,7 +66,10 @@ import java.util.Set;
* ...
* </action>
*
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ParameterRemoverInterceptor} instead.
*/
+@Deprecated
public class ParameterRemoverInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(ParameterRemoverInterceptor.class);
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java
index 040080824..0ac840c7a 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java
@@ -19,8 +19,8 @@
package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
-import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -28,7 +28,7 @@ import java.lang.reflect.Method;
/**
*
* A utility class for invoking prefixed methods in action class.
- *
+ *
* Interceptors that made use of this class are:
*
else if the action class have validateDo{MethodName}(), it will be invoked
*
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.
else if the action class have prepareDo(MethodName()}(), it will be invoked
*
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.
*
- *
+ *
*
- *
+ *
* @author Philip Luppens
* @author tm_jee
*/
public class PrefixMethodInvocationUtil {
-
+
private static final Logger LOG = LogManager.getLogger(PrefixMethodInvocationUtil.class);
private static final String DEFAULT_INVOCATION_METHODNAME = "execute";
@@ -76,7 +76,7 @@ public class PrefixMethodInvocationUtil {
*
* This method will prefix actionInvocation's ActionProxy's
* method with prefixes before invoking the prefixed method.
- * Order of the prefixes is important, as this method will return once
+ * Order of the prefixes is important, as this method will return once
* a prefixed method is found in the action class.
*
*
@@ -89,7 +89,7 @@ public class PrefixMethodInvocationUtil {
*
*
*
- * Assuming actionInvocation.getProxy(),getMethod() returns "submit",
+ * Assuming actionInvocation.getProxy(),getMethod() returns "submit",
* the order of invocation would be as follows:-
*
*
@@ -99,12 +99,12 @@ public class PrefixMethodInvocationUtil {
*
*
*
- * If prepareSubmit() exists, it will be invoked and this method
- * will return, prepareDoSubmit() will NOT be invoked.
+ * If prepareSubmit() exists, it will be invoked and this method
+ * will return, prepareDoSubmit() will NOT be invoked.
*
*
*
- * On the other hand, if prepareDoSubmit() does not exists, and
+ * On the other hand, if prepareDoSubmit() does not exists, and
* prepareDoSubmit() exists, it will be invoked.
*
*
@@ -119,29 +119,32 @@ public class PrefixMethodInvocationUtil {
*/
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
+ // 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]);
}
}
-
-
+
+ public static void invokePrefixMethod(org.apache.struts2.ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException {
+ invokePrefixMethod(ActionInvocation.adapt(actionInvocation), prefixes);
+ }
+
/**
- * This method returns a {@link Method} in action. The method
+ * This method returns a {@link Method} in action. The method
* returned is found by searching for method in action whose method name
* is equals to the result of appending each prefixes
* to methodName. Only the first method found will be returned, hence
* the order of prefixes is important. If none is found this method
* will return null.
- *
+ *
* @param prefixes the prefixes to prefix the methodName
* @param methodName the method name to be prefixed with prefixes
* @param action the action class of which the prefixed method is to be search for.
@@ -162,7 +165,7 @@ public class PrefixMethodInvocationUtil {
}
return null;
}
-
+
/**
*
* This method capitalized the first character of methodName.
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrepareInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/PrepareInterceptor.java
index e4d5af634..43bb12c2b 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrepareInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/PrepareInterceptor.java
@@ -96,7 +96,10 @@ import java.lang.reflect.InvocationTargetException;
* @author Philip Luppens
* @author tm_jee
* @see com.opensymphony.xwork2.Preparable
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.PrepareInterceptor} instead.
*/
+@Deprecated
public class PrepareInterceptor extends MethodFilterInterceptor {
private static final long serialVersionUID = -5216969014510719786L;
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptor.java
index ae2266be0..03473034d 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptor.java
@@ -36,7 +36,7 @@ import java.util.Map;
*
*
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.
- *
+ *
*
*
*
Interceptor parameters:
@@ -46,7 +46,7 @@ import java.util.Map;
*
*
*
className - The model class name. Defaults to the class name of the object returned by the getModel() method.
- *
+ *
*
name - The key to use when storing or retrieving the instance in a scope. Defaults to the model
* class name.
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ScopedModelDrivenInterceptor} instead.
*/
+@Deprecated
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;
Map scopeMap = actionContext.getContextMap();
if ("session".equals(modelScope)) {
scopeMap = actionContext.getSession();
}
-
+
model = scopeMap.get(modelName);
if (model == null) {
model = factory.buildBean(modelClassName, null);
@@ -120,7 +123,7 @@ public class ScopedModelDrivenInterceptor extends AbstractInterceptor {
if (modelDriven.getModel() == null) {
ActionContext ctx = ActionContext.getContext();
ActionConfig config = invocation.getProxy().getConfig();
-
+
String cName = className;
if (cName == null) {
try {
@@ -162,5 +165,5 @@ public class ScopedModelDrivenInterceptor extends AbstractInterceptor {
*/
public void setScope(String scope) {
this.scope = scope;
- }
+ }
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
index d560e1dd4..f5d4382ae 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java
@@ -85,7 +85,10 @@ import java.util.Map;
*
*
* @author Patrick Lightbody
+ *
+ * @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.StaticParametersInterceptor} instead.
*/
+@Deprecated
public class StaticParametersInterceptor extends AbstractInterceptor {
private boolean parse;
diff --git a/core/src/main/java/org/apache/struts2/interceptor/AliasInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/AliasInterceptor.java
new file mode 100644
index 000000000..c5aa9fb3c
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/interceptor/AliasInterceptor.java
@@ -0,0 +1,293 @@
+/*
+ * 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.LocalizedTextProvider;
+import com.opensymphony.xwork2.config.entities.ActionConfig;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.interceptor.ParametersInterceptor;
+import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
+import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
+import com.opensymphony.xwork2.util.ClearableValueStack;
+import com.opensymphony.xwork2.util.Evaluated;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ActionContext;
+import org.apache.struts2.ActionInvocation;
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.dispatcher.HttpParameters;
+import org.apache.struts2.dispatcher.Parameter;
+import org.apache.struts2.util.ValueStack;
+
+import java.util.Map;
+
+
+/**
+ *
+ *
+ * The aim of this Interceptor is to alias a named parameter to a different named parameter. By acting as the glue
+ * between actions sharing similar parameters (but with different names), it can help greatly with action chaining.
+ *
+ *
Action's alias expressions should be in the form of #{ "name1" : "alias1", "name2" : "alias2" }.
+ * This means that assuming an action (or something else in the stack) has a value for the expression named name1 and the
+ * action this interceptor is applied to has a setter named alias1, alias1 will be set with the value from
+ * name1.
+ *
+ *
+ *
+ *
+ *
Interceptor parameters:
+ *
+ *
+ *
+ *
+ *
+ *
aliasesKey (optional) - the name of the action parameter to look for the alias map (by default this is
+ * aliases).
+ *
+ *
+ *
+ *
+ *
+ *
Extending the interceptor:
+ *
+ *
+ *
+ * This interceptor does not have any known extension points.
+ *
+ *
+ *
+ *
Example code:
+ *
+ *
+ *
+ * <action name="someAction" class="com.examples.SomeAction">
+ * <!-- The value for the foo parameter will be applied as if it were named bar -->
+ * <param name="aliases">#{ 'foo' : 'bar' }</param>
+ *
+ * <interceptor-ref name="alias"/>
+ * <interceptor-ref name="basicStack"/>
+ * <result name="success">good_result.ftl</result>
+ * </action>
+ *
+ *
+ * Sets the name of the action parameter to look for the alias map.
+ *
+ *
+ *
+ * Default is aliases.
+ *
+ *
+ * @param aliasesKey the name of the action parameter
+ */
+ public void setAliasesKey(String aliasesKey) {
+ this.aliasesKey = aliasesKey;
+ }
+
+ @Override public String intercept(ActionInvocation invocation) throws Exception {
+
+ ActionConfig config = invocation.getProxy().getConfig();
+ ActionContext ac = invocation.getInvocationContext();
+ Object action = invocation.getAction();
+
+ // get the action's parameters
+ final Map parameters = config.getParams();
+
+ if (parameters.containsKey(aliasesKey)) {
+
+ String aliasExpression = parameters.get(aliasesKey);
+ ValueStack stack = ac.getValueStack();
+ Object obj = stack.findValue(aliasExpression);
+
+ if (obj instanceof Map) {
+ //get secure stack
+ ValueStack newStack = valueStackFactory.createValueStack(com.opensymphony.xwork2.util.ValueStack.adapt(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 context = newStack.getContext();
+ ReflectionContextState.setCreatingNullObjects(context, true);
+ ReflectionContextState.setDenyMethodExecution(context, true);
+ ReflectionContextState.setReportingConversionErrors(context, true);
+
+ //keep locale from original context
+ newStack.getActionContext().withLocale(stack.getActionContext().getLocale());
+ }
+
+ // override
+ Map aliases = (Map) obj;
+ for (Object o : aliases.entrySet()) {
+ Map.Entry entry = (Map.Entry) o;
+ String name = entry.getKey().toString();
+ if (isNotAcceptableExpression(name)) {
+ continue;
+ }
+ String alias = (String) entry.getValue();
+ if (isNotAcceptableExpression(alias)) {
+ continue;
+ }
+ Evaluated value = new Evaluated(stack.findValue(name));
+ if (!value.isDefined()) {
+ // workaround
+ HttpParameters contextParameters = ActionContext.getContext().getParameters();
+
+ if (null != contextParameters) {
+ Parameter param = contextParameters.get(name);
+ if (param.isDefined()) {
+ value = new Evaluated(param.getValue());
+ }
+ }
+ }
+ if (value.isDefined()) {
+ try {
+ newStack.setValue(alias, value.get());
+ } catch (RuntimeException e) {
+ if (devMode) {
+ String developerNotification = localizedTextProvider.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.getActionContext().withConversionErrors(newStack.getActionContext().getConversionErrors());
+ }
+ } else {
+ LOG.debug("invalid alias expression: {}", aliasesKey);
+ }
+ }
+
+ return invocation.invoke();
+ }
+
+ protected boolean isAccepted(String paramName) {
+ AcceptedPatternsChecker.IsAccepted result = acceptedPatterns.isAccepted(paramName);
+ if (result.isAccepted()) {
+ return true;
+ }
+
+ LOG.warn("Parameter [{}] didn't match accepted pattern [{}]! See Accepted / Excluded patterns at\n" +
+ "https://struts.apache.org/security/#accepted--excluded-patterns",
+ paramName, result.getAcceptedPattern());
+
+ return false;
+ }
+
+ protected boolean isExcluded(String paramName) {
+ ExcludedPatternsChecker.IsExcluded result = excludedPatterns.isExcluded(paramName);
+ if (!result.isExcluded()) {
+ return false;
+ }
+
+ LOG.warn("Parameter [{}] matches excluded pattern [{}]! See Accepted / Excluded patterns at\n" +
+ "https://struts.apache.org/security/#accepted--excluded-patterns",
+ paramName, result.getExcludedPattern());
+
+ return true;
+ }
+
+ /**
+ * Checks if expression contains vulnerable code
+ *
+ * @param expression of interceptor
+ * @return true|false
+ */
+ protected boolean isNotAcceptableExpression(String expression) {
+ return isExcluded(expression) || !isAccepted(expression);
+ }
+
+ /**
+ * Sets a comma-delimited list of regular expressions to match
+ * parameters that are allowed in the parameter map (aka whitelist).
+ *
+ * Don't change the default unless you know what you are doing in terms
+ * of security implications.
+ *
+ *
+ * @param commaDelim A comma-delimited list of regular expressions
+ */
+ public void setAcceptParamNames(String commaDelim) {
+ acceptedPatterns.setAcceptedPatterns(commaDelim);
+ }
+
+ /**
+ * 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) {
+ excludedPatterns.setExcludedPatterns(commaDelim);
+ }
+
+}
diff --git a/core/src/main/java/org/apache/struts2/interceptor/ChainingInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/ChainingInterceptor.java
new file mode 100644
index 000000000..fd3c25a65
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/interceptor/ChainingInterceptor.java
@@ -0,0 +1,275 @@
+/*
+ * 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.ActionChainResult;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.CompoundRoot;
+import com.opensymphony.xwork2.util.ProxyUtil;
+import com.opensymphony.xwork2.util.TextParseUtil;
+import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.ActionInvocation;
+import org.apache.struts2.Result;
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.Unchainable;
+import org.apache.struts2.util.ValueStack;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ *
+ *
+ * An interceptor that copies all the properties of every object in the value stack to the currently executing object,
+ * except for any object that implements {@link Unchainable}. A collection of optional includes and
+ * excludes may be provided to control how and which parameters are copied. Only includes or excludes may be
+ * specified. Specifying both results in undefined behavior. See the javadocs for {@link ReflectionProvider#copy(Object, Object,
+ * Map, Collection, Collection)} for more information.
+ *
+ *
+ *
+ * Note: It is important to remember that this interceptor does nothing if there are no objects already on the stack.
+ * This means two things:
+ * One, you can safely apply it to all your actions without any worry of adverse affects.
+ * Two, it is up to you to ensure an object exists in the stack prior to invoking this action. The most typical way this is done
+ * is through the use of the chain result type, which combines with this interceptor to make up the action
+ * chaining feature.
+ *
+ *
+ *
+ * Note: By default Errors, Field errors and Message aren't copied during chaining, to change the behaviour you can specify
+ * the below three constants in struts.properties or struts.xml:
+ *
+ *
+ *
+ *
struts.chaining.copyErrors - set to true to copy Action Errors
+ *
struts.chaining.copyFieldErrors - set to true to copy Field Errors
+ *
struts.chaining.copyMessages - set to true to copy Action Messages
+ *
+ *
+ *
+ * @author mrdon
+ * @author tm_jee ( tm_jee(at)yahoo.co.uk )
+ * @see ActionChainResult
+ */
+public class ChainingInterceptor extends AbstractInterceptor {
+
+ private static final Logger LOG = LogManager.getLogger(ChainingInterceptor.class);
+
+ private static final String ACTION_ERRORS = "actionErrors";
+ private static final String FIELD_ERRORS = "fieldErrors";
+ private static final String ACTION_MESSAGES = "actionMessages";
+
+ private boolean copyMessages = false;
+ private boolean copyErrors = false;
+ private boolean copyFieldErrors = false;
+
+ protected Collection excludes;
+
+ protected Collection includes;
+ protected ReflectionProvider reflectionProvider;
+
+ @Inject
+ public void setReflectionProvider(ReflectionProvider prov) {
+ this.reflectionProvider = prov;
+ }
+
+ @Inject(value = StrutsConstants.STRUTS_CHAINING_COPY_ERRORS, required = false)
+ public void setCopyErrors(String copyErrors) {
+ this.copyErrors = "true".equalsIgnoreCase(copyErrors);
+ }
+
+ @Inject(value = StrutsConstants.STRUTS_CHAINING_COPY_FIELD_ERRORS, required = false)
+ public void setCopyFieldErrors(String copyFieldErrors) {
+ this.copyFieldErrors = "true".equalsIgnoreCase(copyFieldErrors);
+ }
+
+ @Inject(value = StrutsConstants.STRUTS_CHAINING_COPY_MESSAGES, required = false)
+ public void setCopyMessages(String copyMessages) {
+ this.copyMessages = "true".equalsIgnoreCase(copyMessages);
+ }
+
+ @Override
+ public String intercept(ActionInvocation invocation) throws Exception {
+ ValueStack stack = invocation.getStack();
+ CompoundRoot root = stack.getRoot();
+ if (shouldCopyStack(invocation, root)) {
+ copyStack(invocation, root);
+ }
+ return invocation.invoke();
+ }
+
+ private void copyStack(ActionInvocation invocation, CompoundRoot root) {
+ List list = prepareList(root);
+ Map ctxMap = invocation.getInvocationContext().getContextMap();
+ for (Object object : list) {
+ if (shouldCopy(object)) {
+ Object action = invocation.getAction();
+ Class> editable = null;
+ if(ProxyUtil.isProxy(action)) {
+ editable = ProxyUtil.ultimateTargetClass(action);
+ }
+ reflectionProvider.copy(object, action, ctxMap, prepareExcludes(), includes, editable);
+ }
+ }
+ }
+
+ private Collection prepareExcludes() {
+ Collection localExcludes = excludes;
+ if (!copyErrors || !copyMessages ||!copyFieldErrors) {
+ if (localExcludes == null) {
+ localExcludes = new HashSet();
+ if (!copyErrors) {
+ localExcludes.add(ACTION_ERRORS);
+ }
+ if (!copyMessages) {
+ localExcludes.add(ACTION_MESSAGES);
+ }
+ if (!copyFieldErrors) {
+ localExcludes.add(FIELD_ERRORS);
+ }
+ }
+ }
+ return localExcludes;
+ }
+
+ private boolean shouldCopy(Object o) {
+ return o != null && !(o instanceof Unchainable);
+ }
+
+ @SuppressWarnings("unchecked")
+ private List prepareList(CompoundRoot root) {
+ List list = new ArrayList(root);
+ list.remove(0);
+ Collections.reverse(list);
+ return list;
+ }
+
+ private boolean shouldCopyStack(ActionInvocation invocation, CompoundRoot root) throws Exception {
+ Result result = invocation.getResult();
+ return root.size() > 1 && (result == null || ActionChainResult.class.isAssignableFrom(result.getClass()));
+ }
+
+ /**
+ * Gets list of parameter names to exclude
+ *
+ * @return the exclude list
+ */
+ public Collection getExcludes() {
+ return excludes;
+ }
+
+ /**
+ * Sets the list of parameter names to exclude from copying (all others will be included).
+ *
+ * @param excludes the excludes list as comma separated String
+ */
+ public void setExcludes(String excludes) {
+ this.excludes = TextParseUtil.commaDelimitedStringToSet(excludes);
+ }
+
+ /**
+ * Sets the list of parameter names to exclude from copying (all others will be included).
+ *
+ * @param excludes the excludes list
+ */
+ public void setExcludesCollection(Collection excludes) {
+ this.excludes = excludes;
+ }
+
+ /**
+ * Gets list of parameter names to include
+ *
+ * @return the include list
+ */
+ public Collection getIncludes() {
+ return includes;
+ }
+
+ /**
+ * Sets the list of parameter names to include when copying (all others will be excluded).
+ *
+ * @param includes the includes list as comma separated String
+ */
+ public void setIncludes(String includes) {
+ this.includes = TextParseUtil.commaDelimitedStringToSet(includes);
+ }
+
+
+ /**
+ * Sets the list of parameter names to include when copying (all others will be excluded).
+ *
+ * @param includes the includes list
+ */
+ public void setIncludesCollection(Collection includes) {
+ this.includes = includes;
+ }
+
+}
diff --git a/core/src/main/java/org/apache/struts2/interceptor/ConversionErrorInterceptor.java b/core/src/main/java/org/apache/struts2/interceptor/ConversionErrorInterceptor.java
new file mode 100644
index 000000000..e795543d4
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/interceptor/ConversionErrorInterceptor.java
@@ -0,0 +1,149 @@
+/*
+ * 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.conversion.impl.ConversionData;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import org.apache.commons.text.StringEscapeUtils;
+import org.apache.struts2.ActionContext;
+import org.apache.struts2.ActionInvocation;
+import org.apache.struts2.util.ValueStack;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ *
+ * ConversionErrorInterceptor adds conversion errors from the ActionContext to the Action's field errors.
+ *
+ *
+ * This interceptor adds any error found in the {@link ActionContext}'s conversionErrors map as a field error (provided
+ * that the action implements {@link ValidationAware}). In addition, any field that contains a validation error has its
+ * original value saved such that any subsequent requests for that value return the original value rather than the value
+ * in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to
+ * display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to
+ * the user).
+ *
+ *
+ *
+ * Note: Since 2.5.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.
+ *
+ *
+ *
+ *
+ *
Interceptor parameters:
+ *
+ *
+ *
+ *
+ *
None
+ *
+ *
+ *
+ *
+ *
Extending the interceptor:
+ *
+ *
+ *
+ * Because this interceptor is not web-specific, it abstracts the logic for whether an error should be added. This
+ * allows for web-specific interceptors to use more complex logic in the {@link #shouldAddError} method for when a value
+ * has a conversion error but is null or empty or otherwise indicates that the value was never actually entered by the
+ * user.
+ *
+ *
+ *
+ *