diff --git a/apps/pom.xml b/apps/pom.xml
index 87de12462..ab871b01e 100644
--- a/apps/pom.xml
+++ b/apps/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-parent
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-apps
pom
diff --git a/apps/portlet/pom.xml b/apps/portlet/pom.xml
index 388b9c4d2..dbed8171c 100644
--- a/apps/portlet/pom.xml
+++ b/apps/portlet/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-apps
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-portlet
diff --git a/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp b/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp
index 217b158af..6f6b97c53 100644
--- a/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp
+++ b/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp
@@ -5,11 +5,11 @@ Here you'll find examples of what is possible with the Struts Portlet integratio
">A simple form
">Form example with proper PRG
- ">Model driven example
+ ">Model driven example/li>
">Validation
">Token
">Spring integration
- ">File upload
+ ">File upload
">FreeMarker
">Velocity
">Form Example Validation with Tiles
diff --git a/apps/portlet/src/test/java/org/apache/struts2/portlet/test/BasePortletTest.java b/apps/portlet/src/test/java/org/apache/struts2/portlet/test/BasePortletTest.java
index 4f63080b6..c46f2ed3c 100644
--- a/apps/portlet/src/test/java/org/apache/struts2/portlet/test/BasePortletTest.java
+++ b/apps/portlet/src/test/java/org/apache/struts2/portlet/test/BasePortletTest.java
@@ -9,6 +9,8 @@ import org.mortbay.jetty.webapp.WebAppContext;
import junit.framework.TestCase;
import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
public abstract class BasePortletTest extends TestCase {
@@ -20,17 +22,29 @@ public abstract class BasePortletTest extends TestCase {
public void setUp() throws Exception {
System.setProperty("org.apache.pluto.embedded.portletIds", getPortletName());
+ System.setProperty("org.apache.jasper.compiler.disablejsr199", "false");
+
server = new Server(port);
WebAppContext webapp = new WebAppContext("src/main/webapp", contextPath);
webapp.setTempDirectory(new File("target/work"));
webapp.setDefaultsDescriptor("/WEB-INF/jetty-pluto-web-default.xml");
- ServletHolder portletServlet = new ServletHolder(new PortletServlet());
+
+ // Set Classloader of Context to be sane (needed for JSTL)
+ // JSP requires a non-System classloader, this simply wraps the
+ // embedded System classloader in a way that makes it suitable
+ // for JSP to use
+ ClassLoader jspClassLoader = new URLClassLoader(new URL[0], this.getClass().getClassLoader());
+ webapp.setClassLoader(jspClassLoader);
+
+ ServletHolder portletServlet = new ServletHolder(new PortletServlet());
portletServlet.setInitParameter("portlet-name", getPortletName());
portletServlet.setInitOrder(1);
webapp.addServlet(portletServlet, "/PlutoInvoker/" + getPortletName());
- server.addHandler(webapp);
- server.start();
+
+ server.addHandler(webapp);
+
+ server.start();
// Retrieve the actual port that is used, in case a random, free port is
// picked
int port = server.getConnectors()[0].getLocalPort();
diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml
index b02923cd1..6e7e0c02e 100644
--- a/apps/rest-showcase/pom.xml
+++ b/apps/rest-showcase/pom.xml
@@ -26,12 +26,12 @@
org.apache.struts
struts2-apps
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-rest-showcase
war
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
Struts 2 Rest Showcase Webapp
Struts 2 Rest Showcase Example
diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml
index 4e6044beb..53d9a93a4 100644
--- a/apps/showcase/pom.xml
+++ b/apps/showcase/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-apps
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-showcase
diff --git a/archetypes/pom.xml b/archetypes/pom.xml
index b66531d2a..a24531a6c 100644
--- a/archetypes/pom.xml
+++ b/archetypes/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-parent
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-archetypes
diff --git a/archetypes/struts2-archetype-angularjs/pom.xml b/archetypes/struts2-archetype-angularjs/pom.xml
index fdff57d12..9db220aa3 100644
--- a/archetypes/struts2-archetype-angularjs/pom.xml
+++ b/archetypes/struts2-archetype-angularjs/pom.xml
@@ -2,7 +2,7 @@
org.apache.struts
struts2-archetypes
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/archetypes/struts2-archetype-blank/pom.xml b/archetypes/struts2-archetype-blank/pom.xml
index ee3f99aa7..9a9260c22 100644
--- a/archetypes/struts2-archetype-blank/pom.xml
+++ b/archetypes/struts2-archetype-blank/pom.xml
@@ -3,7 +3,7 @@
org.apache.struts
struts2-archetypes
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/archetypes/struts2-archetype-convention/pom.xml b/archetypes/struts2-archetype-convention/pom.xml
index a5cbcfd7b..e308ac125 100644
--- a/archetypes/struts2-archetype-convention/pom.xml
+++ b/archetypes/struts2-archetype-convention/pom.xml
@@ -2,7 +2,7 @@
org.apache.struts
struts2-archetypes
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/archetypes/struts2-archetype-dbportlet/pom.xml b/archetypes/struts2-archetype-dbportlet/pom.xml
index 0bedf93a7..cb7d22822 100644
--- a/archetypes/struts2-archetype-dbportlet/pom.xml
+++ b/archetypes/struts2-archetype-dbportlet/pom.xml
@@ -2,7 +2,7 @@
org.apache.struts
struts2-archetypes
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/archetypes/struts2-archetype-plugin/pom.xml b/archetypes/struts2-archetype-plugin/pom.xml
index 91b44262e..e954f1f5a 100644
--- a/archetypes/struts2-archetype-plugin/pom.xml
+++ b/archetypes/struts2-archetype-plugin/pom.xml
@@ -2,7 +2,7 @@
org.apache.struts
struts2-archetypes
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/archetypes/struts2-archetype-portlet/pom.xml b/archetypes/struts2-archetype-portlet/pom.xml
index 482b09b2c..d0b2cc3ed 100644
--- a/archetypes/struts2-archetype-portlet/pom.xml
+++ b/archetypes/struts2-archetype-portlet/pom.xml
@@ -2,7 +2,7 @@
org.apache.struts
struts2-archetypes
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/archetypes/struts2-archetype-starter/pom.xml b/archetypes/struts2-archetype-starter/pom.xml
index 168cf31c4..8c8583913 100644
--- a/archetypes/struts2-archetype-starter/pom.xml
+++ b/archetypes/struts2-archetype-starter/pom.xml
@@ -4,7 +4,7 @@
org.apache.struts
struts2-archetypes
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/assembly/pom.xml b/assembly/pom.xml
index a5e3a04d7..9f445b44f 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -3,7 +3,7 @@
org.apache.struts
struts2-parent
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-assembly
diff --git a/bom/pom.xml b/bom/pom.xml
index e170a5eab..13098b374 100644
--- a/bom/pom.xml
+++ b/bom/pom.xml
@@ -10,7 +10,7 @@
struts2-bom
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
pom
Struts 2 Bill of Materials
@@ -25,7 +25,7 @@
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
diff --git a/bundles/admin/pom.xml b/bundles/admin/pom.xml
index 2380aa48e..a7c9e1dcf 100644
--- a/bundles/admin/pom.xml
+++ b/bundles/admin/pom.xml
@@ -4,7 +4,7 @@
org.apache.struts
struts2-osgi-bundles
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-osgi-admin-bundle
diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml
index 245da9f10..bc3ee9ccc 100644
--- a/bundles/demo/pom.xml
+++ b/bundles/demo/pom.xml
@@ -4,7 +4,7 @@
org.apache.struts
struts2-osgi-bundles
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-osgi-demo-bundle
diff --git a/bundles/pom.xml b/bundles/pom.xml
index f1d9b826e..8937c7bfa 100755
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-parent
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-osgi-bundles
diff --git a/core/pom.xml b/core/pom.xml
index 91cc5ebd3..9ce0fcda1 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-parent
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-core
jar
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/ActionConfig.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/ActionConfig.java
index e12a86b4b..1b8373822 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/entities/ActionConfig.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/entities/ActionConfig.java
@@ -43,7 +43,7 @@ public class ActionConfig extends Located implements Serializable {
public static final String DEFAULT_METHOD = "execute";
public static final String WILDCARD = "*";
- public static final String REGEX_WILDCARD = "regex:.*";
+ public static final String DEFAULT_METHOD_REGEX = "([A-Za-z0-9_$]*)";
protected List interceptors; // a list of interceptorMapping Objects eg. List
protected Map params;
@@ -53,6 +53,7 @@ public class ActionConfig extends Located implements Serializable {
protected String methodName;
protected String packageName;
protected String name;
+ protected boolean strictMethodInvocation = true;
protected AllowedMethods allowedMethods;
protected ActionConfig(String packageName, String name, String className) {
@@ -63,7 +64,6 @@ public class ActionConfig extends Located implements Serializable {
results = new LinkedHashMap<>();
interceptors = new ArrayList<>();
exceptionMappings = new ArrayList<>();
- allowedMethods = AllowedMethods.build(new HashSet<>(Collections.singletonList(DEFAULT_METHOD)));
}
/**
@@ -80,7 +80,7 @@ public class ActionConfig extends Located implements Serializable {
this.interceptors = new ArrayList<>(orig.interceptors);
this.results = new LinkedHashMap<>(orig.results);
this.exceptionMappings = new ArrayList<>(orig.exceptionMappings);
- this.allowedMethods = AllowedMethods.build(orig.allowedMethods.list());
+ this.allowedMethods = orig.allowedMethods;
this.location = orig.location;
}
@@ -132,6 +132,10 @@ public class ActionConfig extends Located implements Serializable {
return method.equals(methodName != null ? methodName : DEFAULT_METHOD) || allowedMethods.isAllowed(method);
}
+ public boolean isStrictMethodInvocation() {
+ return strictMethodInvocation;
+ }
+
@Override public boolean equals(Object o) {
if (this == o) {
return true;
@@ -213,6 +217,7 @@ public class ActionConfig extends Located implements Serializable {
protected ActionConfig target;
protected Set allowedMethods;
+ private String methodRegex;
public Builder(ActionConfig toClone) {
target = new ActionConfig(toClone);
@@ -328,12 +333,22 @@ public class ActionConfig extends Located implements Serializable {
return this;
}
+ public Builder setStrictMethodInvocation(boolean strictMethodInvocation) {
+ target.strictMethodInvocation = strictMethodInvocation;
+ return this;
+ }
+
+ public Builder setDefaultMethodRegex(String methodRegex) {
+ this.methodRegex = methodRegex;
+ return this;
+ }
+
public ActionConfig build() {
target.params = Collections.unmodifiableMap(target.params);
target.results = Collections.unmodifiableMap(target.results);
target.interceptors = Collections.unmodifiableList(target.interceptors);
target.exceptionMappings = Collections.unmodifiableList(target.exceptionMappings);
- target.allowedMethods = AllowedMethods.build(allowedMethods);
+ target.allowedMethods = AllowedMethods.build(target.strictMethodInvocation, allowedMethods, methodRegex != null ? methodRegex : DEFAULT_METHOD_REGEX);
ActionConfig result = target;
target = new ActionConfig(target);
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/AllowedMethods.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/AllowedMethods.java
index 22fea1240..d81de5a2e 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/entities/AllowedMethods.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/entities/AllowedMethods.java
@@ -28,44 +28,51 @@ public class AllowedMethods {
private static final Logger LOG = LogManager.getLogger(AllowedMethods.class);
private Set allowedMethods;
+ private final boolean strictMethodInvocation;
+ private String defaultRegex;
- public static AllowedMethods build(Set methods) {
+ public static AllowedMethods build(boolean strictMethodInvocation, Set methods, String defaultRegex) {
Set allowedMethods = new HashSet<>();
for (String method : methods) {
boolean isPattern = false;
+ StringBuilder methodPattern = new StringBuilder();
int len = method.length();
- StringBuilder ret = new StringBuilder();
char c;
for (int x = 0; x < len; x++) {
c = method.charAt(x);
if (x < len - 2 && c == '{' && '}' == method.charAt(x + 2)) {
- ret.append("(.*)");
+ methodPattern.append(defaultRegex);
isPattern = true;
x += 2;
} else {
- ret.append(c);
+ methodPattern.append(c);
}
}
- if (isPattern && !method.startsWith("regex:")) {
- allowedMethods.add(new PatternAllowedMethod(ret.toString(), method));
+
+ if (isPattern && !method.startsWith("regex:") && !strictMethodInvocation) {
+ allowedMethods.add(new PatternAllowedMethod(methodPattern.toString(), method));
} else if (method.startsWith("regex:")) {
String pattern = method.substring(method.indexOf(":") + 1);
allowedMethods.add(new PatternAllowedMethod(pattern, method));
- } else if (method.contains("*") && !method.startsWith("regex:")) {
- String pattern = method.replaceAll("\\*", "(.*)");
+ } else if (method.contains("*") && !method.startsWith("regex:") && !strictMethodInvocation) {
+ String pattern = method.replace("*", defaultRegex);
allowedMethods.add(new PatternAllowedMethod(pattern, method));
+ } else if (!isPattern) {
+ allowedMethods.add(new LiteralAllowedMethod(method));
} else {
- allowedMethods.add(new LiteralAllowedMethod(ret.toString()));
+ LOG.trace("Ignoring method name: [{}] when SMI is set to [{}]", method, strictMethodInvocation);
}
}
LOG.debug("Defined allowed methods: {}", allowedMethods);
- return new AllowedMethods(allowedMethods);
+ return new AllowedMethods(strictMethodInvocation, allowedMethods, defaultRegex);
}
- private AllowedMethods(Set methods) {
+ private AllowedMethods(boolean strictMethodInvocation, Set methods, String defaultRegex) {
+ this.strictMethodInvocation = strictMethodInvocation;
+ this.defaultRegex = defaultRegex;
this.allowedMethods = Collections.unmodifiableSet(methods);
}
@@ -86,6 +93,14 @@ public class AllowedMethods {
return result;
}
+ public String getDefaultRegex() {
+ return defaultRegex;
+ }
+
+ public boolean isStrictMethodInvocation() {
+ return strictMethodInvocation;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -139,13 +154,13 @@ public class AllowedMethods {
PatternAllowedMethod that = (PatternAllowedMethod) o;
- return original.equals(that.original);
+ return allowedMethodPattern.pattern().equals(that.allowedMethodPattern.pattern());
}
@Override
public int hashCode() {
- return original.hashCode();
+ return allowedMethodPattern.pattern().hashCode();
}
@Override
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java
index 2a2f0edf6..07a8c46a2 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java
@@ -115,6 +115,7 @@ public class ActionConfigMatcher extends AbstractMatcher implement
.methodName(methodName)
.addParams(params)
.addResultConfigs(results)
+ .setStrictMethodInvocation(orig.isStrictMethodInvocation())
.addAllowedMethod(orig.getAllowedMethods())
.addInterceptors(orig.getInterceptors())
.addExceptionMappings(exs)
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
index 1aa45c192..742683109 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java
@@ -36,6 +36,7 @@ import ognl.PropertyAccessor;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.apache.struts2.StrutsConstants;
import java.util.*;
@@ -370,11 +371,20 @@ public class DefaultConfiguration implements Configuration {
}
}
+ String methodRegex = container.getInstance(String.class, StrutsConstants.STRUTS_SMI_METHOD_REGEX);
+ if (methodRegex == null) {
+ methodRegex = ActionConfig.DEFAULT_METHOD_REGEX;
+ }
+
+ LOG.debug("Using pattern [{}] to match allowed methods when SMI is disabled!", methodRegex);
+
return new ActionConfig.Builder(baseConfig)
.addParams(params)
.addResultConfigs(results)
.defaultClassName(packageContext.getDefaultClassRef()) // fill in default if non class has been provided
.interceptors(interceptors)
+ .setStrictMethodInvocation(packageContext.isStrictMethodInvocation())
+ .setDefaultMethodRegex(methodRegex)
.addExceptionMappings(packageContext.getAllExceptionMappingConfigs())
.build();
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java
index 6075be28b..4e76bb290 100644
--- a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java
+++ b/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java
@@ -464,6 +464,7 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
.addInterceptors(interceptorList)
.addExceptionMappings(exceptionMappings)
.addParams(XmlHelper.getParams(actionElement))
+ .setStrictMethodInvocation(packageContext.isStrictMethodInvocation())
.addAllowedMethod(allowedMethods)
.location(location)
.build();
@@ -872,11 +873,13 @@ public class XmlConfigurationProvider implements ConfigurationProvider {
// user enabled Strict DMI but didn't defined action specific 'allowed-methods' so we use 'global-allowed-methods' only
allowedMethods = new HashSet<>(packageContext.getGlobalAllowedMethods());
} else {
- // Strict DMI is disabled to any method can be called
+ // Strict DMI is disabled so any method can be called
allowedMethods = new HashSet<>();
- allowedMethods.add(ActionConfig.REGEX_WILDCARD);
+ allowedMethods.add(ActionConfig.WILDCARD);
}
+ LOG.debug("Collected allowed methods: {}", allowedMethods);
+
return Collections.unmodifiableSet(allowedMethods);
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
index 679c80451..562b6fc14 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -287,7 +287,7 @@ public class OgnlUtil {
compileAndExecute(name, context, new OgnlTask() {
public Void execute(Object tree) throws OgnlException {
if (isEvalExpression(tree, context)) {
- throw new OgnlException("Eval expression cannot be used as parameter name");
+ throw new OgnlException("Eval expression/chained expressions cannot be used as parameter name");
}
Ognl.setValue(tree, context, root, value);
return null;
@@ -303,7 +303,7 @@ public class OgnlUtil {
if (context!=null && context instanceof OgnlContext) {
ognlContext = (OgnlContext) context;
}
- return node.isEvalChain(ognlContext);
+ return node.isEvalChain(ognlContext) || node.isSequence(ognlContext);
}
return false;
}
@@ -360,7 +360,7 @@ public class OgnlUtil {
private void checkEnableEvalExpression(Object tree, Map context) throws OgnlException {
if (!enableEvalExpression && isEvalExpression(tree, context)) {
- throw new OgnlException("Eval expressions has been disabled!");
+ throw new OgnlException("Eval expressions/chained expressions have been disabled!");
}
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/EmailValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/EmailValidator.java
index d54a1fa65..9410eb659 100644
--- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/EmailValidator.java
+++ b/core/src/main/java/com/opensymphony/xwork2/validator/validators/EmailValidator.java
@@ -23,7 +23,7 @@ package com.opensymphony.xwork2.validator.validators;
* The regular expression used to validate that the string is an email address is:
*
*
- * \\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)$\\b
+ * \\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
*
*
* You can also specify expression, caseSensitive and trim params as a OGNL expression, see the example below.
@@ -80,7 +80,7 @@ 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)$\\b";
+ "\\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 EmailValidator() {
setRegex(EMAIL_ADDRESS_PATTERN);
diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index d5b70cff0..186e880f9 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -298,4 +298,5 @@ public final class StrutsConstants {
public static final String STRUTS_CONTENT_TYPE_MATCHER = "struts.contentTypeMatcher";
+ public static final String STRUTS_SMI_METHOD_REGEX = "struts.strictMethodInvocation.methodRegex";
}
diff --git a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java
index 95ab0d5bd..d0e89beef 100644
--- a/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java
+++ b/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java
@@ -34,6 +34,7 @@ import org.apache.logging.log4j.Logger;
import org.apache.struts2.RequestUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.StrutsException;
import org.apache.struts2.util.PrefixTrie;
import javax.servlet.http.HttpServletRequest;
@@ -136,7 +137,7 @@ public class DefaultActionMapper implements ActionMapper {
put(METHOD_PREFIX, new ParameterAction() {
public void execute(String key, ActionMapping mapping) {
if (allowDynamicMethodCalls) {
- mapping.setMethod(key.substring(METHOD_PREFIX.length()));
+ mapping.setMethod(cleanupActionName(key.substring(METHOD_PREFIX.length())));
}
}
});
@@ -148,7 +149,7 @@ public class DefaultActionMapper implements ActionMapper {
if (allowDynamicMethodCalls) {
int bang = name.indexOf('!');
if (bang != -1) {
- String method = name.substring(bang + 1);
+ String method = cleanupActionName(name.substring(bang + 1));
mapping.setMethod(method);
name = name.substring(0, bang);
}
@@ -385,14 +386,7 @@ public class DefaultActionMapper implements ActionMapper {
if (allowedActionNames.matcher(rawActionName).matches()) {
return rawActionName;
} else {
- LOG.warn("Action [{}] does not match allowed action names pattern [{}], cleaning it up!",
- rawActionName, allowedActionNames);
- String cleanActionName = rawActionName;
- for (String chunk : allowedActionNames.split(rawActionName)) {
- cleanActionName = cleanActionName.replace(chunk, "");
- }
- LOG.debug("Cleaned action name [{}]", cleanActionName);
- return cleanActionName;
+ throw new StrutsException("Action [" + rawActionName + "] does not match allowed action names pattern [" + allowedActionNames + "]!");
}
}
diff --git a/core/src/main/java/org/apache/struts2/interceptor/MessageStorePreResultListener.java b/core/src/main/java/org/apache/struts2/interceptor/MessageStorePreResultListener.java
index 60fcffe21..9b313a8fe 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/MessageStorePreResultListener.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/MessageStorePreResultListener.java
@@ -73,8 +73,7 @@ class MessageStorePreResultListener implements PreResultListener {
try {
ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(resultCode);
if (resultConfig != null) {
- isRedirect = ServletRedirectResult.class.getName().equals(resultConfig.getClassName())
- || ServletActionRedirectResult.class.getName().equals(resultConfig.getClassName());
+ isRedirect = ServletRedirectResult.class.isAssignableFrom(Class.forName(resultConfig.getClassName()));
}
} catch (Exception e) {
LOG.warn("Cannot read result!", e);
diff --git a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
index 5ebbf67bb..5dfd5fb25 100644
--- a/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
+++ b/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java
@@ -404,12 +404,7 @@ public class XSLTResult implements Result {
ServletActionContext.getServletContext());
}
- protected Templates getTemplates(String path) throws TransformerException, IOException {
- String pathFromRequest = ServletActionContext.getRequest().getParameter("xslt.location");
-
- if (pathFromRequest != null)
- path = pathFromRequest;
-
+ protected Templates getTemplates(final String path) throws TransformerException, IOException {
if (path == null)
throw new TransformerException("Stylesheet path is null");
diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml
index 4c1361baf..e4090a55e 100644
--- a/core/src/main/resources/struts-default.xml
+++ b/core/src/main/resources/struts-default.xml
@@ -50,6 +50,8 @@
ognl.OgnlContext,
ognl.ClassResolver,
ognl.TypeConverter,
+ ognl.MemberAccess,
+ ognl.DefaultMemberAccess,
com.opensymphony.xwork2.ognl.SecurityMemberAccess,
com.opensymphony.xwork2.ActionContext" />
diff --git a/core/src/main/resources/template/simple/submit.ftl b/core/src/main/resources/template/simple/submit.ftl
index 24db4a886..d77b5d090 100644
--- a/core/src/main/resources/template/simple/submit.ftl
+++ b/core/src/main/resources/template/simple/submit.ftl
@@ -61,6 +61,9 @@
#if>
<#else>
+<#if parameters.nameValue?has_content>
+ value="<@s.property value="parameters.nameValue"/>"<#rt/>
+#if>
#if>
<#if parameters.id?has_content>
id="${parameters.id?html}"<#rt/>
@@ -68,9 +71,6 @@
<#if parameters.name?has_content>
name="${parameters.name?html}"<#rt/>
#if>
-<#if parameters.nameValue?has_content>
- value="<@s.property value="parameters.nameValue"/>"<#rt/>
-#if>
<#if parameters.disabled!false>
disabled="disabled"<#rt/>
#if>
diff --git a/core/src/main/resources/template/xhtml/controlheader-core.ftl b/core/src/main/resources/template/xhtml/controlheader-core.ftl
index 302442d03..31df86944 100644
--- a/core/src/main/resources/template/xhtml/controlheader-core.ftl
+++ b/core/src/main/resources/template/xhtml/controlheader-core.ftl
@@ -62,11 +62,11 @@
class="label"<#t/>
#if>
><#t/>
-<#if parameters.required!false && parameters.requiredPosition!"right" != 'right'>
+<#if (parameters.required!false) && ((parameters.requiredPosition!"right") != 'right')>
* <#t/>
#if>
${parameters.label?html}<#t/>
-<#if parameters.required!false && parameters.requiredPosition!"right" == 'right'>
+<#if (parameters.required!false) && ((parameters.requiredPosition!"right") == 'right')>
* <#t/>
#if>
${parameters.labelseparator!":"?html}<#t/>
diff --git a/core/src/test/java/com/opensymphony/xwork2/config/entities/AllowedMethodsTest.java b/core/src/test/java/com/opensymphony/xwork2/config/entities/AllowedMethodsTest.java
index 607a9dc9d..adb8935cc 100644
--- a/core/src/test/java/com/opensymphony/xwork2/config/entities/AllowedMethodsTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/config/entities/AllowedMethodsTest.java
@@ -14,7 +14,7 @@ public class AllowedMethodsTest extends TestCase {
literals.add(method);
// when
- AllowedMethods allowedMethods = AllowedMethods.build(literals);
+ AllowedMethods allowedMethods = AllowedMethods.build(false, literals, ActionConfig.DEFAULT_METHOD_REGEX);
// then
assertEquals(1, allowedMethods.list().size());
@@ -22,14 +22,14 @@ public class AllowedMethodsTest extends TestCase {
assertFalse(allowedMethods.isAllowed("someOtherMethod"));
}
- public void testWidlcardMethods() throws Exception {
+ public void testWildcardMethodsWithNoSMI() throws Exception {
// given
String method = "my{1}";
Set literals = new HashSet<>();
literals.add(method);
// when
- AllowedMethods allowedMethods = AllowedMethods.build(literals);
+ AllowedMethods allowedMethods = AllowedMethods.build(false, literals, ActionConfig.DEFAULT_METHOD_REGEX);
// then
assertEquals(1, allowedMethods.list().size());
@@ -37,18 +37,50 @@ public class AllowedMethodsTest extends TestCase {
assertFalse(allowedMethods.isAllowed("someOtherMethod"));
}
- public void testWidlcardWithStarMethods() throws Exception {
+ public void testWildcardMethodsWithSMI() throws Exception {
+ // given
+ Set literals = new HashSet<>();
+ literals.add("my{1}");
+ literals.add("myMethod");
+
+ // when
+ AllowedMethods allowedMethods = AllowedMethods.build(true, literals, ActionConfig.DEFAULT_METHOD_REGEX);
+
+ // then
+ assertEquals(1, allowedMethods.list().size());
+ assertFalse(allowedMethods.isAllowed("my{1}"));
+ assertTrue(allowedMethods.isAllowed("myMethod"));
+ assertFalse(allowedMethods.isAllowed("someOtherMethod"));
+ }
+
+ public void testWildcardWithStarMethodsWithNoSMI() throws Exception {
+ // given
+ String method = "cancel*Action*";
+ Set literals = new HashSet<>();
+ literals.add(method);
+
+ // when
+ AllowedMethods allowedMethods = AllowedMethods.build(false, literals, ActionConfig.DEFAULT_METHOD_REGEX);
+
+ // then
+ assertEquals(1, allowedMethods.list().size());
+ assertTrue(allowedMethods.isAllowed("cancelAction"));
+ assertFalse(allowedMethods.isAllowed("startEvent"));
+ }
+
+ public void testWildcardWithStarMethodsWithSMI() throws Exception {
// given
String method = "cancel*";
Set literals = new HashSet<>();
literals.add(method);
// when
- AllowedMethods allowedMethods = AllowedMethods.build(literals);
+ AllowedMethods allowedMethods = AllowedMethods.build(true, literals, ActionConfig.DEFAULT_METHOD_REGEX);
// then
assertEquals(1, allowedMethods.list().size());
- assertTrue(allowedMethods.isAllowed("cancelAction"));
+ assertTrue(allowedMethods.isAllowed("cancel*"));
+ assertFalse(allowedMethods.isAllowed("cancelAction"));
assertFalse(allowedMethods.isAllowed("startEvent"));
}
@@ -59,7 +91,7 @@ public class AllowedMethodsTest extends TestCase {
literals.add(method);
// when
- AllowedMethods allowedMethods = AllowedMethods.build(literals);
+ AllowedMethods allowedMethods = AllowedMethods.build(true, literals, ActionConfig.DEFAULT_METHOD_REGEX);
// then
assertEquals(1, allowedMethods.list().size());
diff --git a/core/src/test/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcherTest.java b/core/src/test/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcherTest.java
index 6eb9f27c4..7957cf906 100644
--- a/core/src/test/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcherTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcherTest.java
@@ -156,18 +156,21 @@ public class ActionConfigMatcherTest extends XWorkTestCase {
.build())
.addInterceptor(new InterceptorMapping(null, null))
.addResultConfig(new ResultConfig.Builder("success{1}", "foo.{2}").addParams(params).build())
+ .setStrictMethodInvocation(false)
.build();
map.put("foo/*/*", config);
config = new ActionConfig.Builder("package-{1}", "bar/*/**", "bar")
.methodName("do{1}_{1}")
.addParam("first", "{2}")
+ .setStrictMethodInvocation(false)
.build();
map.put("bar/*/**", config);
config = new ActionConfig.Builder("package", "eventAdd!*", "bar")
.methodName("{1}")
+ .setStrictMethodInvocation(false)
.build();
map.put("addEvent!*", config);
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
index 1ccdc4a9c..339d6035f 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
@@ -744,6 +744,21 @@ public class OgnlUtilTest extends XWorkTestCase {
assertEquals(expected.getMessage(), "Method \"getRuntime\" failed for object class java.lang.Runtime");
}
+ public void testBlockSequenceOfExpressions() throws Exception {
+ Foo foo = new Foo();
+
+ Exception expected = null;
+ try {
+ ognlUtil.setValue("#booScope=@myclass@DEFAULT_SCOPE,#bootScope.init()", ognlUtil.createDefaultContext(foo), foo, true);
+ fail();
+ } catch (OgnlException e) {
+ expected = e;
+ }
+ assertNotNull(expected);
+ assertSame(OgnlException.class, expected.getClass());
+ assertEquals(expected.getMessage(), "Eval expressions/chained expressions have been disabled!");
+ }
+
public static class Email {
String address;
diff --git a/core/src/test/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsCheckerTest.java b/core/src/test/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsCheckerTest.java
index faf807e39..762dedfc4 100644
--- a/core/src/test/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsCheckerTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsCheckerTest.java
@@ -91,7 +91,6 @@ public class DefaultExcludedPatternsCheckerTest extends XWorkTestCase {
}
for (String param : params) {
- System.out.println(param);
// when
ExcludedPatternsChecker.IsExcluded actual = checker.isExcluded(param);
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/EmailValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/EmailValidatorTest.java
index d24d7955d..2de1f1823 100644
--- a/core/src/test/java/com/opensymphony/xwork2/validator/EmailValidatorTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/EmailValidatorTest.java
@@ -45,6 +45,8 @@ public class EmailValidatorTest extends XWorkTestCase {
assertTrue(verifyEmailValidity("tmj'ee@yahoo.com"));
assertTrue(verifyEmailValidity("ferda+mravenec@yahoo.com"));
assertTrue(verifyEmailValidity("Ferda+Mravenec@yaHoo.CoM"));
+ assertTrue(verifyEmailValidity("user@domainname.tech"));
+ assertTrue(verifyEmailValidity("Ferda+Mravenec@yaHoo.cat"));
assertFalse(verifyEmailValidity("tm_jee#marry@yahoo.co.uk"));
assertFalse(verifyEmailValidity("tm_jee@ yahoo.co.uk"));
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java
index 43146721a..69bb7de77 100644
--- a/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java
+++ b/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java
@@ -30,6 +30,7 @@ import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsException;
import org.apache.struts2.StrutsInternalTestCase;
import org.apache.struts2.result.StrutsResultSupport;
import org.apache.struts2.views.jsp.StrutsMockHttpServletRequest;
@@ -844,14 +845,37 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
String actionName = "action";
assertEquals(actionName, mapper.cleanupActionName(actionName));
+ Throwable expected = null;
+
actionName = "${action}";
- assertEquals("action", mapper.cleanupActionName(actionName));
+ try {
+ mapper.cleanupActionName(actionName);
+ fail();
+ } catch (Throwable t) {
+ expected = t;
+ }
+ assertTrue(expected instanceof StrutsException);
+ assertEquals("Action [${action}] does not match allowed action names pattern [[a-zA-Z0-9._!/\\-]*]!", expected.getMessage());
actionName = "${${%{action}}}";
- assertEquals("action", mapper.cleanupActionName(actionName));
+ try {
+ mapper.cleanupActionName(actionName);
+ fail();
+ } catch (Throwable t) {
+ expected = t;
+ }
+ assertTrue(expected instanceof StrutsException);
+ assertEquals("Action [${${%{action}}}] does not match allowed action names pattern [[a-zA-Z0-9._!/\\-]*]!", expected.getMessage());
actionName = "${#foo='action',#foo}";
- assertEquals("fooactionfoo", mapper.cleanupActionName(actionName));
+ try {
+ mapper.cleanupActionName(actionName);
+ fail();
+ } catch (Throwable t) {
+ expected = t;
+ }
+ assertTrue(expected instanceof StrutsException);
+ assertEquals("Action [${#foo='action',#foo}] does not match allowed action names pattern [[a-zA-Z0-9._!/\\-]*]!", expected.getMessage());
actionName = "test-action";
assertEquals("test-action", mapper.cleanupActionName(actionName));
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java
index 2a33037e2..71fbb149f 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java
@@ -232,7 +232,7 @@ public class SubmitTest extends AbstractUITagTest {
tag.doStartTag();
tag.doEndTag();
- assertEquals(" ", writer.toString().trim());
+ assertEquals(" ", writer.toString().trim());
}
/**
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java
index d61aae849..d8143084c 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java
@@ -239,6 +239,62 @@ public class TextfieldTest extends AbstractUITagTest {
verify(TextFieldTag.class.getResource("Textfield-9.txt"));
}
+ public void testRequiredLabelPositionDefault() throws Exception {
+ TestAction testAction = (TestAction) action;
+ testAction.setFoo("bar");
+
+ TextFieldTag tag = new TextFieldTag();
+ tag.setPageContext(pageContext);
+ tag.setId("myId");
+ tag.setLabel("mylabel");
+ tag.setName("foo");
+ tag.setValue("bar");
+ tag.setRequiredLabel("true");
+
+ tag.doStartTag();
+ tag.doEndTag();
+
+ verify(TextFieldTag.class.getResource("Textfield-12.txt"));
+ }
+
+ public void testRequiredLabelPositionRight() throws Exception {
+ TestAction testAction = (TestAction) action;
+ testAction.setFoo("bar");
+
+ TextFieldTag tag = new TextFieldTag();
+ tag.setPageContext(pageContext);
+ tag.setId("myId");
+ tag.setLabel("mylabel");
+ tag.setName("foo");
+ tag.setValue("bar");
+ tag.setRequiredLabel("true");
+ tag.setRequiredPosition("right");
+
+ tag.doStartTag();
+ tag.doEndTag();
+
+ verify(TextFieldTag.class.getResource("Textfield-12.txt"));
+ }
+
+ public void testRequiredLabelPositionLeft() throws Exception {
+ TestAction testAction = (TestAction) action;
+ testAction.setFoo("bar");
+
+ TextFieldTag tag = new TextFieldTag();
+ tag.setPageContext(pageContext);
+ tag.setId("myId");
+ tag.setLabel("mylabel");
+ tag.setName("foo");
+ tag.setValue("bar");
+ tag.setRequiredLabel("true");
+ tag.setRequiredPosition("left");
+
+ tag.doStartTag();
+ tag.doEndTag();
+
+ verify(TextFieldTag.class.getResource("Textfield-13.txt"));
+ }
+
public void testErrorPositionBottomCssXhtmlTheme() throws Exception {
TestAction testAction = (TestAction) action;
testAction.setFoo("bar");
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-1.txt
index ef5882ccb..330df2c4c 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-1.txt
@@ -1,3 +1,3 @@
-
+
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-2.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-2.txt
index 36b1554f5..e4b7c8b9d 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-2.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-2.txt
@@ -1,3 +1,3 @@
-
+
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-5.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-5.txt
index d83c44fcf..8632bc0ba 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-5.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-5.txt
@@ -1,3 +1,3 @@
-
+
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-6.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-6.txt
index 9cd5d0246..41dba2aad 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-6.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-6.txt
@@ -1,3 +1,3 @@
-
+
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-12.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-12.txt
new file mode 100644
index 000000000..9a3155d4d
--- /dev/null
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-12.txt
@@ -0,0 +1,11 @@
+
+
+
+ mylabel
+ * :
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-13.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-13.txt
new file mode 100644
index 000000000..e5e6e926d
--- /dev/null
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-13.txt
@@ -0,0 +1,11 @@
+
+
+
+ *
+ mylabel:
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/bean-validation/pom.xml b/plugins/bean-validation/pom.xml
index f2500c52b..235cb327a 100644
--- a/plugins/bean-validation/pom.xml
+++ b/plugins/bean-validation/pom.xml
@@ -24,7 +24,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
4.0.0
diff --git a/plugins/cdi/pom.xml b/plugins/cdi/pom.xml
index c375bea8f..d508ea464 100644
--- a/plugins/cdi/pom.xml
+++ b/plugins/cdi/pom.xml
@@ -25,7 +25,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-cdi-plugin
diff --git a/plugins/config-browser/pom.xml b/plugins/config-browser/pom.xml
index 69ebd2293..25a2762b8 100644
--- a/plugins/config-browser/pom.xml
+++ b/plugins/config-browser/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-config-browser-plugin
diff --git a/plugins/convention/pom.xml b/plugins/convention/pom.xml
index a7c6d6355..5609415c0 100644
--- a/plugins/convention/pom.xml
+++ b/plugins/convention/pom.xml
@@ -3,7 +3,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-convention-plugin
diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java b/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
index fc85d54dd..45c71a350 100644
--- a/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
+++ b/plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java
@@ -930,7 +930,7 @@ public class PackageBasedActionConfigBuilder implements ActionConfigBuilder {
actionConfig.addAllowedMethod(allowedMethods);
actionConfig.addAllowedMethod(pkgCfg.getGlobalAllowedMethods());
} else {
- actionConfig.addAllowedMethod(ActionConfig.REGEX_WILDCARD);
+ actionConfig.addAllowedMethod(ActionConfig.WILDCARD);
}
if (LOG.isDebugEnabled()) {
diff --git a/plugins/dwr/pom.xml b/plugins/dwr/pom.xml
index d34be748e..fec6997c2 100644
--- a/plugins/dwr/pom.xml
+++ b/plugins/dwr/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-dwr-plugin
diff --git a/plugins/embeddedjsp/pom.xml b/plugins/embeddedjsp/pom.xml
index 077b861a0..e6d994257 100644
--- a/plugins/embeddedjsp/pom.xml
+++ b/plugins/embeddedjsp/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-embeddedjsp-plugin
diff --git a/plugins/gxp/pom.xml b/plugins/gxp/pom.xml
index 5639ff43a..14c296471 100644
--- a/plugins/gxp/pom.xml
+++ b/plugins/gxp/pom.xml
@@ -3,7 +3,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-gxp-plugin
diff --git a/plugins/jasperreports/pom.xml b/plugins/jasperreports/pom.xml
index f6a8cd63d..69c0e7df2 100644
--- a/plugins/jasperreports/pom.xml
+++ b/plugins/jasperreports/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-jasperreports-plugin
diff --git a/plugins/java8-support/pom.xml b/plugins/java8-support/pom.xml
index 49dee3f07..4d26ade5a 100644
--- a/plugins/java8-support/pom.xml
+++ b/plugins/java8-support/pom.xml
@@ -5,7 +5,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-java8-support-plugin
diff --git a/plugins/javatemplates/pom.xml b/plugins/javatemplates/pom.xml
index a4a274b04..1d193dc5d 100644
--- a/plugins/javatemplates/pom.xml
+++ b/plugins/javatemplates/pom.xml
@@ -25,7 +25,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-javatemplates-plugin
diff --git a/plugins/jfreechart/pom.xml b/plugins/jfreechart/pom.xml
index a6a19d831..9aed2b848 100644
--- a/plugins/jfreechart/pom.xml
+++ b/plugins/jfreechart/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-jfreechart-plugin
diff --git a/plugins/json/pom.xml b/plugins/json/pom.xml
index fc3d83df7..bbe7f9dea 100644
--- a/plugins/json/pom.xml
+++ b/plugins/json/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-json-plugin
diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONWriterTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONWriterTest.java
index 88c888cdc..2a9d733cd 100644
--- a/plugins/json/src/test/java/org/apache/struts2/json/JSONWriterTest.java
+++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONWriterTest.java
@@ -7,7 +7,9 @@ import org.junit.Test;
import java.net.URL;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.TimeZone;
@@ -90,6 +92,41 @@ public class JSONWriterTest extends StrutsTestCase{
TestUtils.assertEquals(JSONWriter.class.getResource("jsonwriter-write-bean-02.txt"), json);
}
+ @Test
+ public void testWriteBeanWithList() throws Exception {
+ BeanWithList bean1 = new BeanWithList();
+ bean1.setStringField("str");
+ bean1.setBooleanField(true);
+ bean1.setCharField('s');
+ bean1.setDoubleField(10.1);
+ bean1.setFloatField(1.5f);
+ bean1.setIntField(10);
+ bean1.setLongField(100);
+ bean1.setEnumField(AnEnum.ValueA);
+ bean1.setEnumBean(AnEnumBean.Two);
+ List errors = new ArrayList();
+ errors.add("Field is required");
+ bean1.setErrors(errors);
+
+ JSONWriter jsonWriter = new JSONWriter();
+ jsonWriter.setEnumAsBean(false);
+ jsonWriter.setIgnoreHierarchy(false);
+ String json = jsonWriter.write(bean1);
+ TestUtils.assertEquals(JSONWriter.class.getResource("jsonwriter-write-bean-04.txt"), json);
+ }
+
+ private class BeanWithList extends Bean {
+ private List errors;
+
+ public List getErrors() {
+ return errors;
+ }
+
+ public void setErrors(List errors) {
+ this.errors = errors;
+ }
+ }
+
private class AnnotatedBean extends Bean{
private URL url;
diff --git a/plugins/json/src/test/resources/org/apache/struts2/json/jsonwriter-write-bean-04.txt b/plugins/json/src/test/resources/org/apache/struts2/json/jsonwriter-write-bean-04.txt
new file mode 100644
index 000000000..41f0b8177
--- /dev/null
+++ b/plugins/json/src/test/resources/org/apache/struts2/json/jsonwriter-write-bean-04.txt
@@ -0,0 +1,16 @@
+{
+ "bigDecimal":null,
+ "bigInteger":null,
+ "booleanField":true,
+ "byteField":0,
+ "charField":"s",
+ "doubleField":10.1,
+ "enumBean":"Two",
+ "enumField":"ValueA",
+ "errors":["Field is required"],
+ "floatField":1.5,
+ "intField":10,
+ "longField":100,
+ "objectField":null,
+ "stringField":"str"
+}
diff --git a/plugins/junit/pom.xml b/plugins/junit/pom.xml
index 798c14329..94ec0b310 100644
--- a/plugins/junit/pom.xml
+++ b/plugins/junit/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-junit-plugin
diff --git a/plugins/osgi/pom.xml b/plugins/osgi/pom.xml
index 2ed66b07d..484ee03c7 100644
--- a/plugins/osgi/pom.xml
+++ b/plugins/osgi/pom.xml
@@ -4,7 +4,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-osgi-plugin
diff --git a/plugins/oval/pom.xml b/plugins/oval/pom.xml
index cdaf94d33..bdfb5cf5e 100644
--- a/plugins/oval/pom.xml
+++ b/plugins/oval/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-oval-plugin
diff --git a/plugins/pell-multipart/pom.xml b/plugins/pell-multipart/pom.xml
index 18fa61e8c..a811d1d17 100644
--- a/plugins/pell-multipart/pom.xml
+++ b/plugins/pell-multipart/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-pell-multipart-plugin
diff --git a/plugins/plexus/pom.xml b/plugins/plexus/pom.xml
index c981ba187..066a87e24 100644
--- a/plugins/plexus/pom.xml
+++ b/plugins/plexus/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-plexus-plugin
diff --git a/plugins/pom.xml b/plugins/pom.xml
index ba4418184..c074d3642 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-parent
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-plugins
diff --git a/plugins/portlet-tiles/pom.xml b/plugins/portlet-tiles/pom.xml
index 8b710b206..833569ba6 100644
--- a/plugins/portlet-tiles/pom.xml
+++ b/plugins/portlet-tiles/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-portlet-tiles-plugin
diff --git a/plugins/portlet/pom.xml b/plugins/portlet/pom.xml
index b7500f713..ddca94ce0 100644
--- a/plugins/portlet/pom.xml
+++ b/plugins/portlet/pom.xml
@@ -3,7 +3,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-portlet-plugin
diff --git a/plugins/rest/pom.xml b/plugins/rest/pom.xml
index 0867ddea3..f4fb1237f 100644
--- a/plugins/rest/pom.xml
+++ b/plugins/rest/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-rest-plugin
diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java
index f1fc41a0f..678a6f30e 100644
--- a/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java
+++ b/plugins/rest/src/main/java/org/apache/struts2/rest/RestActionMapper.java
@@ -320,7 +320,7 @@ public class RestActionMapper extends DefaultActionMapper {
mapping.setName(actionName);
if (allowDynamicMethodCalls) {
- mapping.setMethod(actionMethod);
+ mapping.setMethod(cleanupActionName(actionMethod));
} else {
mapping.setMethod(null);
}
diff --git a/plugins/sitegraph/pom.xml b/plugins/sitegraph/pom.xml
index 8f6302f3c..3eb549cd3 100644
--- a/plugins/sitegraph/pom.xml
+++ b/plugins/sitegraph/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-sitegraph-plugin
diff --git a/plugins/sitemesh/pom.xml b/plugins/sitemesh/pom.xml
index a6b800104..239d403da 100644
--- a/plugins/sitemesh/pom.xml
+++ b/plugins/sitemesh/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-sitemesh-plugin
diff --git a/plugins/spring/pom.xml b/plugins/spring/pom.xml
index 4e509f1e7..7ed9d45ba 100644
--- a/plugins/spring/pom.xml
+++ b/plugins/spring/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-spring-plugin
diff --git a/plugins/testng/pom.xml b/plugins/testng/pom.xml
index a45a17f74..709e402eb 100644
--- a/plugins/testng/pom.xml
+++ b/plugins/testng/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-testng-plugin
diff --git a/plugins/tiles/pom.xml b/plugins/tiles/pom.xml
index 0b964af9d..e6bc1b7f8 100644
--- a/plugins/tiles/pom.xml
+++ b/plugins/tiles/pom.xml
@@ -26,7 +26,7 @@
org.apache.struts
struts2-plugins
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
struts2-tiles-plugin
diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsApplicationResource.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsApplicationResource.java
index 6884e9a42..4ff5b5470 100644
--- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsApplicationResource.java
+++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsApplicationResource.java
@@ -52,4 +52,8 @@ public class StrutsApplicationResource extends PostfixedApplicationResource {
return 0;
}
+ @Override
+ public String toString() {
+ return "Resource " + getLocalePath() + " at " + url.toString();
+ }
}
diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java
index fe90d75a2..a8e77cec8 100644
--- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java
+++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java
@@ -19,6 +19,7 @@
package org.apache.struts2.tiles;
+import com.opensymphony.xwork2.util.TextParseUtil;
import ognl.OgnlException;
import ognl.OgnlRuntime;
import ognl.PropertyAccessor;
@@ -71,6 +72,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
/**
* Dedicated Struts factory to build Tiles container with support for:
@@ -176,25 +178,28 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory {
@Override
protected List getSources(ApplicationContext applicationContext) {
- Collection resources = applicationContext.getResources(getTilesDefinitionPattern(applicationContext.getInitParams()));
+ Collection resources = new ArrayList<>();
+
+ Set definitions = getTilesDefinitions(applicationContext.getInitParams());
+ for (String definition : definitions) {
+ resources.addAll(applicationContext.getResources(definition));
+ }
List filteredResources = new ArrayList<>();
- if (resources != null) {
- for (ApplicationResource resource : resources) {
- if (Locale.ROOT.equals(resource.getLocale())) {
- filteredResources.add(resource);
- }
+ for (ApplicationResource resource : resources) {
+ if (Locale.ROOT.equals(resource.getLocale())) {
+ filteredResources.add(resource);
}
}
return filteredResources;
}
- protected String getTilesDefinitionPattern(Map params) {
+ protected Set getTilesDefinitions(Map params) {
if (params.containsKey(DefinitionsFactory.DEFINITIONS_CONFIG)) {
- return params.get(DefinitionsFactory.DEFINITIONS_CONFIG);
+ return TextParseUtil.commaDelimitedStringToSet(params.get(DefinitionsFactory.DEFINITIONS_CONFIG));
}
- return TILES_DEFAULT_PATTERN;
+ return TextParseUtil.commaDelimitedStringToSet(TILES_DEFAULT_PATTERN);
}
protected ELAttributeEvaluator createELEvaluator(ApplicationContext applicationContext) {
diff --git a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java
index 70a21ed22..df6152bd5 100644
--- a/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java
+++ b/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsWildcardServletApplicationContext.java
@@ -54,8 +54,12 @@ public class StrutsWildcardServletApplicationContext extends ServletApplicationC
for (Object path : context.getResourcePaths("/")) {
try {
- URL url = new File(context.getRealPath(String.valueOf(path))).toURI().toURL();
- urls.add(url);
+ String realPath = context.getRealPath(String.valueOf(path));
+
+ if (realPath != null) {
+ URL url = new File(realPath).toURI().toURL();
+ urls.add(url);
+ }
} catch (MalformedURLException e) {
throw new ConfigurationException(e);
}
diff --git a/pom.xml b/pom.xml
index 8a24fd09c..323cf9e56 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
4.0.0
struts2-parent
- 2.5-SNAPSHOT
+ 2.5.1-SNAPSHOT
pom
Struts 2
http://struts.apache.org/
@@ -85,7 +85,7 @@
${project.version}
4.1.6.RELEASE
- 3.1.2
+ 3.1.4
3.3
5.0.2
3.0.5
@@ -706,7 +706,7 @@
commons-collections
commons-collections
- 3.2.1
+ 3.2.2
commons-fileupload