Compare commits

..

30 Commits

Author SHA1 Message Date
Lukasz Lenart f0f4e9ece7 [maven-release-plugin] prepare release STRUTS_2_5_10 2017-01-27 10:35:05 +01:00
Lukasz Lenart 45580718ab WW-4735 Uses more flexible RegExp to match domain suffixes 2017-01-27 08:27:50 +01:00
Lukasz Lenart 87f113ebb2 Moves description to wiki 2017-01-19 08:36:26 +01:00
Lukasz Lenart 0023d9664b [maven-release-plugin] prepare for next development iteration 2017-01-17 10:27:23 +01:00
Lukasz Lenart ee27b6604a [maven-release-plugin] prepare release STRUTS_2_5_9 2017-01-17 10:27:01 +01:00
Lukasz Lenart 7f80ef1bb5 WW-4734 Fixes proper lookup flow 2017-01-15 17:59:41 +01:00
Lukasz Lenart 253799c6c5 Adds additional excluded packages 2017-01-12 08:07:12 +01:00
Lukasz Lenart 20c54df03a WW-4733 Reduces noise in the logs 2017-01-12 08:06:59 +01:00
Lukasz Lenart ff8d731594 Fixes test to match fixed error message 2017-01-10 19:41:59 +01:00
Lukasz Lenart 880c4c2d33 Fixes small typo 2017-01-10 19:07:37 +01:00
Lukasz Lenart d12bb7cddb WW-4722 Uses proper read method 2017-01-10 19:06:15 +01:00
Lukasz Lenart f48c9620fc WW-4731 Adds additional test case to confirm that everything is ok 2017-01-10 10:28:54 +01:00
Lukasz Lenart fc6ffba9cf WW-4730 Uses session.getId().intern() to properly lock down session 2017-01-09 11:52:30 +01:00
Lukasz Lenart 08e181a4fe WW-4728 Allows override request parameter names used to enable validation 2017-01-09 11:40:13 +01:00
Lukasz Lenart a7f4e255b0 Uses AbstractInterceptor instead of leaving init() and destroy() empty 2017-01-09 10:18:59 +01:00
Lukasz Lenart 2b12f06b01 WW-4687 Allows define interceptors with dynamic parameters 2017-01-09 10:07:20 +01:00
Lukasz Lenart b9c05a7181 Extracts default loop count constant 2017-01-09 09:12:35 +01:00
Lukasz Lenart 14d56fbb93 WW-4731 Moves detailed description to wiki 2017-01-08 20:29:58 +01:00
Lukasz Lenart 97419283ea WW-4050 Converts NoSuchMethodExceotion into ConfigurationException 2017-01-02 09:00:21 +01:00
Lukasz Lenart 55fed53764 WW-4174 Makes fields protected to allow easily override 2017-01-02 08:20:14 +01:00
Lukasz Lenart 98979423a1 WW-3787 WW-3961 Allows include config files from JARs 2016-12-31 12:04:35 +01:00
Lukasz Lenart 3144b6c995 WW-4729 Fixes issue with passing params in location 2016-12-30 14:39:07 +01:00
Lukasz Lenart 3ce21403ee WW-4102 Reduces LOG visibility 2016-12-30 14:11:16 +01:00
Lukasz Lenart e38a71365a WW-4695 Puts back commons-collections 3.x to override Velocity's transitive dependency 2016-12-30 08:06:06 +01:00
Lukasz Lenart f78d90ee22 WW-4726 Fixes wrong value type used to limit upload 2016-12-20 19:50:43 +01:00
Lukasz Lenart 7e4d1b45ea WW-4725 Allows handle all redirection by MessageStoreInterceptor 2016-12-19 18:51:04 +01:00
Lukasz Lenart 4727265e59 [maven-release-plugin] prepare for next development iteration 2016-12-06 11:18:07 +01:00
Lukasz Lenart 4281e31864 [maven-release-plugin] prepare release STRUTS_2_5_8 2016-12-06 11:17:46 +01:00
Lukasz Lenart baffa9a68b WW-4722 Checks proper scope for stored locale 2016-12-02 19:30:36 +01:00
Lukasz Lenart 484ce1d191 [maven-release-plugin] prepare for next development iteration 2016-12-02 08:27:02 +01:00
91 changed files with 815 additions and 634 deletions
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
+2 -2
View File
@@ -26,12 +26,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>2.5.7</version>
<version>2.5.10</version>
<name>Struts 2 Rest Showcase Webapp</name>
<description>Struts 2 Rest Showcase Example</description>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-showcase</artifactId>
@@ -24,23 +24,17 @@ package org.apache.struts2.showcase.chat;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.struts2.dispatcher.SessionMap;
public class ChatAuthenticationInterceptor implements Interceptor {
public class ChatAuthenticationInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LogManager.getLogger(ChatAuthenticationInterceptor.class);
public static final String USER_SESSION_KEY = "chatUserSessionKey";
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
LOG.debug("Authenticating chat user");
@@ -23,7 +23,7 @@ package org.apache.struts2.showcase.chat;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
@@ -32,7 +32,7 @@ import javax.servlet.http.HttpSession;
/**
* Authenticate showcase chat example, make sure everyone have a username.
*/
public class ChatInterceptor implements Interceptor {
public class ChatInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(ChatInterceptor.class);
@@ -40,12 +40,6 @@ public class ChatInterceptor implements Interceptor {
public static final String CHAT_USER_SESSION_KEY = "ChatUserSessionKey";
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
HttpSession session = (HttpSession) ActionContext.getContext().get(ActionContext.SESSION);
User chatUser = (User) session.getAttribute(CHAT_USER_SESSION_KEY);
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-assembly</artifactId>
+3 -3
View File
@@ -10,7 +10,7 @@
</parent>
<artifactId>struts2-bom</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
<packaging>pom</packaging>
<name>Struts 2 Bill of Materials</name>
@@ -25,7 +25,7 @@
</licenses>
<properties>
<struts-version.version>2.5.7</struts-version.version>
<struts-version.version>2.5.10</struts-version.version>
</properties>
<build>
@@ -172,6 +172,6 @@
</dependencyManagement>
<scm>
<tag>STRUTS_2_5_7</tag>
<tag>STRUTS_2_5_10</tag>
</scm>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-osgi-admin-bundle</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-osgi-demo-bundle</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-osgi-bundles</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-core</artifactId>
<packaging>jar</packaging>
@@ -19,21 +19,16 @@ 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.*;
/**
* 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 Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
protected static Logger LOG = LogManager.getLogger(ActionSupport.class);
private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
private transient TextProvider textProvider;
@@ -21,7 +21,9 @@ import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.interceptor.WithLazyParams;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
@@ -67,6 +69,7 @@ public class DefaultActionInvocation implements ActionInvocation {
protected Container container;
protected UnknownHandlerManager unknownHandlerManager;
protected OgnlUtil ognlUtil;
protected WithLazyParams.LazyParamInjector lazyParamInjector;
public DefaultActionInvocation(final Map<String, Object> extraContext, final boolean pushAction) {
this.extraContext = extraContext;
@@ -233,11 +236,15 @@ public class DefaultActionInvocation implements ActionInvocation {
}
if (interceptors.hasNext()) {
final InterceptorMapping interceptor = interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
final InterceptorMapping interceptorMapping = interceptors.next();
String interceptorMsg = "interceptorMapping: " + interceptorMapping.getName();
UtilTimerStack.push(interceptorMsg);
try {
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
Interceptor interceptor = interceptorMapping.getInterceptor();
if (interceptor instanceof WithLazyParams) {
interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext);
}
resultCode = interceptor.intercept(DefaultActionInvocation.this);
} finally {
UtilTimerStack.pop(interceptorMsg);
}
@@ -400,6 +407,13 @@ public class DefaultActionInvocation implements ActionInvocation {
invocationContext.setName(proxy.getActionName());
createInterceptors(proxy);
prepareLazyParamInjector(invocationContext.getValueStack());
}
protected void prepareLazyParamInjector(ValueStack valueStack) {
lazyParamInjector = new WithLazyParams.LazyParamInjector(valueStack);
container.inject(lazyParamInjector);
}
protected void createInterceptors(ActionProxy proxy) {
@@ -19,6 +19,8 @@ package com.opensymphony.xwork2.config.entities;
import com.opensymphony.xwork2.interceptor.Interceptor;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* <code>InterceptorMapping</code>
@@ -30,10 +32,16 @@ public class InterceptorMapping implements Serializable {
private String name;
private Interceptor interceptor;
private final Map<String, String> params;
public InterceptorMapping(String name, Interceptor interceptor) {
this(name, interceptor, new HashMap<String, String>());
}
public InterceptorMapping(String name, Interceptor interceptor, Map<String, String> params) {
this.name = name;
this.interceptor = interceptor;
this.params = params;
}
public String getName() {
@@ -44,6 +52,10 @@ public class InterceptorMapping implements Serializable {
return interceptor;
}
public Map<String, String> getParams() {
return params;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -65,7 +77,7 @@ public class InterceptorMapping implements Serializable {
@Override
public String toString() {
return "InterceptorMapping: [" + name + "] => [" + interceptor.getClass().getName() + ']';
return "InterceptorMapping: [" + name + "] => [" + interceptor.getClass().getName() + "] with params [" + params + "]" ;
}
}
@@ -25,6 +25,7 @@ import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.location.Location;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -43,7 +44,6 @@ public class InterceptorBuilder {
private static final Logger LOG = LogManager.getLogger(InterceptorBuilder.class);
/**
* Builds a list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object).
*
@@ -67,13 +67,11 @@ public class InterceptorBuilder {
InterceptorConfig config = (InterceptorConfig) referencedConfig;
Interceptor inter;
try {
inter = objectFactory.buildInterceptor(config, refParams);
result.add(new InterceptorMapping(refName, inter));
result.add(new InterceptorMapping(refName, inter, refParams));
} catch (ConfigurationException ex) {
LOG.warn("Unable to load config class {} at {} probably due to a missing jar, which might be fine if you never plan to use the {} interceptor",
config.getClassName(), ex.getLocation(), config.getName());
LOG.error("Unable to load config class {}", config.getClassName(), ex);
LOG.warn(new ParameterizedMessage("Unable to load config class {} at {} probably due to a missing jar, which might be fine if you never plan to use the {} interceptor",
config.getClassName(), ex.getLocation(), config.getName()), ex);
}
} else if (referencedConfig instanceof InterceptorStackConfig) {
@@ -757,7 +757,7 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
{
// if <result ...>something</result> then we add a parameter of 'something' as this is the most used result param
if (resultElement.getChildNodes().getLength() >= 1) {
resultParams = new LinkedHashMap<String, String>();
resultParams = new LinkedHashMap<>();
String paramName = config.getDefaultResultParam();
if (paramName != null) {
@@ -775,7 +775,7 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
resultParams.put(paramName, val);
}
} else {
LOG.warn("No default parameter defined for result [{}] of type [{}] ", config.getName(), config.getClassName());
LOG.debug("No default parameter defined for result [{}] of type [{}] ", config.getName(), config.getClassName());
}
}
}
@@ -5,7 +5,10 @@ import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.entities.InterceptorConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.WithLazyParams;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.HashMap;
import java.util.Map;
@@ -15,6 +18,8 @@ import java.util.Map;
*/
public class DefaultInterceptorFactory implements InterceptorFactory {
private static final Logger LOG = LogManager.getLogger(DefaultInterceptorFactory.class);
private ObjectFactory objectFactory;
private ReflectionProvider reflectionProvider;
@@ -40,7 +45,12 @@ public class DefaultInterceptorFactory implements InterceptorFactory {
try {
// interceptor instances are long-lived and used across user sessions, so don't try to pass in any extra context
Object o = objectFactory.buildBean(interceptorClassName, null);
reflectionProvider.setProperties(params, o);
if (o instanceof WithLazyParams) {
LOG.debug("Interceptor {} is marked with interface {} and params will be set during action invocation",
interceptorClassName, WithLazyParams.class.getName());
} else {
reflectionProvider.setProperties(params, o);
}
if (o instanceof Interceptor) {
Interceptor interceptor = (Interceptor) o;
@@ -153,7 +153,7 @@ import java.util.Map;
*/
public class ExceptionMappingInterceptor extends AbstractInterceptor {
protected static final Logger LOG = LogManager.getLogger(ExceptionMappingInterceptor.class);
private static final Logger LOG = LogManager.getLogger(ExceptionMappingInterceptor.class);
protected Logger categoryLogger;
protected boolean logEnabled = false;
@@ -70,7 +70,8 @@ import java.util.Set;
* @see com.opensymphony.xwork2.validator.ValidationInterceptor
*/
public abstract class MethodFilterInterceptor extends AbstractInterceptor {
protected transient Logger log = LogManager.getLogger(getClass());
private static final Logger LOG = LogManager.getLogger(MethodFilterInterceptor.class);
protected Set<String> excludeMethods = Collections.emptySet();
protected Set<String> includeMethods = Collections.emptySet();
@@ -104,7 +105,7 @@ public abstract class MethodFilterInterceptor extends AbstractInterceptor {
// ValidationInterceptor
boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method);
if (!applyMethod) {
log.debug("Skipping Interceptor... Method [{}] found in exclude list.", method);
LOG.debug("Skipping Interceptor... Method [{}] found in exclude list.", method);
}
return applyMethod;
}
@@ -93,7 +93,8 @@ import org.apache.logging.log4j.Logger;
* @author Claus Ibsen
*/
public class TimerInterceptor extends AbstractInterceptor {
protected static final Logger LOG = LogManager.getLogger(TimerInterceptor.class);
private static final Logger LOG = LogManager.getLogger(TimerInterceptor.class);
protected Logger categoryLogger;
protected String logCategory;
@@ -0,0 +1,63 @@
package com.opensymphony.xwork2.interceptor;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.TextParser;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
import java.util.Map;
/**
* Interceptors marked with this interface won't be fully initialised during initialisation.
* Appropriated params will be injected just before usage of the interceptor.
*
* Please be aware that in such case {@link Interceptor#init()} method must be prepared for this.
*
* @since 2.5.9
*/
public interface WithLazyParams {
class LazyParamInjector {
protected OgnlUtil ognlUtil;
protected TextParser textParser;
protected ReflectionProvider reflectionProvider;
private final TextParseUtil.ParsedValueEvaluator valueEvaluator;
public LazyParamInjector(final ValueStack valueStack) {
valueEvaluator = new TextParseUtil.ParsedValueEvaluator() {
public Object evaluate(String parsedValue) {
return valueStack.findValue(parsedValue); // no asType !!!
}
};
}
@Inject
public void setTextParser(TextParser textParser) {
this.textParser = textParser;
}
@Inject
public void setReflectionProvider(ReflectionProvider reflectionProvider) {
this.reflectionProvider = reflectionProvider;
}
@Inject
public void setOgnlUtil(OgnlUtil ognlUtil) {
this.ognlUtil = ognlUtil;
}
public Interceptor injectParams(Interceptor interceptor, Map<String, String> params, ActionContext invocationContext) {
for (Map.Entry<String, String> entry : params.entrySet()) {
Object paramValue = textParser.evaluate(new char[]{ '$' }, entry.getValue(), valueEvaluator, TextParser.DEFAULT_LOOP_COUNT);
ognlUtil.setProperty(entry.getKey(), paramValue, interceptor, invocationContext.getContextMap());
}
return interceptor;
}
}
}
@@ -16,16 +16,15 @@
package com.opensymphony.xwork2.mock;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.junit.Assert;
/**
* Mock for an {@link com.opensymphony.xwork2.interceptor.Interceptor}.
*
* @author Jason Carreira
*/
public class MockInterceptor implements Interceptor {
public class MockInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 2692551676567227756L;
@@ -57,12 +56,6 @@ public class MockInterceptor implements Interceptor {
return foo;
}
/**
* Called to let an interceptor clean up any resources it has allocated.
*/
public void destroy() {
}
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -101,13 +94,6 @@ public class MockInterceptor implements Interceptor {
return result;
}
/**
* Called after an Interceptor is created, but before any requests are processed using the intercept() methodName. This
* gives the Interceptor a chance to initialize any needed resources.
*/
public void init() {
}
/**
* Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
* request by the DefaultActionInvocation or to short-circuit the processing and just return a String return code.
@@ -52,19 +52,20 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
public static final String THROW_EXCEPTION_ON_FAILURE = OgnlValueStack.class.getName() + ".throwExceptionOnFailure";
private static final Logger LOG = LogManager.getLogger(OgnlValueStack.class);
private static final long serialVersionUID = 370737852934925530L;
private static final String MAP_IDENTIFIER_KEY = "com.opensymphony.xwork2.util.OgnlValueStack.MAP_IDENTIFIER_KEY";
private static final Logger LOG = LogManager.getLogger(OgnlValueStack.class);
CompoundRoot root;
transient Map<String, Object> context;
Class defaultType;
Map<Object, Object> overrides;
transient OgnlUtil ognlUtil;
transient SecurityMemberAccess securityMemberAccess;
protected CompoundRoot root;
protected transient Map<String, Object> context;
protected Class defaultType;
protected Map<Object, Object> overrides;
protected transient OgnlUtil ognlUtil;
protected transient SecurityMemberAccess securityMemberAccess;
private transient XWorkConverter converter;
private boolean devMode;
private boolean logMissingProperties;
@@ -189,7 +190,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
context.remove(REPORT_ERRORS_ON_NO_PROP);
}
private void handleRuntimeException(String expr, Object value, boolean throwExceptionOnFailure, RuntimeException re) {
protected void handleRuntimeException(String expr, Object value, boolean throwExceptionOnFailure, RuntimeException re) {
if (throwExceptionOnFailure) {
String message = ErrorMessageBuilder.create()
.errorSettingExpressionWithValue(expr, value)
@@ -200,7 +201,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
}
}
private void handleOgnlException(String expr, Object value, boolean throwExceptionOnFailure, OgnlException e) {
protected void handleOgnlException(String expr, Object value, boolean throwExceptionOnFailure, OgnlException e) {
boolean shouldLog = shouldLogMissingPropertyWarning(e);
String msg = null;
if (throwExceptionOnFailure || shouldLog) {
@@ -242,7 +243,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
}
}
private void setupExceptionOnFailure(boolean throwExceptionOnFailure) {
protected void setupExceptionOnFailure(boolean throwExceptionOnFailure) {
if (throwExceptionOnFailure) {
context.put(THROW_EXCEPTION_ON_FAILURE, true);
}
@@ -255,7 +256,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
return tryFindValue(expr);
}
private Object handleOtherException(String expr, boolean throwExceptionOnFailure, Exception e) {
protected Object handleOtherException(String expr, boolean throwExceptionOnFailure, Exception e) {
logLookupFailure(expr, e);
if (throwExceptionOnFailure)
@@ -322,7 +323,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
return tryFindValue(expr, asType);
}
private Object handleOgnlException(String expr, boolean throwExceptionOnFailure, OgnlException e) {
protected Object handleOgnlException(String expr, boolean throwExceptionOnFailure, OgnlException e) {
Object ret = findInContext(expr);
if (ret == null) {
if (shouldLogMissingPropertyWarning(e)) {
@@ -335,7 +336,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
return ret;
}
private boolean shouldLogMissingPropertyWarning(OgnlException e) {
protected boolean shouldLogMissingPropertyWarning(OgnlException e) {
return (e instanceof NoSuchPropertyException || e instanceof MethodFailedException)
&& devMode && logMissingProperties;
}
@@ -359,7 +360,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
return ognlUtil.getValue(expr, context, root, asType);
}
private Object findInContext(String name) {
protected Object findInContext(String name) {
return getContext().get(name);
}
@@ -38,11 +38,11 @@ import java.util.Set;
*/
public class OgnlValueStackFactory implements ValueStackFactory {
private XWorkConverter xworkConverter;
private CompoundRootAccessor compoundRootAccessor;
private TextProvider textProvider;
private Container container;
private boolean allowStaticMethodAccess;
protected XWorkConverter xworkConverter;
protected CompoundRootAccessor compoundRootAccessor;
protected TextProvider textProvider;
protected Container container;
protected boolean allowStaticMethodAccess;
@Inject
public void setXWorkConverter(XWorkConverter converter) {
@@ -53,6 +53,8 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
@Override
public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
LOG.debug("Checking access for [target: {}, member: {}, property: {}] is deprecated!", target, member, propertyName);
if (checkEnumAccess(target, member)) {
LOG.trace("Allowing access to enum: {}", target);
return true;
@@ -20,12 +20,16 @@ package com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.XWorkException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* This class is an utility class that will search through the classpath
@@ -88,10 +92,24 @@ public class ClassPathFinder {
} catch (URISyntaxException e) {
continue;
}
File entry = new File(entryURI) ;
Vector<String> results = checkEntries(entry.list(), entry, "");
if (results != null ) {
matches.addAll(results);
File entry = new File(entryURI);
if (entry.isFile() && entry.toString().endsWith(".jar")) {
try {
ZipInputStream zip = new ZipInputStream(new FileInputStream(entry));
for (ZipEntry zipEntry = zip.getNextEntry(); zipEntry != null; zipEntry = zip.getNextEntry()) {
boolean doesMatch = patternMatcher.match(new HashMap<String, String>(), zipEntry.getName(), compiledPattern);
if (doesMatch) {
matches.add(zipEntry.getName());
}
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
Vector<String> results = checkEntries(entry.list(), entry, "");
if (results != null) {
matches.addAll(results);
}
}
}
return matches;
@@ -31,8 +31,6 @@ import java.util.*;
*/
public class TextParseUtil {
private static final int MAX_RECURSION = 1;
/**
* Converts all instances of ${...}, and %{...} in <code>expression</code> to the value returned
* by a call to {@link ValueStack#findValue(java.lang.String)}. If an item cannot
@@ -108,7 +106,7 @@ public class TextParseUtil {
* @return Converted object from variable translation.
*/
public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator) {
return translateVariables(new char[]{open} , expression, stack, asType, evaluator, MAX_RECURSION);
return translateVariables(new char[]{open} , expression, stack, asType, evaluator, TextParser.DEFAULT_LOOP_COUNT);
}
/**
@@ -122,7 +120,7 @@ public class TextParseUtil {
* @return Converted object from variable translation.
*/
public static Object translateVariables(char[] openChars, String expression, ValueStack stack, Class asType, ParsedValueEvaluator evaluator) {
return translateVariables(openChars, expression, stack, asType, evaluator, MAX_RECURSION);
return translateVariables(openChars, expression, stack, asType, evaluator, TextParser.DEFAULT_LOOP_COUNT);
}
/**
@@ -178,7 +176,7 @@ public class TextParseUtil {
* @return converted objects
*/
public static Collection<String> translateVariablesCollection(String expression, ValueStack stack, boolean excludeEmptyElements, ParsedValueEvaluator evaluator) {
return translateVariablesCollection(new char[]{'$', '%'}, expression, stack, excludeEmptyElements, evaluator, MAX_RECURSION);
return translateVariablesCollection(new char[]{'$', '%'}, expression, stack, excludeEmptyElements, evaluator, TextParser.DEFAULT_LOOP_COUNT);
}
/**
@@ -6,6 +6,8 @@ package com.opensymphony.xwork2.util;
*/
public interface TextParser {
int DEFAULT_LOOP_COUNT = 1;
Object evaluate(char[] openChars, String expression, TextParseUtil.ParsedValueEvaluator evaluator, int maxLoopCount);
}
@@ -129,15 +129,15 @@ import org.apache.logging.log4j.Logger;
*/
public class ValidationInterceptor extends MethodFilterInterceptor {
private static final Logger LOG = LogManager.getLogger(ValidationInterceptor.class);
private final static String VALIDATE_PREFIX = "validate";
private final static String ALT_VALIDATE_PREFIX = "validateDo";
private boolean validateAnnotatedMethodOnly;
private ActionValidatorManager actionValidatorManager;
private static final Logger LOG = LogManager.getLogger(ValidationInterceptor.class);
private final static String VALIDATE_PREFIX = "validate";
private final static String ALT_VALIDATE_PREFIX = "validateDo";
private boolean alwaysInvokeValidate = true;
private boolean programmatic = true;
private boolean declarative = true;
@@ -212,8 +212,8 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
String context = this.getValidationContext(proxy);
String method = proxy.getMethod();
if (log.isDebugEnabled()) {
log.debug("Validating {}/{} with method {}.", invocation.getProxy().getNamespace(), invocation.getProxy().getActionName(), method);
if (LOG.isDebugEnabled()) {
LOG.debug("Validating {}/{} with method {}.", invocation.getProxy().getNamespace(), invocation.getProxy().getActionName(), method);
}
@@ -23,7 +23,7 @@ package com.opensymphony.xwork2.validator.validators;
* The regular expression used to validate that the string is an email address is:
*
* <pre>
* \\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2}|aero|arpa|asia|biz|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|nato|net|org|pro|tel|travel|xxx|tech|cat)$\\b
* \\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,6})$\\b
* </pre>
*
* You can also specify expression, caseSensitive and trim params as a OGNL expression, see the example below.
@@ -78,9 +78,7 @@ package com.opensymphony.xwork2.validator.validators;
*/
public class EmailValidator extends RegexFieldValidator {
// see XW-371
public static final String EMAIL_ADDRESS_PATTERN =
"\\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2}|aero|arpa|asia|biz|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|nato|net|org|pro|tel|travel|xxx|tech|cat)$\\b";
public static final String EMAIL_ADDRESS_PATTERN = "\\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,6})$\\b";
public EmailValidator() {
setRegex(EMAIL_ADDRESS_PATTERN);
@@ -33,7 +33,7 @@ public abstract class AbstractMultiPartRequest implements MultiPartRequest {
/**
* Specifies the maximum size of the entire request.
*/
protected int maxSize;
protected long maxSize;
protected boolean maxSizeProvided;
/**
@@ -67,7 +67,7 @@ public abstract class AbstractMultiPartRequest implements MultiPartRequest {
@Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
public void setMaxSize(String maxSize) {
this.maxSizeProvided = true;
this.maxSize = Integer.parseInt(maxSize);
this.maxSize = Long.parseLong(maxSize);
}
/**
@@ -1,7 +1,7 @@
package org.apache.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.dispatcher.Parameter;
@@ -12,7 +12,7 @@ import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
public class DateTextFieldInterceptor implements Interceptor {
public class DateTextFieldInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(DateTextFieldInterceptor.class);
@@ -56,12 +56,6 @@ public class DateTextFieldInterceptor implements Interceptor {
return values();
}
}
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation ai) throws Exception {
HttpParameters parameters = ai.getInvocationContext().getParameters();
@@ -38,59 +38,8 @@ import java.util.Locale;
import java.util.Map;
/**
* <!-- START SNIPPET: description -->
* <p>
* An interceptor that handles setting the locale specified in a session as the locale for the current action request.
* In addition, this interceptor will look for a specific HTTP request parameter and set the locale to whatever value is
* provided, it also looks for specific cookie to read locale from. This means that this interceptor can be used to allow
* for your application to dynamically change the locale for the user's session or, alternatively, only for the current
* request (since XWork 2.1.3).
* This is very useful for applications that require multi-lingual support and want the user to
* be able to set his or her language preference at any point. The locale parameter is removed during the execution of
* this interceptor, ensuring that properties aren't set on an action (such as request_locale) that have no typical
* corresponding setter in your action.
* </p>
*
* <p>
* For example, using the default parameter name, a request to <b>foo.action?request_locale=en_US</b>, then the
* locale for US English is saved in the user's session and will be used for all future requests.
* If there is no locale set (for example with the first visit), the interceptor uses the browser locale.
* </p>
* <!-- END SNIPPET: description -->
*
* <!-- START SNIPPET: parameters -->
*
* <ul>
*
* <li>parameterName (optional) - the name of the HTTP request parameter that dictates the locale to switch to and save
* in the session. By default this is <b>request_locale</b></li>
*
* <li>requestCookieParameterName (optional) - the name of the HTTP request parameter that dictates the locale to switch to
* and save in a cookien. By default this is <b>request_cookie_locale</b></li>
*
* <li>requestOnlyParameterName (optional) - the name of the HTTP request parameter that dictates the locale to switch to
* for the current request only, without saving it in the session. By default this is <b>request_only_locale</b></li>
*
* <li>attributeName (optional) - the name of the session key to store the selected locale. By default this is
* <b>WW_TRANS_I18N_LOCALE</b></li>
*
* <li>storage (optional) - the name of storage location, it can be <b>none</b>, <b>session</b> or <b>cookie</b>.
* By default this is <b>session</b></li>
*
* </ul>
*
* <!-- END SNIPPET: parameters -->
*
* <!-- START SNIPPET: example -->
* &lt;interceptor name="i18nCookie" class="org.apache.struts2.interceptor.I18nInterceptor"/&gt;
*
* &lt;action name="someAction" class="com.examples.SomeAction"&gt;
* &lt;interceptor-ref name="i18nCookie"/&gt;
* &lt;interceptor-ref name="basicStack"/&gt;
* &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
* &lt;/action&gt;
* <!-- END SNIPPET: example -->
*/
*/
public class I18nInterceptor extends AbstractInterceptor {
private static final Logger LOG = LogManager.getLogger(I18nInterceptor.class);
@@ -135,7 +84,7 @@ public class I18nInterceptor extends AbstractInterceptor {
try {
this.storage = Storage.valueOf(storageName.toUpperCase());
} catch (IllegalArgumentException e) {
LOG.warn(new ParameterizedMessage("Wrong storage name [{{}] was defined, falling back to {}", storageName, Storage.SESSION), e);
LOG.warn(new ParameterizedMessage("Wrong storage name [{}] was defined, falling back to {}", storageName, Storage.SESSION), e);
this.storage = Storage.SESSION;
}
}
@@ -148,107 +97,53 @@ public class I18nInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
LOG.debug("Intercept '{}/{}'",
invocation.getProxy().getNamespace(), invocation.getProxy().getActionName());
LOG.debug("Intercept '{}/{}'", invocation.getProxy().getNamespace(), invocation.getProxy().getActionName());
LocaleHandler localeHandler = getLocaleHandler(invocation);
Locale locale = localeHandler.find();
if (locale == null) {
locale = localeHandler.read(invocation);
}
if (localeHandler.shouldStore()) {
locale = localeHandler.store(invocation, locale);
}
RequestOnlyLocaleFinder localeFinder = getLocaleFinder(invocation);
Locale locale = getLocaleFromParam(localeFinder.find());
locale = storeLocale(invocation, locale);
useLocale(invocation, locale);
if (LOG.isDebugEnabled()) {
LOG.debug("Before action invocation Locale={}", invocation.getStack().findValue("locale"));
}
final String result = invocation.invoke();
if (LOG.isDebugEnabled()) {
LOG.debug("After action invocation Locale={}", invocation.getStack().findValue("locale"));
}
return result;
}
protected RequestOnlyLocaleFinder getLocaleFinder(ActionInvocation invocation) {
RequestOnlyLocaleFinder localeFinder;
if (this.storage == Storage.COOKIE) {
localeFinder = new CookieLocaleFinder(invocation);
} else if (this.storage == Storage.SESSION) {
localeFinder = new SessionLocaleFinder(invocation);
} else {
localeFinder = new RequestOnlyLocaleFinder(invocation);
}
LOG.debug("Using LocaleFinder implementation {}", localeFinder.getClass().getName());
return localeFinder;
}
/**
* Store the locale to the chosen storage, like f. e. the session
*
* @param invocation the action invocation
* @param locale the locale to store
*
* @return the locale
*/
protected Locale storeLocale(ActionInvocation invocation, Locale locale) {
if (locale == null) {
storage = Storage.NONE;
locale = readStoredLocale(invocation);
}
if (storage == Storage.COOKIE) {
storeLocaleInCookie(invocation, locale);
}
if (Storage.SESSION == storage) {
storeLocaleInSession(invocation, locale);
}
return locale;
}
protected void storeLocaleInCookie(ActionInvocation ignore, Locale locale) {
HttpServletResponse response = ServletActionContext.getResponse();
Cookie cookie = new Cookie(DEFAULT_COOKIE_ATTRIBUTE, locale.toString());
cookie.setMaxAge(1209600); // two weeks
response.addCookie(cookie);
}
protected void storeLocaleInSession(ActionInvocation invocation, Locale locale) {
//save it in session
Map<String, Object> session = invocation.getInvocationContext().getSession();
if (session != null) {
synchronized (session) {
session.put(attributeName, locale);
try {
return invocation.invoke();
} finally {
if (LOG.isDebugEnabled()) {
LOG.debug("After action invocation Locale={}", invocation.getStack().findValue("locale"));
}
}
}
/**
* Reads the locale from the session, and if not found from the
* current invocation (=browser)
* Override this method to use your own implementation of {@link LocaleHandler}
*
* @param invocation the current invocation
* @return the read locale
* @param invocation current action invocation context
* @return instance of {@link LocaleHandler}
*/
protected Locale readStoredLocale(ActionInvocation invocation) {
Locale locale = readStoredLocalFromSession(invocation);
if (locale != null) {
LOG.debug("Found stored Locale {} in session, using it!", locale);
return locale;
protected LocaleHandler getLocaleHandler(ActionInvocation invocation) {
LocaleHandler localeHandler;
if (this.storage == Storage.COOKIE) {
localeHandler = new CookieLocaleHandler(invocation);
} else if (this.storage == Storage.SESSION) {
localeHandler = new SessionLocaleHandler(invocation);
} else {
localeHandler = new RequestOnlyLocaleHandler(invocation);
}
Locale cookie = readStoredLocaleFromCookie(invocation);
if (cookie != null) {
LOG.debug("Found stored Locale {} in cookies, using it!", locale);
return cookie;
}
LOG.debug("Neither locale was in session nor in cookies, searching current Invocation context");
return readStoredLocalFromCurrentInvocation(invocation);
LOG.debug("Using LocaleFinder implementation {}", localeHandler.getClass().getName());
return localeHandler;
}
/**
@@ -270,7 +165,7 @@ public class I18nInterceptor extends AbstractInterceptor {
}
}
if (locale != null) {
LOG.debug("Applied request locale: {}", locale);
LOG.debug("Found locale: {}", locale);
}
}
@@ -283,45 +178,8 @@ public class I18nInterceptor extends AbstractInterceptor {
return locale;
}
protected Locale readStoredLocalFromSession(ActionInvocation invocation) {
// check session for saved locale
Map<String, Object> session = invocation.getInvocationContext().getSession();
if (session != null) {
synchronized (session) {
Object sessionLocale = session.get(attributeName);
if (sessionLocale != null && sessionLocale instanceof Locale) {
Locale locale = (Locale) sessionLocale;
LOG.debug("Applied session locale: {}", locale);
return locale;
}
}
}
return null;
}
protected Locale readStoredLocaleFromCookie(ActionInvocation ignore) {
Cookie[] cookies = ServletActionContext.getRequest().getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (DEFAULT_COOKIE_ATTRIBUTE.equals(cookie.getName())) {
return getLocaleFromParam(cookie.getValue());
}
}
}
return null;
}
protected Locale readStoredLocalFromCurrentInvocation(ActionInvocation invocation) {
// no overriding locale definition found, stay with current invocation (=browser) locale
Locale locale = invocation.getInvocationContext().getLocale();
if (locale != null) {
LOG.debug("Applied invocation context locale: {}", locale);
}
return locale;
}
protected Parameter findLocaleParameter(HttpParameters params, String parameterName) {
protected Parameter findLocaleParameter(ActionInvocation invocation, String parameterName) {
HttpParameters params = invocation.getInvocationContext().getParameters();
Parameter requestedLocale = params.get(parameterName);
params.remove(parameterName);
if (requestedLocale.isDefined()) {
@@ -340,75 +198,182 @@ public class I18nInterceptor extends AbstractInterceptor {
invocation.getInvocationContext().setLocale(locale);
}
protected class RequestOnlyLocaleFinder {
/**
* Uses to handle reading/storing Locale from/in different locations
*/
protected interface LocaleHandler {
Locale find();
Locale read(ActionInvocation invocation);
Locale store(ActionInvocation invocation, Locale locale);
boolean shouldStore();
}
protected class RequestOnlyLocaleHandler implements LocaleHandler {
protected ActionInvocation actionInvocation = null;
protected boolean shouldStore = true;
protected RequestOnlyLocaleFinder(ActionInvocation invocation) {
protected RequestOnlyLocaleHandler(ActionInvocation invocation) {
actionInvocation = invocation;
}
public String find() {
HttpParameters params = actionInvocation.getInvocationContext().getParameters();
public Locale find() {
LOG.debug("Searching locale in request under parameter {}", requestOnlyParameterName);
Parameter requestedLocale = findLocaleParameter(params, requestOnlyParameterName);
Parameter requestedLocale = findLocaleParameter(actionInvocation, requestOnlyParameterName);
if (requestedLocale.isDefined()) {
storage = Storage.NONE;
return requestedLocale.getValue();
return getLocaleFromParam(requestedLocale.getValue());
}
return null;
}
@Override
public Locale store(ActionInvocation invocation, Locale locale) {
return locale;
}
@Override
public Locale read(ActionInvocation invocation) {
LOG.debug("Searching current Invocation context");
// no overriding locale definition found, stay with current invocation (=browser) locale
Locale locale = invocation.getInvocationContext().getLocale();
if (locale != null) {
LOG.debug("Applied invocation context locale: {}", locale);
}
return locale;
}
@Override
public boolean shouldStore() {
return shouldStore;
}
}
protected class SessionLocaleFinder extends RequestOnlyLocaleFinder {
protected class SessionLocaleHandler extends RequestOnlyLocaleHandler {
protected SessionLocaleFinder(ActionInvocation invocation) {
protected SessionLocaleHandler(ActionInvocation invocation) {
super(invocation);
}
public String find() {
String requestOnlyLocale = super.find();
public Locale find() {
Locale requestOnlyLocale = super.find();
if (requestOnlyLocale != null) {
LOG.debug("Found locale under request only param, it won't be stored in session!");
shouldStore = false;
return requestOnlyLocale;
}
HttpParameters params = actionInvocation.getInvocationContext().getParameters();
Parameter requestedLocale = findLocaleParameter(params, parameterName);
LOG.debug("Searching locale in request under parameter {}", parameterName);
Parameter requestedLocale = findLocaleParameter(actionInvocation, parameterName);
if (requestedLocale.isDefined()) {
return requestedLocale.getValue();
return getLocaleFromParam(requestedLocale.getValue());
}
return requestedLocale.getValue();
return null;
}
@Override
public Locale store(ActionInvocation invocation, Locale locale) {
//save it in session
Map<String, Object> session = invocation.getInvocationContext().getSession();
if (session != null) {
String sessionId = ServletActionContext.getRequest().getSession().getId();
synchronized (sessionId.intern()) {
session.put(attributeName, locale);
}
}
return locale;
}
@Override
public Locale read(ActionInvocation invocation) {
Locale locale = null;
LOG.debug("Checks session for saved locale");
Map<String, Object> session = invocation.getInvocationContext().getSession();
if (session != null) {
String sessionId = ServletActionContext.getRequest().getSession().getId();
synchronized (sessionId.intern()) {
Object sessionLocale = session.get(attributeName);
if (sessionLocale != null && sessionLocale instanceof Locale) {
locale = (Locale) sessionLocale;
LOG.debug("Applied session locale: {}", locale);
}
}
}
if (locale == null) {
LOG.debug("No Locale defined in session, fetching from current request and it won't be stored in session!");
shouldStore = false;
locale = super.read(invocation);
} else {
LOG.debug("Found stored Locale {} in session, using it!", locale);
}
return locale;
}
}
protected class CookieLocaleFinder extends RequestOnlyLocaleFinder {
protected CookieLocaleFinder(ActionInvocation invocation) {
protected class CookieLocaleHandler extends RequestOnlyLocaleHandler {
protected CookieLocaleHandler(ActionInvocation invocation) {
super(invocation);
}
@Override
public String find() {
String requestOnlySessionLocale = super.find();
public Locale find() {
Locale requestOnlySessionLocale = super.find();
if (requestOnlySessionLocale != null) {
shouldStore = false;
return requestOnlySessionLocale;
}
HttpParameters params = actionInvocation.getInvocationContext().getParameters();
Parameter requestedLocale = findLocaleParameter(params, requestCookieParameterName);
LOG.debug("Searching locale in request under parameter {}", requestCookieParameterName);
Parameter requestedLocale = findLocaleParameter(actionInvocation, requestCookieParameterName);
if (requestedLocale.isDefined()) {
storage = Storage.COOKIE;
return requestedLocale.getValue();
return getLocaleFromParam(requestedLocale.getValue());
}
return null;
}
@Override
public Locale store(ActionInvocation invocation, Locale locale) {
HttpServletResponse response = ServletActionContext.getResponse();
Cookie cookie = new Cookie(attributeName, locale.toString());
cookie.setMaxAge(1209600); // two weeks
response.addCookie(cookie);
return locale;
}
@Override
public Locale read(ActionInvocation invocation) {
Locale locale = null;
Cookie[] cookies = ServletActionContext.getRequest().getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (attributeName.equals(cookie.getName())) {
locale = getLocaleFromParam(cookie.getValue());
}
}
}
if (locale == null) {
LOG.debug("No Locale defined in cookie, fetching from current request and it won't be stored!");
shouldStore = false;
locale = super.read(invocation);
} else {
LOG.debug("Found stored Locale {} in cookie, using it!", locale);
}
return locale;
}
}
}
@@ -203,7 +203,10 @@ public class MessageStoreInterceptor extends AbstractInterceptor {
before(invocation);
LOG.trace("Registering listener to store messages before result will be executed");
invocation.addPreResultListener(new MessageStorePreResultListener(this));
MessageStorePreResultListener preResultListener = createPreResultListener(invocation);
preResultListener.init(this);
invocation.addPreResultListener(preResultListener);
String result = invocation.invoke();
@@ -212,6 +215,10 @@ public class MessageStoreInterceptor extends AbstractInterceptor {
return result;
}
protected MessageStorePreResultListener createPreResultListener(ActionInvocation invocation) {
return new MessageStorePreResultListener();
}
/**
* Handle the retrieving of field errors / action messages / field errors, which is
* done before action invocation, and the <code>operationMode</code> is 'RETRIEVE'.
@@ -26,8 +26,7 @@ import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.result.ServletActionRedirectResult;
import org.apache.struts2.result.ServletRedirectResult;
import org.apache.struts2.result.Redirectable;
import java.util.Map;
@@ -36,26 +35,25 @@ import java.util.Map;
* just before result will be executed. It must be done that way as after result will be executed
* HttpSession cannot be modified (response was already sent to browser).
*/
class MessageStorePreResultListener implements PreResultListener {
public class MessageStorePreResultListener implements PreResultListener {
private static final Logger LOG = LogManager.getLogger(MessageStorePreResultListener.class);
private MessageStoreInterceptor interceptor;
protected MessageStoreInterceptor interceptor;
public MessageStorePreResultListener(MessageStoreInterceptor interceptor) {
public void init(MessageStoreInterceptor interceptor) {
this.interceptor = interceptor;
}
@Override
public void beforeResult(ActionInvocation invocation, String resultCode) {
boolean isCommitted = ServletActionContext.getResponse().isCommitted();
boolean isCommitted = isCommitted();
if (isCommitted) {
LOG.trace("Response was already committed, cannot store messages!");
return;
}
boolean isInvalidated = ServletActionContext.getRequest().getSession(false) == null;
boolean isInvalidated = isInvalidated();
if (isInvalidated) {
LOG.trace("Session was invalidated or never created, cannot store messages!");
return;
@@ -69,15 +67,7 @@ class MessageStorePreResultListener implements PreResultListener {
String reqOperationMode = interceptor.getRequestOperationMode(invocation);
boolean isRedirect = false;
try {
ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(resultCode);
if (resultConfig != null) {
isRedirect = ServletRedirectResult.class.isAssignableFrom(Class.forName(resultConfig.getClassName()));
}
} catch (Exception e) {
LOG.warn("Cannot read result!", e);
}
boolean isRedirect = isRedirect(invocation, resultCode);
if (MessageStoreInterceptor.STORE_MODE.equalsIgnoreCase(reqOperationMode) ||
MessageStoreInterceptor.STORE_MODE.equalsIgnoreCase(interceptor.getOperationModel()) ||
@@ -97,4 +87,26 @@ class MessageStorePreResultListener implements PreResultListener {
}
}
}
protected boolean isCommitted() {
return ServletActionContext.getResponse().isCommitted();
}
protected boolean isInvalidated() {
return ServletActionContext.getRequest().getSession(false) == null;
}
protected boolean isRedirect(ActionInvocation invocation, String resultCode) {
boolean isRedirect = false;
try {
ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(resultCode);
if (resultConfig != null) {
isRedirect = Redirectable.class.isAssignableFrom(Class.forName(resultConfig.getClassName()));
}
} catch (Exception e) {
LOG.warn("Cannot read result!", e);
}
return isRedirect;
}
}
@@ -26,6 +26,8 @@ import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.util.TokenHelper;
@@ -116,7 +118,7 @@ import javax.servlet.http.HttpSession;
*/
public class TokenInterceptor extends MethodFilterInterceptor {
private static final long serialVersionUID = -6680894220590585506L;
private static final Logger LOG = LogManager.getLogger(TokenInterceptor.class);
public static final String INVALID_TOKEN_CODE = "invalid.token";
@@ -135,7 +137,7 @@ public class TokenInterceptor extends MethodFilterInterceptor {
*/
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
log.debug("Intercepting invocation to check for valid transaction token.");
LOG.debug("Intercepting invocation to check for valid transaction token.");
return handleToken(invocation);
}
@@ -143,7 +145,7 @@ public class TokenInterceptor extends MethodFilterInterceptor {
//see WW-2902: we need to use the real HttpSession here, as opposed to the map
//that wraps the session, because a new wrap is created on every request
HttpSession session = ServletActionContext.getRequest().getSession(true);
synchronized (session) {
synchronized (session.getId().intern()) {
if (!TokenHelper.validToken()) {
return handleInvalidToken(invocation);
}
@@ -165,7 +167,7 @@ public class TokenInterceptor extends MethodFilterInterceptor {
if (action instanceof ValidationAware) {
((ValidationAware) action).addActionError(errorMessage);
} else {
log.warn(errorMessage);
LOG.warn(errorMessage);
}
return INVALID_TOKEN_CODE;
@@ -22,10 +22,13 @@
package org.apache.struts2.interceptor.validation;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.AnnotationUtils;
import com.opensymphony.xwork2.validator.ValidationInterceptor;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import java.lang.reflect.Method;
@@ -38,19 +41,20 @@ import java.util.Collection;
*/
public class AnnotationValidationInterceptor extends ValidationInterceptor {
/** Auto-generated serialization id */
private static final long serialVersionUID = 1813272797367431184L;
private static final Logger LOG = LogManager.getLogger(AnnotationValidationInterceptor.class);
protected String doIntercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action != null) {
Method method = getActionMethod(action.getClass(), invocation.getProxy().getMethod());
Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(), SkipValidation.class);
if (annotatedMethods.contains(method))
return invocation.invoke();
//check if method overwites an annotated method
Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(), SkipValidation.class);
if (annotatedMethods.contains(method)) {
return invocation.invoke();
}
LOG.debug("Check if method overrides an annotated method");
Class clazz = action.getClass().getSuperclass();
while (clazz != null) {
annotatedMethods = AnnotationUtils.getAnnotatedMethods(clazz, SkipValidation.class);
@@ -69,9 +73,12 @@ public class AnnotationValidationInterceptor extends ValidationInterceptor {
return super.doIntercept(invocation);
}
// FIXME: This is copied from DefaultActionInvocation but should be exposed through the interface
protected Method getActionMethod(Class<?> actionClass, String methodName) throws NoSuchMethodException {
return actionClass.getMethod(methodName);
protected Method getActionMethod(Class<?> actionClass, String methodName) {
try {
return actionClass.getMethod(methodName);
} catch (NoSuchMethodException e) {
throw new ConfigurationException("Wrong method was defined as an action method: " + methodName, e);
}
}
}
@@ -0,0 +1,8 @@
package org.apache.struts2.result;
/**
* Marking interface for results which perform browser redirection
*/
public interface Redirectable {
}
@@ -123,7 +123,7 @@ import java.util.List;
*
* @see ActionMapper
*/
public class ServletActionRedirectResult extends ServletRedirectResult implements ReflectionExceptionHandler {
public class ServletActionRedirectResult extends ServletRedirectResult implements ReflectionExceptionHandler, Redirectable {
private static final long serialVersionUID = -9042425229314584066L;
@@ -29,6 +29,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.views.util.UrlHelper;
import javax.servlet.RequestDispatcher;
@@ -142,14 +143,17 @@ public class ServletDispatcherResult extends StrutsResultSupport {
// see WW-2120
if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
Map<String, Object> parameters = getParameters(invocation);
HttpParameters parameters = getParameters(invocation);
Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
if (queryParams != null && !queryParams.isEmpty())
parameters.putAll(queryParams);
if (queryParams != null && !queryParams.isEmpty()) {
parameters = HttpParameters.create(queryParams).withParent(parameters).build();
invocation.getInvocationContext().setParameters(parameters);
}
}
// if the view doesn't exist, let's do a 404
if (dispatcher == null) {
LOG.warn("Location {} not found!", finalLocation);
response.sendError(404, "result '" + finalLocation + "' not found");
return;
}
@@ -171,9 +175,8 @@ public class ServletDispatcherResult extends StrutsResultSupport {
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> getParameters(ActionInvocation invocation) {
return (Map<String, Object>) invocation.getInvocationContext().getContextMap().get("parameters");
protected HttpParameters getParameters(ActionInvocation invocation) {
return invocation.getInvocationContext().getParameters();
}
}
@@ -98,7 +98,7 @@ import static javax.servlet.http.HttpServletResponse.SC_FOUND;
* </pre>
*
*/
public class ServletRedirectResult extends StrutsResultSupport implements ReflectionExceptionHandler {
public class ServletRedirectResult extends StrutsResultSupport implements ReflectionExceptionHandler, Redirectable {
private static final long serialVersionUID = 6316947346435301270L;
@@ -43,162 +43,8 @@ import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* <!-- START SNIPPET: description -->
*
* XSLTResult uses XSLT to transform an action object to XML. The recent version
* has been specifically modified to deal with Xalan flaws. When using Xalan you
* may notice that even though you have a very minimal stylesheet like this one
* <pre>
* &lt;xsl:template match="/result"&gt;
* &lt;result/&gt;
* &lt;/xsl:template&gt;</pre>
*
* <p>
* Xalan would still iterate through every property of your action and all
* its descendants.
* </p>
*
* <p>
* If you had double-linked objects, Xalan would work forever analysing an
* infinite object tree. Even if your stylesheet was not constructed to process
* them all. It's because the current Xalan eagerly and extensively converts
* everything to its internal DTM model before further processing.
* </p>
*
* <p>
* That's why there's a loop eliminator added that works by indexing every
* object-property combination during processing. If it notices that some
* object's property was already walked through, it doesn't go any deeper.
* Say you have two objects, x and y, with the following properties set
* (pseudocode):
* </p>
* <pre>
* x.y = y;
* and
* y.x = x;
* action.x=x;</pre>
*
* <p>
* Due to that modification, the resulting XML document based on x would be:
* </p>
*
* <pre>
* &lt;result&gt;
* &lt;x&gt;
* &lt;y/&gt;
* &lt;/x&gt;
* &lt;/result&gt;</pre>
*
* <p>
* Without it there would be endless x/y/x/y/x/y/... elements.
* </p>
*
* <p>
* The XSLTResult code tries also to deal with the fact that DTM model is built
* in a manner that children are processed before siblings. The result is that if
* there is object x that is both set in action's x property, and very deeply
* under action's a property then it would only appear under a, not under x.
* That's not what we expect, and that's why XSLTResult allows objects to repeat
* in various places to some extent.
* </p>
*
* <p>
* Sometimes the object mesh is still very dense and you may notice that even
* though you have a relatively simple stylesheet, execution takes a tremendous
* amount of time. To help you to deal with that obstacle of Xalan, you may
* attach regexp filters to elements paths (xpath).
* </p>
*
* <p>
* <b>Note:</b> In your .xsl file the root match must be named <tt>result</tt>.
* <br>This example will output the username by using <tt>getUsername</tt> on your
* action class:
* <pre>
* &lt;xsl:template match="result"&gt;
* &lt;html&gt;
* &lt;body&gt;
* Hello &lt;xsl:value-of select="username"/&gt; how are you?
* &lt;/body&gt;
* &lt;/html&gt;
* &lt;/xsl:template&gt;
* </pre>
*
* <p>
* In the following example the XSLT result would only walk through action's
* properties without their childs. It would also skip every property that has
* "hugeCollection" in their name. Element's path is first compared to
* excludingPattern - if it matches it's no longer processed. Then it is
* compared to matchingPattern and processed only if there's a match.
* </p>
*
* <!-- END SNIPPET: description -->
*
* <pre><!-- START SNIPPET: description.example -->
* &lt;result name="success" type="xslt"&gt;
* &lt;param name="location"&gt;foo.xslt&lt;/param&gt;
* &lt;param name="matchingPattern"&gt;^/result/[^/*]$&lt;/param&gt;
* &lt;param name="excludingPattern"&gt;.*(hugeCollection).*&lt;/param&gt;
* &lt;/result&gt;
* <!-- END SNIPPET: description.example --></pre>
*
* <p>
* In the following example the XSLT result would use the action's user property
* instead of the action as it's base document and walk through it's properties.
* The exposedValue uses an ognl expression to derive it's value.
* </p>
*
* <pre>
* &lt;result name="success" type="xslt"&gt;
* &lt;param name="location"&gt;foo.xslt&lt;/param&gt;
* &lt;param name="exposedValue"&gt;user$&lt;/param&gt;
* &lt;/result&gt;
* </pre>
* *
* <b>This result type takes the following parameters:</b>
*
* <!-- START SNIPPET: params -->
*
* <ul>
*
* <li><b>location (default)</b> - the location to go to after execution.</li>
* <li><b>encoding</b> - character encoding used in XML, default UTF-8.</li>
*
* <li><b>parse</b> - true by default. If set to false, the location param will
* not be parsed for Ognl expressions.</li>
*
* <!--
* <li><b>matchingPattern</b> - Pattern that matches only desired elements, by
* default it matches everything.</li>
*
* <li><b>excludingPattern</b> - Pattern that eliminates unwanted elements, by
* default it matches none.</li>
* -->
*
* </ul>
*
* <p>
* <code>struts.properties</code> related configuration:
* </p>
* <ul>
*
* <li><b>struts.xslt.nocache</b> - Defaults to false. If set to true, disables
* stylesheet caching. Good for development, bad for production.</li>
*
* </ul>
*
* <!-- END SNIPPET: params -->
* <p>
* <b>Example:</b>
* </p>
*
* <pre>
* <!-- START SNIPPET: example -->
* &lt;result name="success" type="xslt"&gt;foo.xslt&lt;/result&gt;
* <!-- END SNIPPET: example -->
* </pre>
*
* XSLTResult uses XSLT to transform an action object to XML.
*/
public class XSLTResult implements Result {
@@ -233,7 +79,7 @@ public class XSLTResult implements Result {
/** Indicates the property name patterns which should be excluded from the xml. */
private String excludingPattern;
/** Indicates the ognl expression respresenting the bean which is to be exposed as xml. */
/** Indicates the ognl expression representing the bean which is to be exposed as xml. */
private String exposedValue;
/** Indicates the status to return in the response */
@@ -258,8 +104,6 @@ public class XSLTResult implements Result {
}
public void setStylesheetLocation(String location) {
if (location == null)
throw new IllegalArgumentException("Null location");
this.stylesheetLocation = location;
}
@@ -306,12 +150,15 @@ public class XSLTResult implements Result {
long startTime = System.currentTimeMillis();
String location = getStylesheetLocation();
if (location == null) {
throw new IllegalArgumentException("Parameter 'stylesheetLocation' cannot be null!");
}
if (parse) {
ValueStack stack = ActionContext.getContext().getValueStack();
location = TextParseUtil.translateVariables(location, stack);
}
try {
HttpServletResponse response = ServletActionContext.getResponse();
response.setStatus(status);
@@ -324,17 +171,20 @@ public class XSLTResult implements Result {
if (location != null) {
templates = getTemplates(location);
transformer = templates.newTransformer();
} else
} else {
transformer = TransformerFactory.newInstance().newTransformer();
}
transformer.setURIResolver(getURIResolver());
transformer.setErrorListener(buildErrorListener());
String mimeType;
if (templates == null)
if (templates == null) {
mimeType = "text/xml"; // no stylesheet, raw xml
else
} else {
mimeType = templates.getOutputProperties().getProperty(OutputKeys.MEDIA_TYPE);
}
if (mimeType == null) {
// guess (this is a servlet, so text/html might be the best guess)
mimeType = "text/html";
@@ -383,8 +233,9 @@ public class XSLTResult implements Result {
}
protected AdapterFactory getAdapterFactory() {
if (adapterFactory == null)
if (adapterFactory == null) {
adapterFactory = new AdapterFactory();
}
return adapterFactory;
}
@@ -397,8 +248,7 @@ public class XSLTResult implements Result {
* function. The default is an instance of ServletURIResolver, which operates relative to the servlet context.
*/
protected URIResolver getURIResolver() {
return new ServletURIResolver(
ServletActionContext.getServletContext());
return new ServletURIResolver(ServletActionContext.getServletContext());
}
protected Templates getTemplates(final String path) throws TransformerException, IOException {
@@ -428,8 +278,7 @@ public class XSLTResult implements Result {
return templates;
}
protected Source getDOMSourceForStack(Object value)
throws IllegalAccessException, InstantiationException {
protected Source getDOMSourceForStack(Object value) throws IllegalAccessException, InstantiationException {
return new DOMSource(getAdapterFactory().adaptDocument("result", value) );
}
}
@@ -31,7 +31,7 @@ struts.messages.invalid.file=Could not find a Filename for {0}. Verify that a va
struts.messages.invalid.content.type=Could not find a Content-Type for {0}. Verify that a valid file was submitted.
struts.messages.removing.file=Removing file {0} {1}
struts.messages.error.uploading=Error uploading: {0}
struts.messages.error.file.too.large=The file is to large to be uploaded: {0} "{1}" "{2}" {3}
struts.messages.error.file.too.large=The file is too large to be uploaded: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
+1 -1
View File
@@ -60,7 +60,7 @@
<!-- constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^(?!javax\.servlet\..+)(javax\..+)" / -->
<!-- this is simpler version of the above used with string comparison -->
<constant name="struts.excludedPackageNames" value="java.lang.,ognl,javax" />
<constant name="struts.excludedPackageNames" value="java.lang.,ognl,javax,freemarker.core,freemarker.template" />
<bean class="com.opensymphony.xwork2.ObjectFactory" name="struts"/>
<bean type="com.opensymphony.xwork2.factory.ResultFactory" name="struts" class="org.apache.struts2.factory.StrutsResultFactory" />
@@ -3,16 +3,20 @@ package com.opensymphony.xwork2;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork2.mock.MockActionProxy;
import com.opensymphony.xwork2.mock.MockContainer;
import com.opensymphony.xwork2.mock.MockInterceptor;
import com.opensymphony.xwork2.mock.MockLazyInterceptor;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import org.apache.struts2.dispatcher.HttpParameters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -298,6 +302,36 @@ public class DefaultActionInvocationTest extends XWorkTestCase {
assertEquals("success", result);
}
public void testInvokeWithLazyParams() throws Exception {
HashMap<String, Object> params = new HashMap<>();
params.put("blah", "this is blah");
HashMap<String, Object> extraContext = new HashMap<>();
extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
DefaultActionInvocation defaultActionInvocation = new DefaultActionInvocation(extraContext, true);
container.inject(defaultActionInvocation);
ActionProxy actionProxy = actionProxyFactory.createActionProxy( "", "LazyFoo", null, extraContext);
defaultActionInvocation.init(actionProxy);
defaultActionInvocation.invoke();
SimpleAction action = (SimpleAction) defaultActionInvocation.getAction();
assertEquals("this is blah", action.getBlah());
assertEquals("this is blah", action.getName());
}
@Override
protected void setUp() throws Exception {
super.setUp();
// ensure we're using the default configuration, not simple config
XmlConfigurationProvider configurationProvider = new XmlConfigurationProvider("xwork-sample.xml");
container.inject(configurationProvider);
loadConfigurationProviders(configurationProvider);
}
}
class DefaultActionInvocationTester extends DefaultActionInvocation {
@@ -41,6 +41,10 @@ public class XmlConfigurationProviderWildCardIncludeTest extends ConfigurationTe
assertNotNull(defaultTwoPackage);
assertEquals("default-2", defaultTwoPackage.getName());
PackageConfig defaultPackage = configuration.getPackageConfig("default");
assertNotNull(defaultPackage);
assertEquals("default", defaultPackage.getName());
configurationManager.addContainerProvider(provider);
configurationManager.reload();
@@ -55,21 +55,18 @@ public class TimerInterceptorTest extends XWorkTestCase {
public void testDefault() throws Exception {
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!execute] took "));
assertSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testNoNamespace() throws Exception {
ap.setNamespace(null);
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myAction!execute] took "));
assertSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testInputMethod() throws Exception {
ap.setMethod("input");
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!input] took "));
assertSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testTraceLevel() throws Exception {
@@ -89,35 +86,30 @@ public class TimerInterceptorTest extends XWorkTestCase {
interceptor.setLogLevel("info");
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!execute] took "));
assertSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testWarnLevel() throws Exception {
interceptor.setLogLevel("warn");
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!execute] took "));
assertSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testErrorLevel() throws Exception {
interceptor.setLogLevel("error");
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!execute] took "));
assertSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testFatalLevel() throws Exception {
interceptor.setLogLevel("fatal");
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!execute] took "));
assertSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testLogCategory() throws Exception {
interceptor.setLogCategory("com.mycompany.myapp.actiontiming");
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!execute] took "));
assertNotSame(interceptor.logger, TimerInterceptor.LOG);
}
public void testLogCategoryLevel() throws Exception {
@@ -125,7 +117,6 @@ public class TimerInterceptorTest extends XWorkTestCase {
interceptor.setLogLevel("error");
interceptor.intercept(mai);
assertTrue(interceptor.message.startsWith("Executed action [myApp/myAction!execute] took "));
assertNotSame(interceptor.logger, TimerInterceptor.LOG);
assertEquals("com.mycompany.myapp.actiontiming", interceptor.getLogCategory());
}
@@ -0,0 +1,39 @@
/*
* Copyright 2002-2006,2009 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.opensymphony.xwork2.mock;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.SimpleAction;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.WithLazyParams;
import org.junit.Assert;
public class MockLazyInterceptor extends AbstractInterceptor implements WithLazyParams {
private String foo = "";
public void setFoo(String foo) {
this.foo = foo;
}
public String intercept(ActionInvocation invocation) throws Exception {
if (invocation.getAction() instanceof SimpleAction) {
((SimpleAction) invocation.getAction()).setName(foo);
}
return invocation.invoke();
}
}
@@ -47,6 +47,7 @@ public class EmailValidatorTest extends XWorkTestCase {
assertTrue(verifyEmailValidity("Ferda+Mravenec@yaHoo.CoM"));
assertTrue(verifyEmailValidity("user@domainname.tech"));
assertTrue(verifyEmailValidity("Ferda+Mravenec@yaHoo.cat"));
assertTrue(verifyEmailValidity("user@domainname.swiss"));
assertFalse(verifyEmailValidity("tm_jee#marry@yahoo.co.uk"));
assertFalse(verifyEmailValidity("tm_jee@ yahoo.co.uk"));
@@ -207,7 +207,7 @@ public class FileUploadInterceptorTest extends StrutsInternalTestCase {
assertEquals(1, errors.size());
String msg = (String) errors.get(0);
// the error message should contain at least this test
assertTrue(msg.startsWith("The file is to large to be uploaded"));
assertTrue(msg.startsWith("The file is too large to be uploaded"));
assertTrue(msg.indexOf("inputName") > 0);
assertTrue(msg.indexOf("log4j2.xml") > 0);
}
@@ -54,7 +54,8 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
// when
MessageStoreInterceptor msi = new MessageStoreInterceptor();
MessageStorePreResultListener listener = new MessageStorePreResultListener(msi);
MessageStorePreResultListener listener = new MessageStorePreResultListener();
listener.init(msi);
listener.beforeResult(mockActionInvocation, Action.SUCCESS);
// then
@@ -86,7 +87,8 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
// when
MessageStoreInterceptor msi = new MessageStoreInterceptor();
MessageStorePreResultListener listener = new MessageStorePreResultListener(msi);
MessageStorePreResultListener listener = new MessageStorePreResultListener();
listener.init(msi);
listener.beforeResult(mockActionInvocation, Action.SUCCESS);
// then
@@ -98,7 +100,8 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
MessageStoreInterceptor interceptor = new MessageStoreInterceptor();
interceptor.setOperationMode(MessageStoreInterceptor.AUTOMATIC_MODE);
MessageStorePreResultListener listener = new MessageStorePreResultListener(interceptor);
MessageStorePreResultListener listener = new MessageStorePreResultListener();
listener.init(interceptor);
Map sessionMap = new LinkedHashMap();
@@ -178,7 +181,8 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
interceptor.setAllowRequestParameterSwitch(true);
interceptor.setOperationMode(MessageStoreInterceptor.STORE_MODE);
MessageStorePreResultListener listener = new MessageStorePreResultListener(interceptor);
MessageStorePreResultListener listener = new MessageStorePreResultListener();
listener.init(interceptor);
Map sessionMap = new LinkedHashMap();
@@ -25,6 +25,9 @@ import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import ognl.Ognl;
import org.apache.struts2.ServletActionContext;
@@ -107,4 +110,46 @@ public class ServletDispatcherResultTest extends StrutsInternalTestCase implemen
requestMock.verify();
dispatcherMock.verify();
}
public void testWithParameter() {
ServletDispatcherResult view = container.inject(ServletDispatcherResult.class);
view.setLocation("foo.jsp?bar=1");
Mock dispatcherMock = new Mock(RequestDispatcher.class);
dispatcherMock.expect("forward", C.ANY_ARGS);
Mock requestMock = new Mock(HttpServletRequest.class);
requestMock.expectAndReturn("getAttribute", "struts.actiontag.invocation", null);
requestMock.expectAndReturn("getAttribute", "javax.servlet.include.servlet_path", null);
requestMock.expectAndReturn("getRequestDispatcher", C.args(C.eq("foo.jsp?bar=1")), dispatcherMock.proxy());
requestMock.expect("setAttribute", C.ANY_ARGS); // this is a bad mock, but it works
requestMock.expect("setAttribute", C.ANY_ARGS); // this is a bad mock, but it works
requestMock.matchAndReturn("getRequestURI", "foo.jsp");
Mock responseMock = new Mock(HttpServletResponse.class);
responseMock.expectAndReturn("isCommitted", Boolean.FALSE);
ActionContext ac = new ActionContext(Ognl.createDefaultContext(null));
ac.setContainer(container);
ActionContext.setContext(ac);
ServletActionContext.setRequest((HttpServletRequest) requestMock.proxy());
ServletActionContext.setResponse((HttpServletResponse) responseMock.proxy());
MockActionInvocation mockActionInvocation = new MockActionInvocation();
mockActionInvocation.setInvocationContext(ac);
mockActionInvocation.setStack(container.getInstance(ValueStackFactory.class).createValueStack());
try {
view.execute(mockActionInvocation);
} catch (Exception e) {
e.printStackTrace();
fail();
}
assertTrue(mockActionInvocation.getInvocationContext().getParameters().contains("bar"));
assertEquals("1", mockActionInvocation.getInvocationContext().getParameters().get("bar").getValue());
dispatcherMock.verify();
requestMock.verify();
dispatcherMock.verify();
}
}
@@ -35,6 +35,7 @@ import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@@ -82,6 +83,22 @@ public class XSLTResultTest extends StrutsInternalTestCase {
assertTrue(out.indexOf("<result xmlns=\"http://www.w3.org/TR/xhtml1/strict\"") > -1);
}
public void testSimpleTransform5() throws Exception {
result.setParse(false);
result.setStylesheetLocation("XSLTResultTest6.xsl");
result.execute(mai);
String out = response.getContentAsString();
assertTrue(out.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"));
assertTrue(out.contains("<title>WebWork in Action</title>"));
assertTrue(out.contains("<author>Patrick and Jason</author>"));
assertTrue(out.contains("<editions><edition value=\"I\">I</edition><edition value=\"IV\">IV</edition></editions>"));
assertTrue(out.contains("<book><title/><author/><editions/></book>"));
assertTrue(out.contains("<title>XWork not in Action</title>"));
assertTrue(out.contains("<author>Superman</author>"));
assertTrue(out.contains("<editions><edition value=\"1234\">1234</edition><edition value=\"345\">345</edition><edition value=\"6667\">6667</edition></editions>"));
}
public void testSimpleTransformParse() throws Exception {
result.setParse(true);
result.setStylesheetLocation("${top.myLocation}");
@@ -277,9 +294,9 @@ public class XSLTResultTest extends StrutsInternalTestCase {
public List getBooks() {
List list = new ArrayList();
list.add(new Book("WebWork in Action", "Patrick and Jason"));
list.add(new Book("WebWork in Action", "Patrick and Jason", Arrays.asList("I", "IV")));
list.add(null);
list.add(new Book("XWork not in Action", "Superman"));
list.add(new Book("XWork not in Action", "Superman", Arrays.asList("1234", "345", "6667")));
return list;
}
@@ -289,10 +306,12 @@ public class XSLTResultTest extends StrutsInternalTestCase {
private String title;
private String author;
private List<String> editions;
public Book(String title, String author) {
public Book(String title, String author, List<String> editions) {
this.title = title;
this.author = author;
this.editions = editions;
}
public String getTitle() {
@@ -302,5 +321,9 @@ public class XSLTResultTest extends StrutsInternalTestCase {
public String getAuthor() {
return author;
}
public List<String> getEditions() {
return editions;
}
}
}
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* 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.
*/
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" />
<xsl:template match="result">
<books>
<xsl:for-each select="books/item">
<book>
<title><xsl:value-of select="title"/></title>
<author><xsl:value-of select="author"/></author>
<editions>
<xsl:for-each select="editions/item">
<edition><xsl:attribute name="value"><xsl:value-of select="."/></xsl:attribute><xsl:value-of select="."/></edition>
</xsl:for-each>
</editions>
</book>
</xsl:for-each>
</books>
</xsl:template>
</xsl:stylesheet>
@@ -6,5 +6,7 @@
<xwork>
<include file="xwork-test-beans.xml" />
<include file="com/opensymphony/xwork2/config/providers/xwork-test-wildcard-*.xml" />
<!-- config file defined inside xwork-jar.jar -->
<include file="xwork-jar.xml" />
<package name="default-wildcard" />
</xwork>
+1
View File
@@ -9,5 +9,6 @@
<Root level="info">
<AppenderRef ref="STDOUT"/>
</Root>
<Logger name="org.apache.struts2.views.xslt" level="debug"/>
</Loggers>
</Configuration>
+8
View File
@@ -26,6 +26,14 @@
<interceptor-ref name="defaultStack"/>
</action>
<action name="LazyFoo" class="com.opensymphony.xwork2.SimpleAction">
<result name="error" type="void" />
<interceptor-ref name="params"/>
<interceptor-ref name="lazy">
<param name="foo">${blah}</param>
</interceptor-ref>
</action>
<action name="WildCard" class="com.opensymphony.xwork2.SimpleAction">
<param name="foo">17</param>
<param name="bar">23</param>
@@ -19,10 +19,11 @@
<interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptor name="validation" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="test" class="com.opensymphony.xwork2.mock.MockInterceptor">
<param name="foo">expectedFoo</param>
</interceptor>
<interceptor name="lazy" class="com.opensymphony.xwork2.mock.MockLazyInterceptor"/>
<interceptor-stack name="defaultStack">
<interceptor-ref name="staticParams"/>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-cdi-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-config-browser-plugin</artifactId>
@@ -27,6 +27,8 @@ import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.validator.ActionValidatorManager;
import com.opensymphony.xwork2.validator.Validator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Collections;
import java.util.List;
@@ -37,7 +39,7 @@ import java.util.List;
*/
public class ListValidatorsAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LogManager.getLogger(ListValidatorsAction.class);
private String clazz;
private String context;
@@ -22,6 +22,8 @@
package org.apache.struts2.config_browser;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.net.URL;
@@ -35,6 +37,8 @@ import java.util.Properties;
*/
public class ShowJarsAction extends ActionNamesAction {
private static final Logger LOG = LogManager.getLogger(ShowJarsAction.class);
public List<Properties> getJarPoms() {
try {
return configHelper.getJarProperties();
@@ -52,8 +56,7 @@ public class ShowJarsAction extends ActionNamesAction {
try {
return ClassLoaderUtil.getResources("struts-plugin.xml", ShowJarsAction.class, false);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
LOG.error("Cannot load struts-plugin.xml", e);
}
return null;
}
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-convention-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-dwr-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-embeddedjsp-plugin</artifactId>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-gxp-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-jasperreports-plugin</artifactId>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-javatemplates-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-jfreechart-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-json-plugin</artifactId>
@@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.result.Redirectable;
import org.apache.struts2.result.ServletActionRedirectResult;
/**
@@ -24,7 +25,7 @@ import org.apache.struts2.result.ServletActionRedirectResult;
* </p>
*
*/
public class JSONActionRedirectResult extends ServletActionRedirectResult {
public class JSONActionRedirectResult extends ServletActionRedirectResult implements Redirectable {
private static final long serialVersionUID = 3107276294073879542L;
@@ -39,36 +39,8 @@ import java.util.List;
import java.util.Map;
/**
* <p>Serializes validation and action errors into JSON. This interceptor does not
* Serializes validation and action errors into JSON. This interceptor does not
* perform any validation, so it must follow the 'validation' interceptor on the stack.
* </p>
*
* <p>This stack (defined in struts-default.xml) shows how to use this interceptor with the
* 'validation' interceptor</p>
* <pre>
* &lt;interceptor-stack name="jsonValidationWorkflowStack"&gt;
* &lt;interceptor-ref name="basicStack"/&gt;
* &lt;interceptor-ref name="validation"&gt;
* &lt;param name="excludeMethods"&gt;input,back,cancel&lt;/param&gt;
* &lt;/interceptor-ref&gt;
* &lt;interceptor-ref name="jsonValidation"/&gt;
* &lt;interceptor-ref name="workflow"/&gt;
* &lt;/interceptor-stack&gt;
* </pre>
* <p>If 'validationFailedStatus' is set it will be used as the Response status
* when validation fails.</p>
*
* <p>If the request has a parameter 'struts.validateOnly' execution will return after
* validation (action won't be executed).</p>
*
* <p>If 'struts.validateOnly' is set to false you may want to use {@link JSONActionRedirectResult}.</p>
*
* <p>A request parameter named 'struts.enableJSONValidation' must be set to 'true' to
* use this interceptor</p>
*
* <p>If the request has a parameter 'struts.JSONValidation.set.encoding' set to true
* the character encoding will NOT be set on the response - is needed in portlet environment
* - for more details see issue WW-3237</p>
*/
public class JSONValidationInterceptor extends MethodFilterInterceptor {
@@ -80,16 +52,10 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
public static final String DEFAULT_ENCODING = "UTF-8";
private int validationFailedStatus = -1;
/**
* HTTP status that will be set in the response if validation fails
*
* @param validationFailedStatus validation failed status
*/
public void setValidationFailedStatus(int validationFailedStatus) {
this.validationFailedStatus = validationFailedStatus;
}
private int validationFailedStatus = HttpServletResponse.SC_BAD_REQUEST;
private String validateOnlyParam = VALIDATE_ONLY_PARAM;
private String validateJsonParam = VALIDATE_JSON_PARAM;
private String noEncodingSetParam = NO_ENCODING_SET_PARAM;
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
@@ -121,13 +87,9 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
private void setupEncoding(HttpServletResponse response, HttpServletRequest request) {
if (isSetEncoding(request)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Default encoding not set!");
}
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Setting up encoding to: [" + DEFAULT_ENCODING + "]!");
}
LOG.debug("Setting up encoding to: [{}]!", DEFAULT_ENCODING);
response.setCharacterEncoding(DEFAULT_ENCODING);
}
}
@@ -143,16 +105,16 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
return Action.NONE;
}
private boolean isJsonEnabled(HttpServletRequest request) {
return "true".equals(request.getParameter(VALIDATE_JSON_PARAM));
public boolean isJsonEnabled(HttpServletRequest request) {
return Boolean.parseBoolean(request.getParameter(validateJsonParam));
}
private boolean isValidateOnly(HttpServletRequest request) {
return "true".equals(request.getParameter(VALIDATE_ONLY_PARAM));
public boolean isValidateOnly(HttpServletRequest request) {
return Boolean.parseBoolean(request.getParameter(validateOnlyParam));
}
private boolean isSetEncoding(HttpServletRequest request) {
return "true".equals(request.getParameter(NO_ENCODING_SET_PARAM));
public boolean isSetEncoding(HttpServletRequest request) {
return Boolean.parseBoolean(request.getParameter(noEncodingSetParam));
}
/**
@@ -222,4 +184,40 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
sb.append("]");
return sb.toString();
}
/**
* HTTP status that will be set in the response if validation fails
*
* @param validationFailedStatus validation failed status
*/
public void setValidationFailedStatus(int validationFailedStatus) {
this.validationFailedStatus = validationFailedStatus;
}
/**
* Overrides 'struts.validateOnly' param name
*
* @param validateOnlyParam new param name
*/
public void setValidateOnlyParam(String validateOnlyParam) {
this.validateOnlyParam = validateOnlyParam;
}
/**
* Overrides 'struts.enableJSONValidation' param name
*
* @param validateJsonParam new param name
*/
public void setValidateJsonParam(String validateJsonParam) {
this.validateJsonParam = validateJsonParam;
}
/**
* Overrides 'struts.JSONValidation.no.encoding' param name
*
* @param noEncodingSetParam new param name
*/
public void setNoEncodingSetParam(String noEncodingSetParam) {
this.noEncodingSetParam = noEncodingSetParam;
}
}
@@ -63,7 +63,6 @@ public class JSONValidationInterceptorTest extends StrutsTestCase {
request.setParameterMap(parameters);
validationInterceptor.intercept(invocation);
interceptor.setValidationFailedStatus(HttpServletResponse.SC_BAD_REQUEST);
interceptor.intercept(invocation);
String json = stringWriter.toString();
@@ -131,6 +130,54 @@ public class JSONValidationInterceptorTest extends StrutsTestCase {
assertEquals("UTF-8", response.getCharacterEncoding());
}
public void testValidationSucceedsWithDifferentParamName() throws Exception {
JSONValidationInterceptor interceptor = new JSONValidationInterceptor();
interceptor.setValidateJsonParam("enableJSONValidation");
action.setText("abcd@ggg.com");
action.setPassword("apassword");
action.setValue(10);
Map<String, String> parameters = new HashMap<>();
parameters.put("enableJSONValidation", "true");
request.setParameterMap(parameters);
validationInterceptor.intercept(invocation);
interceptor.intercept(invocation);
String json = stringWriter.toString();
String normalizedActual = TestUtils.normalize(json, true);
assertEquals("", normalizedActual);
}
public void testValidationSucceedsValidateOnlyWithDifferentParamName() throws Exception {
JSONValidationInterceptor interceptor = new JSONValidationInterceptor();
interceptor.setValidateOnlyParam("validateOnly");
interceptor.setValidateJsonParam("enableJSONValidation");
action.setText("abcd@ggg.com");
action.setPassword("apassword");
action.setValue(10);
//just validate
Map<String, String> parameters = new HashMap<>();
parameters.put("validateOnly", "true");
parameters.put("enableJSONValidation", "true");
request.setParameterMap(parameters);
validationInterceptor.intercept(invocation);
interceptor.intercept(invocation);
String json = stringWriter.toString();
String normalizedActual = TestUtils.normalize(json, true);
assertEquals("{}", normalizedActual);
assertFalse(action.isExecuted());
assertEquals("application/json", response.getContentType());
assertEquals("UTF-8", response.getCharacterEncoding());
}
protected void setUp() throws Exception {
super.setUp();
ActionConfig config = new ActionConfig.Builder("", "name", "").build();
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-junit-plugin</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-osgi-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-oval-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-pell-multipart-plugin</artifactId>
@@ -58,7 +58,8 @@ public class PellMultiPartRequest extends AbstractMultiPartRequest {
synchronized (this) {
setEncoding();
if (maxSizeProvided){
multi = new ServletMultipartRequest(servletRequest, saveDir, maxSize);
int intMaxSize = (maxSize >= Integer.MAX_VALUE ? Integer.MAX_VALUE : Long.valueOf(maxSize).intValue());
multi = new ServletMultipartRequest(servletRequest, saveDir, intMaxSize);
}else{
multi = new ServletMultipartRequest(servletRequest, saveDir);
}
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-plexus-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-plugins</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-portlet-tiles-plugin</artifactId>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-portlet-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-rest-plugin</artifactId>
@@ -24,7 +24,7 @@ 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.Interceptor;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.rest.handler.ContentTypeHandler;
@@ -35,7 +35,7 @@ import java.io.InputStreamReader;
/**
* Uses the content handler to apply the request body to the action
*/
public class ContentTypeInterceptor implements Interceptor {
public class ContentTypeInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
ContentTypeHandlerManager selector;
@@ -45,10 +45,6 @@ public class ContentTypeInterceptor implements Interceptor {
this.selector = sel;
}
public void destroy() {}
public void init() {}
public String intercept(ActionInvocation invocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
ContentTypeHandler handler = selector.getHandlerForRequest(request);
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-sitegraph-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-sitemesh-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-spring-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-testng-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
</parent>
<artifactId>struts2-tiles-plugin</artifactId>
+8 -2
View File
@@ -9,7 +9,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>struts2-parent</artifactId>
<version>2.5.7</version>
<version>2.5.10</version>
<packaging>pom</packaging>
<name>Struts 2</name>
<url>http://struts.apache.org/</url>
@@ -31,7 +31,7 @@
<connection>scm:git:git://git.apache.org/struts.git</connection>
<developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/struts.git</developerConnection>
<url>http://git.apache.org/struts.git</url>
<tag>STRUTS_2_5_7</tag>
<tag>STRUTS_2_5_10</tag>
</scm>
<issueManagement>
@@ -699,6 +699,12 @@
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<!-- it's a dependency of Velocity defined here to override the transitive one -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>