Merge branch 'kusal-depr-apis-5' into 7.0.x/merge-master-2024-11-01

# Conflicts:
#	core/src/main/java/com/opensymphony/xwork2/ActionEventListener.java
#	core/src/main/java/com/opensymphony/xwork2/ModelDriven.java
#	core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java
#	core/src/main/java/com/opensymphony/xwork2/interceptor/PrepareInterceptor.java
#	core/src/main/java/com/opensymphony/xwork2/validator/DelegatingValidatorContext.java
#	core/src/main/java/org/apache/struts2/interceptor/ActionFileUploadInterceptor.java
#	plugins/dwr/src/main/java/org/apache/struts2/validators/DWRValidator.java
#	plugins/oval/src/main/java/org/apache/struts2/oval/interceptor/OValValidationInterceptor.java
This commit is contained in:
Kusal Kithul-Godage
2024-11-01 15:32:30 +11:00
53 changed files with 1113 additions and 470 deletions
@@ -43,7 +43,10 @@ public class ActionContext extends org.apache.struts2.ActionContext {
super(actualContext.getContextMap());
}
static ActionContext adapt(org.apache.struts2.ActionContext actualContext) {
public static ActionContext adapt(org.apache.struts2.ActionContext actualContext) {
if (actualContext instanceof ActionContext) {
return (ActionContext) actualContext;
}
return actualContext != null ? new ActionContext(actualContext) : null;
}
@@ -163,15 +166,19 @@ public class ActionContext extends org.apache.struts2.ActionContext {
return super.getSession();
}
@Override
public ActionContext withValueStack(ValueStack valueStack) {
return withValueStack((org.apache.struts2.util.ValueStack) valueStack);
}
@Override
public ActionContext withValueStack(org.apache.struts2.util.ValueStack valueStack) {
super.withValueStack(valueStack);
return this;
}
@Override
public ValueStack getValueStack() {
return super.getValueStack();
return ValueStack.adapt(super.getValueStack());
}
@Override
@@ -21,24 +21,50 @@ package com.opensymphony.xwork2;
import com.opensymphony.xwork2.util.ValueStack;
/**
* Provides hooks for handling key action events
* {@inheritDoc}
*
* @deprecated since 6.7.0, use {@link org.apache.struts2.ActionEventListener} instead.
*/
public interface ActionEventListener {
/**
* Called after an action has been created.
*
* @param action The action
* @param stack The current value stack
* @return The action to use
*/
@Deprecated
public interface ActionEventListener extends org.apache.struts2.ActionEventListener {
@Override
default Object prepare(Object action, org.apache.struts2.util.ValueStack stack) {
return prepare(action, ValueStack.adapt(stack));
}
@Override
default String handleException(Throwable t, org.apache.struts2.util.ValueStack stack) {
return handleException(t, ValueStack.adapt(stack));
}
Object prepare(Object action, ValueStack stack);
/**
* Called when an exception is thrown by the action
*
* @param t The exception/error that was thrown
* @param stack The current value stack
* @return A result code to execute, can be null
*/
String handleException(Throwable t, ValueStack stack);
static ActionEventListener adapt(org.apache.struts2.ActionEventListener actualListener) {
if (actualListener instanceof ActionEventListener) {
return (ActionEventListener) actualListener;
}
return actualListener != null ? new LegacyAdapter(actualListener) : null;
}
class LegacyAdapter implements ActionEventListener {
private final org.apache.struts2.ActionEventListener adaptee;
private LegacyAdapter(org.apache.struts2.ActionEventListener adaptee) {
this.adaptee = adaptee;
}
@Override
public Object prepare(Object action, ValueStack stack) {
return adaptee.prepare(action, stack);
}
@Override
public String handleException(Throwable t, ValueStack stack) {
return adaptee.handleException(t, stack);
}
}
}
@@ -35,6 +35,12 @@ public interface ActionInvocation extends org.apache.struts2.ActionInvocation {
@Override
Result getResult() throws Exception;
@Override
ActionProxy getProxy();
@Override
ValueStack getStack();
@Override
default void addPreResultListener(org.apache.struts2.interceptor.PreResultListener listener) {
addPreResultListener(PreResultListener.adapt(listener));
@@ -42,7 +48,24 @@ public interface ActionInvocation extends org.apache.struts2.ActionInvocation {
void addPreResultListener(PreResultListener listener);
@Override
default void setActionEventListener(org.apache.struts2.ActionEventListener listener) {
setActionEventListener(ActionEventListener.adapt(listener));
}
void setActionEventListener(ActionEventListener listener);
@Override
default void init(org.apache.struts2.ActionProxy proxy) {
init(ActionProxy.adapt(proxy));
}
void init(ActionProxy proxy);
static ActionInvocation adapt(org.apache.struts2.ActionInvocation actualInvocation) {
if (actualInvocation instanceof ActionInvocation) {
return (ActionInvocation) actualInvocation;
}
return actualInvocation != null ? new LegacyAdapter(actualInvocation) : null;
}
@@ -71,7 +94,7 @@ public interface ActionInvocation extends org.apache.struts2.ActionInvocation {
@Override
public ActionProxy getProxy() {
return adaptee.getProxy();
return ActionProxy.adapt(adaptee.getProxy());
}
@Override
@@ -91,7 +114,7 @@ public interface ActionInvocation extends org.apache.struts2.ActionInvocation {
@Override
public ValueStack getStack() {
return adaptee.getStack();
return ValueStack.adapt(adaptee.getStack());
}
@Override
@@ -20,88 +20,75 @@ package com.opensymphony.xwork2;
import com.opensymphony.xwork2.config.entities.ActionConfig;
/**
* ActionProxy is an extra layer between XWork and the action so that different proxies are possible.
*
* <p>
* An example of this would be a remote proxy, where the layer between XWork and the action might be RMI or SOAP.
* </p>
*
* @author Jason Carreira
*/
public interface ActionProxy {
@Deprecated
public interface ActionProxy extends org.apache.struts2.ActionProxy {
/**
* Gets the Action instance for this Proxy.
*
* @return the Action instance
*/
Object getAction();
/**
* Gets the alias name this ActionProxy is mapped to.
*
* @return the alias name
*/
String getActionName();
/**
* Gets the ActionConfig this ActionProxy is built from.
*
* @return the ActionConfig
*/
ActionConfig getConfig();
/**
* Sets whether this ActionProxy should also execute the Result after executing the Action.
*
* @param executeResult <tt>true</tt> to also execute the Result.
*/
void setExecuteResult(boolean executeResult);
/**
* Gets the status of whether the ActionProxy is set to execute the Result after the Action is executed.
*
* @return the status
*/
boolean getExecuteResult();
/**
* Gets the ActionInvocation associated with this ActionProxy.
*
* @return the ActionInvocation
*/
@Override
ActionInvocation getInvocation();
/**
* Gets the namespace the ActionConfig for this ActionProxy is mapped to.
*
* @return the namespace
*/
String getNamespace();
static ActionProxy adapt(org.apache.struts2.ActionProxy actualProxy) {
if (actualProxy instanceof ActionProxy) {
return (ActionProxy) actualProxy;
}
return actualProxy != null ? new LegacyAdapter(actualProxy) : null;
}
/**
* Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext
* ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal.
*
* @return the result code returned from executing the ActionInvocation
* @throws Exception can be thrown.
* @see ActionInvocation
*/
String execute() throws Exception;
class LegacyAdapter implements ActionProxy {
/**
* Gets the method name to execute, or <tt>null</tt> if no method has been specified (meaning <code>execute</code> will be invoked).
*
* @return the method to execute
*/
String getMethod();
private final org.apache.struts2.ActionProxy adaptee;
/**
* Gets status of the method value's initialization.
*
* @return true if the method returned by getMethod() is not a default initializer value.
*/
boolean isMethodSpecified();
private LegacyAdapter(org.apache.struts2.ActionProxy adaptee) {
this.adaptee = adaptee;
}
@Override
public Object getAction() {
return adaptee.getAction();
}
@Override
public String getActionName() {
return adaptee.getActionName();
}
@Override
public ActionConfig getConfig() {
return adaptee.getConfig();
}
@Override
public void setExecuteResult(boolean executeResult) {
adaptee.setExecuteResult(executeResult);
}
@Override
public boolean getExecuteResult() {
return adaptee.getExecuteResult();
}
@Override
public ActionInvocation getInvocation() {
return ActionInvocation.adapt(adaptee.getInvocation());
}
@Override
public String getNamespace() {
return adaptee.getNamespace();
}
@Override
public String execute() throws Exception {
return adaptee.execute();
}
@Override
public String getMethod() {
return adaptee.getMethod();
}
@Override
public boolean isMethodSpecified() {
return adaptee.isMethodSpecified();
}
}
}
@@ -18,25 +18,9 @@
*/
package com.opensymphony.xwork2;
import org.apache.struts2.interceptor.parameter.StrutsParameter;
/**
* ModelDriven Actions provide a model object to be pushed onto the ValueStack
* in addition to the Action itself, allowing a FormBean type approach like Struts.
*
* @author Jason Carreira
* @deprecated since 6.7.0, use {@link org.apache.struts2.ModelDriven} instead.
*/
public interface ModelDriven<T> {
/**
* Gets the model to be pushed onto the ValueStack instead of the Action itself.
* <p>
* Please be aware that all setters and getters of every depth on the object returned by this method are available
* for user parameter injection!
*
* @return the model
*/
@StrutsParameter(depth = Integer.MAX_VALUE)
T getModel();
@Deprecated
public interface ModelDriven<T> extends org.apache.struts2.ModelDriven<T> {
}
@@ -19,19 +19,8 @@
package com.opensymphony.xwork2;
/**
* Preparable Actions will have their <code>prepare()</code> method called if the {@link com.opensymphony.xwork2.interceptor.PrepareInterceptor}
* is applied to the ActionConfig.
*
* @author Jason Carreira
* @see com.opensymphony.xwork2.interceptor.PrepareInterceptor
* @deprecated since 6.7.0, use {@link org.apache.struts2.Preparable} instead.
*/
public interface Preparable {
/**
* This method is called to allow the action to prepare itself.
*
* @throws Exception thrown if a system level exception occurs.
*/
void prepare() throws Exception;
@Deprecated
public interface Preparable extends org.apache.struts2.Preparable {
}
@@ -34,6 +34,9 @@ public interface Result extends org.apache.struts2.Result {
void execute(ActionInvocation invocation) throws Exception;
static Result adapt(org.apache.struts2.Result actualResult) {
if (actualResult instanceof Result) {
return (Result) actualResult;
}
return actualResult != null ? new LegacyAdapter(actualResult) : null;
}
@@ -19,9 +19,8 @@
package com.opensymphony.xwork2;
/**
* Simple marker interface to indicate an object should <b>not</b> have its properties copied during chaining.
*
* @see com.opensymphony.xwork2.interceptor.ChainingInterceptor
* @deprecated since 6.7.0, use {@link org.apache.struts2.Unchainable} instead.
*/
public interface Unchainable {
@Deprecated
public interface Unchainable extends org.apache.struts2.Unchainable {
}
@@ -19,17 +19,8 @@
package com.opensymphony.xwork2;
/**
* Provides an interface in which a call for a validation check can be done.
*
* @author Jason Carreira
* @see ActionSupport
* @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
* @deprecated since 6.7.0, use {@link org.apache.struts2.Validateable} instead.
*/
public interface Validateable {
/**
* Performs validation.
*/
void validate();
@Deprecated
public interface Validateable extends org.apache.struts2.Validateable {
}
@@ -35,6 +35,7 @@ import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.dispatcher.Parameter;
import org.apache.struts2.interceptor.ValidationAware;
import java.util.Map;
@@ -21,7 +21,6 @@ package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionChainResult;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.Unchainable;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.ProxyUtil;
@@ -31,6 +30,7 @@ import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.Unchainable;
import java.util.ArrayList;
import java.util.Collection;
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.conversion.impl.ConversionData;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.struts2.interceptor.ValidationAware;
import java.util.HashMap;
import java.util.Map;
@@ -25,6 +25,9 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.interceptor.ValidationAware;
import org.apache.struts2.interceptor.ValidationErrorAware;
import org.apache.struts2.interceptor.ValidationWorkflowAware;
import java.io.Serial;
@@ -19,9 +19,9 @@
package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.ModelDriven;
/**
* <!-- START SNIPPET: description -->
@@ -36,6 +36,9 @@ public interface PreResultListener extends org.apache.struts2.interceptor.PreRes
void beforeResult(ActionInvocation invocation, String resultCode);
static PreResultListener adapt(org.apache.struts2.interceptor.PreResultListener actualListener) {
if (actualListener instanceof PreResultListener) {
return (PreResultListener) actualListener;
}
return actualListener != null ? new LegacyAdapter(actualListener) : null;
}
@@ -19,7 +19,7 @@
package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Preparable;
import org.apache.struts2.Preparable;
import java.io.Serial;
import java.lang.reflect.InvocationTargetException;
@@ -21,23 +21,8 @@ package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ModelDriven;
/**
* Adds the ability to set a model, probably retrieved from a given state.
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ScopedModelDriven} instead.
*/
public interface ScopedModelDriven<T> extends ModelDriven<T> {
/**
* @param model sets the model
*/
void setModel(T model);
/**
* Sets the key under which the model is stored
* @param key The model key
*/
void setScopeKey(String key);
/**
* @return the key under which the model is stored
*/
String getScopeKey();
@Deprecated
public interface ScopedModelDriven<T> extends org.apache.struts2.interceptor.ScopedModelDriven<T>, ModelDriven<T> {
}
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.inject.Inject;
import org.apache.struts2.StrutsException;
import org.apache.struts2.interceptor.ScopedModelDriven;
import java.lang.reflect.Method;
import java.util.Map;
@@ -34,6 +34,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.interceptor.ValidationAware;
import java.util.Collections;
import java.util.Map;
@@ -23,109 +23,84 @@ import java.util.List;
import java.util.Map;
/**
* ValidationAware classes can accept Action (class level) or field level error messages. Action level messages are kept
* in a Collection. Field level error messages are kept in a Map from String field name to a List of field error msgs.
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ValidationAware} instead.
*/
public interface ValidationAware {
@Deprecated
public interface ValidationAware extends org.apache.struts2.interceptor.ValidationAware {
/**
* Set the Collection of Action-level String error messages.
*
* @param errorMessages Collection of String error messages
*/
void setActionErrors(Collection<String> errorMessages);
/**
* Get the Collection of Action-level error messages for this action. Error messages should not
* be added directly here, as implementations are free to return a new Collection or an
* Unmodifiable Collection.
*
* @return Collection of String error messages
*/
Collection<String> getActionErrors();
/**
* Set the Collection of Action-level String messages (not errors).
*
* @param messages Collection of String messages (not errors).
*/
void setActionMessages(Collection<String> messages);
/**
* Get the Collection of Action-level messages for this action. Messages should not be added
* directly here, as implementations are free to return a new Collection or an Unmodifiable
* Collection.
*
* @return Collection of String messages
*/
Collection<String> getActionMessages();
/**
* Set the field error map of fieldname (String) to Collection of String error messages.
*
* @param errorMap field error map
*/
void setFieldErrors(Map<String, List<String>> errorMap);
/**
* Get the field specific errors associated with this action. Error messages should not be added
* directly here, as implementations are free to return a new Collection or an Unmodifiable
* Collection.
*
* @return Map with errors mapped from fieldname (String) to Collection of String error messages
*/
Map<String, List<String>> getFieldErrors();
/**
* Add an Action-level error message to this Action.
*
* @param anErrorMessage the error message
*/
void addActionError(String anErrorMessage);
/**
* Add an Action-level message to this Action.
*
* @param aMessage the message
*/
void addActionMessage(String aMessage);
/**
* Add an error message for a given field.
*
* @param fieldName name of field
* @param errorMessage the error message
*/
void addFieldError(String fieldName, String errorMessage);
/**
* Check whether there are any Action-level error messages.
*
* @return true if any Action-level error messages have been registered
*/
boolean hasActionErrors();
/**
* Checks whether there are any Action-level messages.
*
* @return true if any Action-level messages have been registered
*/
boolean hasActionMessages();
/**
* Checks whether there are any action errors or field errors.
*
* @return <code>(hasActionErrors() || hasFieldErrors())</code>
*/
default boolean hasErrors() {
return hasActionErrors() || hasFieldErrors();
static ValidationAware adapt(org.apache.struts2.interceptor.ValidationAware actualValidation) {
if (actualValidation instanceof ValidationAware) {
return (ValidationAware) actualValidation;
}
return actualValidation != null ? new LegacyAdapter(actualValidation) : null;
}
/**
* Check whether there are any field errors associated with this action.
*
* @return whether there are any field errors
*/
boolean hasFieldErrors();
class LegacyAdapter implements ValidationAware {
private final org.apache.struts2.interceptor.ValidationAware adaptee;
private LegacyAdapter(org.apache.struts2.interceptor.ValidationAware adaptee) {
this.adaptee = adaptee;
}
@Override
public void setActionErrors(Collection<String> errorMessages) {
adaptee.setActionErrors(errorMessages);
}
@Override
public Collection<String> getActionErrors() {
return adaptee.getActionErrors();
}
@Override
public void setActionMessages(Collection<String> messages) {
adaptee.setActionMessages(messages);
}
@Override
public Collection<String> getActionMessages() {
return adaptee.getActionMessages();
}
@Override
public void setFieldErrors(Map<String, List<String>> errorMap) {
adaptee.setFieldErrors(errorMap);
}
@Override
public Map<String, List<String>> getFieldErrors() {
return adaptee.getFieldErrors();
}
@Override
public void addActionError(String anErrorMessage) {
adaptee.addActionError(anErrorMessage);
}
@Override
public void addActionMessage(String aMessage) {
adaptee.addActionMessage(aMessage);
}
@Override
public void addFieldError(String fieldName, String errorMessage) {
adaptee.addFieldError(fieldName, errorMessage);
}
@Override
public boolean hasActionErrors() {
return adaptee.hasActionErrors();
}
@Override
public boolean hasActionMessages() {
return adaptee.hasActionMessages();
}
@Override
public boolean hasFieldErrors() {
return adaptee.hasFieldErrors();
}
}
}
@@ -19,22 +19,8 @@
package com.opensymphony.xwork2.interceptor;
/**
* ValidationErrorAware classes can be notified about validation errors
* before {@link com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor} will return 'inputResultName' result
* to allow change or not the result name
*
* This interface can be only applied to action which already implements {@link ValidationAware} interface!
*
* @since 2.3.15
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ValidationErrorAware} instead.
*/
public interface ValidationErrorAware {
/**
* Allows to notify action about occurred action/field errors
*
* @param currentResultName current result name, action can change it or return the same
* @return new result name or passed currentResultName
*/
String actionErrorOccurred(final String currentResultName);
@Deprecated
public interface ValidationErrorAware extends org.apache.struts2.interceptor.ValidationErrorAware {
}
@@ -19,12 +19,8 @@
package com.opensymphony.xwork2.interceptor;
/**
* ValidationWorkflowAware classes can programmatically change result name when errors occurred
*
* This interface can be only applied to action which already implements {@link ValidationAware} interface!
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ValidationWorkflowAware} instead.
*/
public interface ValidationWorkflowAware {
String getInputResultName();
@Deprecated
public interface ValidationWorkflowAware extends org.apache.struts2.interceptor.ValidationWorkflowAware {
}
@@ -19,8 +19,8 @@
package com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.interceptor.ValidationAware;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -20,12 +20,12 @@ package com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ModelDriven;
import java.beans.PropertyDescriptor;
import java.util.Locale;
@@ -23,144 +23,127 @@ import com.opensymphony.xwork2.ActionContext;
import java.util.Map;
/**
* ValueStack allows multiple beans to be pushed in and dynamic EL expressions to be evaluated against it. When
* evaluating an expression, the stack will be searched down the stack, from the latest objects pushed in to the
* earliest, looking for a bean with a getter or setter for the given property or a method of the given name (depending
* on the expression being evaluated).
* @deprecated since 6.7.0, use {@link org.apache.struts2.util.ValueStack} instead.
*/
public interface ValueStack {
String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
String REPORT_ERRORS_ON_NO_PROP = "com.opensymphony.xwork2.util.ValueStack.ReportErrorsOnNoProp";
/**
* Gets the context for this value stack. The context holds all the information in the value stack and it's surroundings.
*
* @return the context.
*/
Map<String, Object> getContext();
@Deprecated
public interface ValueStack extends org.apache.struts2.util.ValueStack {
@Override
ActionContext getActionContext();
/**
* Sets the default type to convert to if no type is provided when getting a value.
*
* @param defaultType the new default type
*/
void setDefaultType(Class defaultType);
static ValueStack adapt(org.apache.struts2.util.ValueStack actualStack) {
if (actualStack instanceof ValueStack) {
return (ValueStack) actualStack;
}
return actualStack != null ? new LegacyAdapter(actualStack) : null;
}
/**
* Set a override map containing <code> key -&gt; values </code> that takes precedent when doing find operations on the ValueStack.
* <p>
* See the unit test for ValueStackTest for examples.
* </p>
*
* @param overrides overrides map.
*/
void setExprOverrides(Map<Object, Object> overrides);
class LegacyAdapter implements ValueStack {
/**
* Gets the override map if anyone exists.
*
* @return the override map, <tt>null</tt> if not set.
*/
Map<Object, Object> getExprOverrides();
private final org.apache.struts2.util.ValueStack adaptee;
/**
* Get the CompoundRoot which holds the objects pushed onto the stack
*
* @return the root
*/
CompoundRoot getRoot();
private LegacyAdapter(org.apache.struts2.util.ValueStack adaptee) {
this.adaptee = adaptee;
}
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
*
* @param expr the expression defining the path to the property to be set.
* @param value the value to be set into the named property
*/
void setValue(String expr, Object value);
@Override
public Map<String, Object> getContext() {
return adaptee.getContext();
}
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
* N.B.: unlike #setValue(String,Object) it doesn't allow eval expression.
* @param expr the expression defining the path to the property to be set.
* @param value the value to be set into the named property
*/
void setParameter(String expr, Object value);
@Override
public ActionContext getActionContext() {
return ActionContext.adapt(adaptee.getActionContext());
}
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
*
* @param expr the expression defining the path to the property to be set.
* @param value the value to be set into the named property
* @param throwExceptionOnFailure a flag to tell whether an exception should be thrown if there is no property with
* the given name.
*/
void setValue(String expr, Object value, boolean throwExceptionOnFailure);
@Override
public void setDefaultType(Class defaultType) {
adaptee.setDefaultType(defaultType);
}
String findString(String expr);
String findString(String expr, boolean throwExceptionOnFailure);
@Override
public void setExprOverrides(Map<Object, Object> overrides) {
adaptee.setExprOverrides(overrides);
}
/**
* Find a value by evaluating the given expression against the stack in the default search order.
*
* @param expr the expression giving the path of properties to navigate to find the property value to return
* @return the result of evaluating the expression
*/
Object findValue(String expr);
@Override
public Map<Object, Object> getExprOverrides() {
return adaptee.getExprOverrides();
}
Object findValue(String expr, boolean throwExceptionOnFailure);
@Override
public CompoundRoot getRoot() {
return adaptee.getRoot();
}
/**
* Find a value by evaluating the given expression against the stack in the default search order.
*
* @param expr the expression giving the path of properties to navigate to find the property value to return
* @param asType the type to convert the return value to
* @return the result of evaluating the expression
*/
Object findValue(String expr, Class asType);
Object findValue(String expr, Class asType, boolean throwExceptionOnFailure);
@Override
public void setValue(String expr, Object value) {
adaptee.setValue(expr, value);
}
/**
* Get the object on the top of the stack <b>without</b> changing the stack.
*
* @return the object on the top.
* @see CompoundRoot#peek()
*/
Object peek();
@Override
public void setParameter(String expr, Object value) {
adaptee.setParameter(expr, value);
}
/**
* Get the object on the top of the stack and <b>remove</b> it from the stack.
*
* @return the object on the top of the stack
* @see CompoundRoot#pop()
*/
Object pop();
@Override
public void setValue(String expr, Object value, boolean throwExceptionOnFailure) {
adaptee.setValue(expr, value, throwExceptionOnFailure);
}
/**
* Put this object onto the top of the stack
*
* @param o the object to be pushed onto the stack
* @see CompoundRoot#push(Object)
*/
void push(Object o);
@Override
public String findString(String expr) {
return adaptee.findString(expr);
}
/**
* Sets an object on the stack with the given key
* so it is retrievable by {@link #findValue(String)}, {@link #findValue(String, Class)}
*
* @param key the key
* @param o the object
*/
void set(String key, Object o);
@Override
public String findString(String expr, boolean throwExceptionOnFailure) {
return adaptee.findString(expr, throwExceptionOnFailure);
}
/**
* Get the number of objects in the stack
*
* @return the number of objects in the stack
*/
int size();
@Override
public Object findValue(String expr) {
return adaptee.findValue(expr);
}
}
@Override
public Object findValue(String expr, boolean throwExceptionOnFailure) {
return adaptee.findValue(expr, throwExceptionOnFailure);
}
@Override
public Object findValue(String expr, Class asType) {
return adaptee.findValue(expr, asType);
}
@Override
public Object findValue(String expr, Class asType, boolean throwExceptionOnFailure) {
return adaptee.findValue(expr, asType, throwExceptionOnFailure);
}
@Override
public Object peek() {
return adaptee.peek();
}
@Override
public Object pop() {
return adaptee.pop();
}
@Override
public void push(Object o) {
adaptee.push(o);
}
@Override
public void set(String key, Object o) {
adaptee.set(key, o);
}
@Override
public int size() {
return adaptee.size();
}
}
}
@@ -254,8 +254,8 @@ public class DelegatingValidatorContext implements ValidatorContext {
}
protected static ValidationAware makeValidationAware(Object object) {
if (object instanceof ValidationAware) {
return (ValidationAware) object;
if (object instanceof org.apache.struts2.interceptor.ValidationAware) {
return ValidationAware.adapt((org.apache.struts2.interceptor.ValidationAware) object);
} else {
return new LoggingValidationAware(object);
}
@@ -20,13 +20,13 @@ package com.opensymphony.xwork2.validator;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.Validateable;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.interceptor.PrefixMethodInvocationUtil;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.Validateable;
/**
* <!-- START SNIPPET: description -->
@@ -71,9 +71,9 @@ import org.apache.logging.log4j.Logger;
* <li>programmatic - Defaults to true. If true and the action is Validateable call validate(),
* and any method that starts with "validate".
* </li>
*
*
* <li>declarative - Defaults to true. Perform validation based on xml or annotations.</li>
*
*
* </ul>
*
* <!-- END SNIPPET: parameters -->
@@ -90,14 +90,14 @@ import org.apache.logging.log4j.Logger;
*
* <pre>
* <!-- START SNIPPET: example -->
*
*
* &lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
* &lt;interceptor-ref name=&quot;params&quot;/&gt;
* &lt;interceptor-ref name=&quot;validation&quot;/&gt;
* &lt;interceptor-ref name=&quot;workflow&quot;/&gt;
* &lt;result name=&quot;success&quot;&gt;good_result.ftl&lt;/result&gt;
* &lt;/action&gt;
*
*
* &lt;-- in the following case myMethod of the action class will not
* get validated --&gt;
* &lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
@@ -108,7 +108,7 @@ import org.apache.logging.log4j.Logger;
* &lt;interceptor-ref name=&quot;workflow&quot;/&gt;
* &lt;result name=&quot;success&quot;&gt;good_result.ftl&lt;/result&gt;
* &lt;/action&gt;
*
*
* &lt;-- in the following case only annotated methods of the action class will
* be validated --&gt;
* &lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
@@ -138,9 +138,9 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
private final static String ALT_VALIDATE_PREFIX = "validateDo";
private boolean validateAnnotatedMethodOnly;
private ActionValidatorManager actionValidatorManager;
private boolean alwaysInvokeValidate = true;
private boolean programmatic = true;
private boolean declarative = true;
@@ -149,11 +149,11 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
public void setActionValidatorManager(ActionValidatorManager mgr) {
this.actionValidatorManager = mgr;
}
/**
* Determines if {@link Validateable}'s <code>validate()</code> should be called,
* as well as methods whose name that start with "validate". Defaults to "true".
*
*
* @param programmatic <tt>true</tt> then <code>validate()</code> is invoked.
*/
public void setProgrammatic(boolean programmatic) {
@@ -161,9 +161,9 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
}
/**
* Determines if validation based on annotations or xml should be performed. Defaults
* Determines if validation based on annotations or xml should be performed. Defaults
* to "true".
*
*
* @param declarative <tt>true</tt> then perform validation based on annotations or xml.
*/
public void setDeclarative(boolean declarative) {
@@ -171,9 +171,9 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
}
/**
* Determines if {@link Validateable}'s <code>validate()</code> should always
* Determines if {@link Validateable}'s <code>validate()</code> should always
* be invoked. Default to "true".
*
*
* @param alwaysInvokeValidate <tt>true</tt> then <code>validate()</code> is always invoked.
*/
public void setAlwaysInvokeValidate(String alwaysInvokeValidate) {
@@ -218,7 +218,7 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
if (LOG.isDebugEnabled()) {
LOG.debug("Validating {}/{} with method {}.", invocation.getProxy().getNamespace(), invocation.getProxy().getActionName(), method);
}
if (declarative) {
if (validateAnnotatedMethodOnly) {
@@ -226,12 +226,12 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
} else {
actionValidatorManager.validate(action, context);
}
}
}
if (action instanceof Validateable && programmatic) {
// keep exception that might occured in validateXXX or validateDoXXX
Exception exception = null;
Exception exception = null;
Validateable validateable = (Validateable) action;
LOG.debug("Invoking validate() on action {}", validateable);
@@ -239,19 +239,19 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
PrefixMethodInvocationUtil.invokePrefixMethod(invocation, new String[]{VALIDATE_PREFIX, ALT_VALIDATE_PREFIX});
}
catch(Exception e) {
// If any exception occurred while doing reflection, we want
// If any exception occurred while doing reflection, we want
// validate() to be executed
LOG.warn("an exception occured while executing the prefix method", e);
exception = e;
}
if (alwaysInvokeValidate) {
validateable.validate();
}
if (exception != null) {
// rethrow if something is wrong while doing validateXXX / validateDoXXX
if (exception != null) {
// rethrow if something is wrong while doing validateXXX / validateDoXXX
throw exception;
}
}
@@ -262,7 +262,7 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
doBeforeInvocation(invocation);
return invocation.invoke();
}
/**
* <p>
* Returns the context that will be used by the
@@ -20,9 +20,9 @@ package org.apache.struts2;
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 org.apache.struts2.util.ValueStack;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -0,0 +1,44 @@
/*
* 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 org.apache.struts2.util.ValueStack;
/**
* Provides hooks for handling key action events
*/
public interface ActionEventListener {
/**
* Called after an action has been created.
*
* @param action The action
* @param stack The current value stack
* @return The action to use
*/
Object prepare(Object action, ValueStack stack);
/**
* Called when an exception is thrown by the action
*
* @param t The exception/error that was thrown
* @param stack The current value stack
* @return A result code to execute, can be null
*/
String handleException(Throwable t, ValueStack stack);
}
@@ -19,10 +19,8 @@
package org.apache.struts2;
import com.opensymphony.xwork2.ActionChainResult;
import com.opensymphony.xwork2.ActionEventListener;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.interceptor.PreResultListener;
import org.apache.struts2.util.ValueStack;
/**
* An {@link ActionInvocation} represents the execution state of an {@link Action}. It holds the Interceptors and the Action instance.
@@ -177,6 +175,6 @@ public interface ActionInvocation {
*/
void setActionEventListener(ActionEventListener listener);
void init(ActionProxy proxy) ;
void init(ActionProxy proxy);
}
@@ -0,0 +1,102 @@
/*
* 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.config.entities.ActionConfig;
/**
* ActionProxy is an extra layer between XWork and the action so that different proxies are possible.
*
* <p>
* An example of this would be a remote proxy, where the layer between XWork and the action might be RMI or SOAP.
* </p>
*
* @author Jason Carreira
*/
public interface ActionProxy {
/**
* Gets the Action instance for this Proxy.
*
* @return the Action instance
*/
Object getAction();
/**
* Gets the alias name this ActionProxy is mapped to.
*
* @return the alias name
*/
String getActionName();
/**
* Gets the ActionConfig this ActionProxy is built from.
*
* @return the ActionConfig
*/
ActionConfig getConfig();
/**
* Sets whether this ActionProxy should also execute the Result after executing the Action.
*
* @param executeResult <tt>true</tt> to also execute the Result.
*/
void setExecuteResult(boolean executeResult);
/**
* Gets the status of whether the ActionProxy is set to execute the Result after the Action is executed.
*
* @return the status
*/
boolean getExecuteResult();
ActionInvocation getInvocation();
/**
* Gets the namespace the ActionConfig for this ActionProxy is mapped to.
*
* @return the namespace
*/
String getNamespace();
/**
* Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext
* ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal.
*
* @return the result code returned from executing the ActionInvocation
* @throws Exception can be thrown.
* @see ActionInvocation
*/
String execute() throws Exception;
/**
* Gets the method name to execute, or <tt>null</tt> if no method has been specified (meaning <code>execute</code> will be invoked).
*
* @return the method to execute
*/
String getMethod();
/**
* Gets status of the method value's initialization.
*
* @return true if the method returned by getMethod() is not a default initializer value.
*/
boolean isMethodSpecified();
}
@@ -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;
import org.apache.struts2.interceptor.parameter.StrutsParameter;
/**
* ModelDriven Actions provide a model object to be pushed onto the ValueStack
* in addition to the Action itself, allowing a FormBean type approach like Struts.
*
* @author Jason Carreira
*/
public interface ModelDriven<T> {
/**
* Gets the model to be pushed onto the ValueStack instead of the Action itself.
*
* @return the model
*/
@StrutsParameter(depth = Integer.MAX_VALUE)
T getModel();
}
@@ -0,0 +1,37 @@
/*
* 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;
/**
* Preparable Actions will have their <code>prepare()</code> method called if the {@link com.opensymphony.xwork2.interceptor.PrepareInterceptor}
* is applied to the ActionConfig.
*
* @author Jason Carreira
* @see com.opensymphony.xwork2.interceptor.PrepareInterceptor
*/
public interface Preparable {
/**
* This method is called to allow the action to prepare itself.
*
* @throws Exception thrown if a system level exception occurs.
*/
void prepare() throws Exception;
}
@@ -0,0 +1,27 @@
/*
* 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;
/**
* Simple marker interface to indicate an object should <b>not</b> have its properties copied during chaining.
*
* @see com.opensymphony.xwork2.interceptor.ChainingInterceptor
*/
public interface Unchainable {
}
@@ -0,0 +1,35 @@
/*
* 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;
/**
* Provides an interface in which a call for a validation check can be done.
*
* @author Jason Carreira
* @see com.opensymphony.xwork2.ActionSupport
* @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
*/
public interface Validateable {
/**
* Performs validation.
*/
void validate();
}
@@ -25,7 +25,6 @@ import com.opensymphony.xwork2.TextProviderFactory;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.util.TextParseUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -20,7 +20,6 @@ package org.apache.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.logging.log4j.LogManager;
@@ -21,7 +21,6 @@ package org.apache.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
@@ -0,0 +1,43 @@
/*
* 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.ModelDriven;
/**
* Adds the ability to set a model, probably retrieved from a given state.
*/
public interface ScopedModelDriven<T> extends ModelDriven<T> {
/**
* @param model sets the model
*/
void setModel(T model);
/**
* Sets the key under which the model is stored
* @param key The model key
*/
void setScopeKey(String key);
/**
* @return the key under which the model is stored
*/
String getScopeKey();
}
@@ -21,7 +21,6 @@ package org.apache.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.TextProviderFactory;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import org.apache.logging.log4j.LogManager;
@@ -0,0 +1,131 @@
/*
* 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 java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* ValidationAware classes can accept Action (class level) or field level error messages. Action level messages are kept
* in a Collection. Field level error messages are kept in a Map from String field name to a List of field error msgs.
*/
public interface ValidationAware {
/**
* Set the Collection of Action-level String error messages.
*
* @param errorMessages Collection of String error messages
*/
void setActionErrors(Collection<String> errorMessages);
/**
* Get the Collection of Action-level error messages for this action. Error messages should not
* be added directly here, as implementations are free to return a new Collection or an
* Unmodifiable Collection.
*
* @return Collection of String error messages
*/
Collection<String> getActionErrors();
/**
* Set the Collection of Action-level String messages (not errors).
*
* @param messages Collection of String messages (not errors).
*/
void setActionMessages(Collection<String> messages);
/**
* Get the Collection of Action-level messages for this action. Messages should not be added
* directly here, as implementations are free to return a new Collection or an Unmodifiable
* Collection.
*
* @return Collection of String messages
*/
Collection<String> getActionMessages();
/**
* Set the field error map of fieldname (String) to Collection of String error messages.
*
* @param errorMap field error map
*/
void setFieldErrors(Map<String, List<String>> errorMap);
/**
* Get the field specific errors associated with this action. Error messages should not be added
* directly here, as implementations are free to return a new Collection or an Unmodifiable
* Collection.
*
* @return Map with errors mapped from fieldname (String) to Collection of String error messages
*/
Map<String, List<String>> getFieldErrors();
/**
* Add an Action-level error message to this Action.
*
* @param anErrorMessage the error message
*/
void addActionError(String anErrorMessage);
/**
* Add an Action-level message to this Action.
*
* @param aMessage the message
*/
void addActionMessage(String aMessage);
/**
* Add an error message for a given field.
*
* @param fieldName name of field
* @param errorMessage the error message
*/
void addFieldError(String fieldName, String errorMessage);
/**
* Check whether there are any Action-level error messages.
*
* @return true if any Action-level error messages have been registered
*/
boolean hasActionErrors();
/**
* Checks whether there are any Action-level messages.
*
* @return true if any Action-level messages have been registered
*/
boolean hasActionMessages();
/**
* Checks whether there are any action errors or field errors.
*
* @return <code>(hasActionErrors() || hasFieldErrors())</code>
*/
default boolean hasErrors() {
return hasActionErrors() || hasFieldErrors();
}
/**
* Check whether there are any field errors associated with this action.
*
* @return whether there are any field errors
*/
boolean hasFieldErrors();
}
@@ -0,0 +1,40 @@
/*
* 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;
/**
* ValidationErrorAware classes can be notified about validation errors
* before {@link com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor} will return 'inputResultName' result
* to allow change or not the result name
*
* This interface can be only applied to action which already implements {@link ValidationAware} interface!
*
* @since 2.3.15
*/
public interface ValidationErrorAware {
/**
* Allows to notify action about occurred action/field errors
*
* @param currentResultName current result name, action can change it or return the same
* @return new result name or passed currentResultName
*/
String actionErrorOccurred(final String currentResultName);
}
@@ -0,0 +1,30 @@
/*
* 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;
/**
* ValidationWorkflowAware classes can programmatically change result name when errors occurred
*
* This interface can be only applied to action which already implements {@link ValidationAware} interface!
*/
public interface ValidationWorkflowAware {
String getInputResultName();
}
@@ -0,0 +1,167 @@
/*
* 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.util;
import com.opensymphony.xwork2.util.CompoundRoot;
import org.apache.struts2.ActionContext;
import java.util.Map;
/**
* ValueStack allows multiple beans to be pushed in and dynamic EL expressions to be evaluated against it. When
* evaluating an expression, the stack will be searched down the stack, from the latest objects pushed in to the
* earliest, looking for a bean with a getter or setter for the given property or a method of the given name (depending
* on the expression being evaluated).
*/
public interface ValueStack {
String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
String REPORT_ERRORS_ON_NO_PROP = "com.opensymphony.xwork2.util.ValueStack.ReportErrorsOnNoProp";
/**
* Gets the context for this value stack. The context holds all the information in the value stack and it's surroundings.
*
* @return the context.
*/
Map<String, Object> getContext();
ActionContext getActionContext();
/**
* Sets the default type to convert to if no type is provided when getting a value.
*
* @param defaultType the new default type
*/
void setDefaultType(Class defaultType);
/**
* Set a override map containing <code> key -&gt; values </code> that takes precedent when doing find operations on the ValueStack.
* <p>
* See the unit test for ValueStackTest for examples.
* </p>
*
* @param overrides overrides map.
*/
void setExprOverrides(Map<Object, Object> overrides);
/**
* Gets the override map if anyone exists.
*
* @return the override map, <tt>null</tt> if not set.
*/
Map<Object, Object> getExprOverrides();
/**
* Get the CompoundRoot which holds the objects pushed onto the stack
*
* @return the root
*/
CompoundRoot getRoot();
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
*
* @param expr the expression defining the path to the property to be set.
* @param value the value to be set into the named property
*/
void setValue(String expr, Object value);
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
* N.B.: unlike #setValue(String,Object) it doesn't allow eval expression.
* @param expr the expression defining the path to the property to be set.
* @param value the value to be set into the named property
*/
void setParameter(String expr, Object value);
/**
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
*
* @param expr the expression defining the path to the property to be set.
* @param value the value to be set into the named property
* @param throwExceptionOnFailure a flag to tell whether an exception should be thrown if there is no property with
* the given name.
*/
void setValue(String expr, Object value, boolean throwExceptionOnFailure);
String findString(String expr);
String findString(String expr, boolean throwExceptionOnFailure);
/**
* Find a value by evaluating the given expression against the stack in the default search order.
*
* @param expr the expression giving the path of properties to navigate to find the property value to return
* @return the result of evaluating the expression
*/
Object findValue(String expr);
Object findValue(String expr, boolean throwExceptionOnFailure);
/**
* Find a value by evaluating the given expression against the stack in the default search order.
*
* @param expr the expression giving the path of properties to navigate to find the property value to return
* @param asType the type to convert the return value to
* @return the result of evaluating the expression
*/
Object findValue(String expr, Class asType);
Object findValue(String expr, Class asType, boolean throwExceptionOnFailure);
/**
* Get the object on the top of the stack <b>without</b> changing the stack.
*
* @return the object on the top.
* @see CompoundRoot#peek()
*/
Object peek();
/**
* Get the object on the top of the stack and <b>remove</b> it from the stack.
*
* @return the object on the top of the stack
* @see CompoundRoot#pop()
*/
Object pop();
/**
* Put this object onto the top of the stack
*
* @param o the object to be pushed onto the stack
* @see CompoundRoot#push(Object)
*/
void push(Object o);
/**
* Sets an object on the stack with the given key
* so it is retrievable by {@link #findValue(String)}, {@link #findValue(String, Class)}
*
* @param key the key
* @param o the object
*/
void set(String key, Object o);
/**
* Get the number of objects in the stack
*
* @return the number of objects in the stack
*/
int size();
}
@@ -65,7 +65,9 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
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")
Class.forName("org.apache.struts2.Action"),
Class.forName("org.apache.struts2.Validateable"),
Class.forName("org.apache.struts2.interceptor.ValidationAware")
);
}
@@ -93,7 +95,9 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
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")
Class.forName("org.apache.struts2.Action"),
Class.forName("org.apache.struts2.Validateable"),
Class.forName("org.apache.struts2.interceptor.ValidationAware")
);
}
@@ -120,7 +124,9 @@ public class ConfigurationProviderOgnlAllowlistTest extends XWorkJUnit4TestCase
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")
Class.forName("org.apache.struts2.Action"),
Class.forName("org.apache.struts2.Validateable"),
Class.forName("org.apache.struts2.interceptor.ValidationAware")
);
}
}
@@ -20,7 +20,6 @@ package org.apache.struts.beanvalidation.validation.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.TextProviderFactory;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
@@ -33,6 +32,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts.beanvalidation.constraints.ValidationGroup;
import org.apache.struts.beanvalidation.validation.constant.ValidatorConstants;
import org.apache.struts2.ModelDriven;
import org.apache.struts2.interceptor.validation.SkipValidation;
import jakarta.validation.ConstraintViolation;
@@ -20,7 +20,6 @@ package org.apache.struts2.json;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
@@ -29,6 +28,7 @@ import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ModelDriven;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.json.smd.SMDGenerator;
@@ -20,13 +20,13 @@ package org.apache.struts2.json;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ModelDriven;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ValidationAware;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -22,7 +22,6 @@ import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.interceptor.annotations.After;
import com.opensymphony.xwork2.interceptor.annotations.Before;
import jakarta.servlet.ServletException;
@@ -35,6 +34,7 @@ import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.interceptor.ValidationAware;
import org.apache.struts2.util.StrutsTestCaseHelper;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.mock.web.MockHttpServletRequest;
@@ -19,9 +19,9 @@
package org.apache.struts2.rest;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.struts2.ModelDriven;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.rest.handler.ContentTypeHandler;
@@ -18,19 +18,23 @@
*/
package org.apache.struts2.rest;
import com.opensymphony.xwork2.*;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.DefaultActionInvocation;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ModelDriven;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.result.HttpHeaderResult;
import org.apache.struts2.interceptor.ValidationAware;
import org.apache.struts2.rest.handler.ContentTypeHandler;
import org.apache.struts2.rest.handler.HtmlHandler;
import org.apache.struts2.result.HttpHeaderResult;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -74,7 +78,7 @@ public class RestActionInvocation extends DefaultActionInvocation {
/**
* If set to true (by default) blocks returning content from any other methods than GET,
* if set to false, the content can be returned for any kind of method
*
*
* @param restrictToGet true or false
*/
@Inject(value = RestConstants.REST_CONTENT_RESTRICT_TO_GET, required = false)
@@ -23,10 +23,10 @@ import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.interceptor.ValidationAware;
import java.util.HashMap;
import java.util.Map;
@@ -19,7 +19,6 @@
package org.apache.struts2.rest.handler;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.security.ArrayTypePermission;
@@ -29,6 +28,7 @@ import com.thoughtworks.xstream.security.PrimitiveTypePermission;
import com.thoughtworks.xstream.security.TypePermission;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ModelDriven;
import org.apache.struts2.rest.handler.xstream.XStreamAllowedClassNames;
import org.apache.struts2.rest.handler.xstream.XStreamAllowedClasses;
import org.apache.struts2.rest.handler.xstream.XStreamPermissionProvider;