Compare commits

...

64 Commits

Author SHA1 Message Date
Lukasz Lenart 1ed29d508f [maven-release-plugin] prepare release STRUTS_2_3_32 2017-03-06 12:03:06 +01:00
Lukasz Lenart 3523064939 Uses default error key if specified key doesn't exist 2017-03-06 11:56:39 +01:00
Lukasz Lenart 54dff362f5 Adds additional example URLs to check if validation works properly 2016-11-25 19:35:15 +01:00
Lukasz Lenart b12864dd38 [maven-release-plugin] prepare for next development iteration 2016-10-05 08:53:34 +02:00
Lukasz Lenart de90290354 [maven-release-plugin] prepare release STRUTS_2_3_31 2016-10-05 08:53:19 +02:00
Lukasz Lenart ba0563183b Fixes issues in config-browse plugin 2016-09-28 11:42:24 +02:00
Lukasz Lenart b348fc552c WW-4674 Uses the same logic as in Dispatcher to control handling exception 2016-09-16 16:37:29 +02:00
Lukasz Lenart 81371e09c5 WW-4685 Adjusts cherry pick to 2.3.x 2016-09-16 16:07:59 +02:00
Lukasz Lenart 431e50e922 WW-4685 Uses dedicated prefixes to access I18N and Struts internals 2016-09-16 16:00:45 +02:00
Lukasz Lenart 156db8e5df WW-4685 Supports evaluating expressions from tiles definitions as a Struts values 2016-09-16 16:00:27 +02:00
Lukasz Lenart 6f5ddca471 WW-4667 Applies params to all instances of interceptor defined in stack 2016-09-06 09:07:02 +02:00
Lukasz Lenart cc0d52f216 WW-4663 Checks if expression is null to avoid NPE 2016-09-02 13:57:15 +02:00
Lukasz Lenart 23e0181328 WW-4669 Returns default action/method instead of throwing exception 2016-08-30 09:20:41 +02:00
Lukasz Lenart 030ffa3354 Disables params evaluation when creating results by convention 2016-08-17 15:36:20 +02:00
Lukasz Lenart 8e67b9144a Adds double check if resource exists 2016-08-17 15:36:20 +02:00
Lukasz Lenart 77017cd677 Allows modify params on coping 2016-08-17 15:36:20 +02:00
cnenning 7d8c3598ef merged fix for WW-4628 (proper url decoding of query-string) 2016-08-03 13:28:00 +02:00
cnenning 83bb64f4c2 WW-4628: new issues were introduced by last change, restoring old behavior and ignoring new tests 2016-08-01 15:42:36 +02:00
cnenning ae2840f183 merged fix for WW-4628 (avoid double encoding of url parameters) 2016-08-01 13:50:23 +02:00
Lukasz Lenart e8b48f8bb4 WW-4601 Hides webconsole when not in devMode 2016-07-08 06:44:12 +02:00
Lukasz Lenart 3243448084 [maven-release-plugin] prepare for next development iteration 2016-07-07 08:32:14 +02:00
Lukasz Lenart 5c61c9a575 [maven-release-plugin] prepare release STRUTS_2_3_30 2016-07-07 08:31:52 +02:00
Lukasz Lenart e40dcaa3f4 Uses the latest OGNL version 2016-06-29 20:24:57 +02:00
Lukasz Lenart ab6acd2382 Cleans up test 2016-06-26 22:04:23 +02:00
Lukasz Lenart bf0a01d390 Upgrades OGNL to latest version 2016-06-26 22:02:32 +02:00
Lukasz Lenart 00c47b7ce6 WW-4648 Upgrades commons-fileupload to the latest version 2016-06-22 10:56:31 +02:00
Lukasz Lenart c84810ff82 Adds test to guard pre-evaulation of name attribute 2016-06-22 10:46:09 +02:00
Lukasz Lenart 2ea59b31b4 Drops commented out test 2016-06-22 10:38:39 +02:00
Lukasz Lenart fae1e0e799 Uses LocaleProvider and default TextProvider instead of evaluating expression 2016-06-22 10:38:12 +02:00
Lukasz Lenart e4ce3ce839 Reverts dropping name pre-evaluation 2016-06-22 08:55:42 +02:00
Lukasz Lenart 730441b7a7 [maven-release-plugin] prepare for next development iteration 2016-06-14 07:11:10 +02:00
Lukasz Lenart bb22c585b5 [maven-release-plugin] prepare release STRUTS_2_3_29 2016-06-14 07:10:57 +02:00
Lukasz Lenart eccc31ebce Improves validation RegEx 2016-06-14 06:53:36 +02:00
Lukasz Lenart 1c92a8b2c9 Reverts previous RegEx 2016-06-03 13:12:02 +02:00
Lukasz Lenart b28b78c062 Introduces new callMethod() function to be used to execute actions 2016-06-03 13:10:58 +02:00
Lukasz Lenart 8d172b8e9b Upgrades to latest OGNL version 2016-06-03 13:08:51 +02:00
Lukasz Lenart 88b885339a Drops pre-evaluation of name 2016-06-02 16:57:44 +02:00
Lukasz Lenart 3f526d630a Drops unneeded method 2016-06-02 16:46:40 +02:00
Lukasz Lenart 34025eafec Allows empty string as a action name 2016-05-23 17:04:38 +02:00
Lukasz Lenart 54e8bf1f75 Disallows dot in action name 2016-05-23 16:02:25 +02:00
Lukasz Lenart 9f2cae2f1e WW-4627 Adds unit test to confirm the issue 2016-05-13 08:00:04 +02:00
Lukasz Lenart 9bcd1bc9f6 WW-4626 Adds support for .cat domain 2016-05-13 07:40:25 +02:00
Lukasz Lenart f052398cd2 WW-4618 Supports custom redirect types which base on ServletRedirectResult 2016-05-13 07:04:50 +02:00
Lukasz Lenart 237432512d Throws away methods that doesn't match pattern 2016-05-12 15:40:04 +02:00
Lukasz Lenart ca25476120 Upgrades commons-collections 2016-05-05 10:46:56 +02:00
Aleksandr Mashchenko 731fde544c WW-4630 - <s:submit> generates a value attribute for type=image which violates W3C (cherry picked from commit c4d2b687be8bdb454a11c5376bb475a8fa7f9c67​) 2016-05-04 23:00:33 +03:00
Lukasz Lenart 76eb8f38a3 Cleans up method name 2016-04-29 08:40:03 +02:00
Lukasz Lenart deefeffd11 Cleans up method name 2016-04-20 08:01:29 +02:00
Lukasz Lenart 98d2692e43 Drops defining location via request 2016-04-20 08:01:22 +02:00
Lukasz Lenart 46517afb14 Adds additional blocked classes 2016-04-20 08:01:12 +02:00
Lukasz Lenart 5190b53673 Uses isSequence flag to block chained expressions 2016-04-20 08:01:02 +02:00
Lukasz Lenart d36f31b3e1 Upgrades OGNL 2016-04-20 08:00:53 +02:00
Lukasz Lenart cbae13a6a8 Reverts 098ee502b4 2016-04-11 16:30:38 +02:00
Lukasz Lenart 865f1f2784 Adds support for deprecated param name 2016-04-08 10:26:21 +02:00
Aleksandr Mashchenko 5ce807aaea WW-4622 - Adds fallback to static config definitions to allow work in restricted envs (cherry picked from 6770b35), getRealPath NPE check; WW-4623, WW-4624 - Adds support for multiple tiles defintions (cherry picked from c12cd61) 2016-04-06 19:36:13 +03:00
Lukasz Lenart 17dab897d9 Uses proper doctype version 2016-04-04 11:21:54 +02:00
Lukasz Lenart 45fa8d0320 Adds missing closing tags 2016-04-04 11:21:37 +02:00
Lukasz Lenart 6fee2eb1a4 [maven-release-plugin] prepare for next development iteration 2016-03-18 20:50:53 +01:00
Lukasz Lenart 0ac8932aa3 [maven-release-plugin] prepare release STRUTS_2_3_28 2016-03-18 20:50:41 +01:00
Lukasz Lenart 6b497ef8f7 WW-4605 Reverts to previous flow when result is created just before executing it 2016-03-18 20:41:06 +01:00
Lukasz Lenart 519c767114 [maven-release-plugin] prepare for next development iteration 2016-03-18 08:54:43 +01:00
Lukasz Lenart 8a59ed02c9 [maven-release-plugin] prepare release STRUTS_2_3_27 2016-03-18 08:54:31 +01:00
Lukasz Lenart f48c30eaa7 Adds proper logic to exclude MemberAccess 2016-03-18 08:45:13 +01:00
Lukasz Lenart 94c4462658 [maven-release-plugin] prepare for next development iteration 2016-03-14 11:39:11 +01:00
113 changed files with 862 additions and 264 deletions
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-blank</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-jboss-blank</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-mailreader</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-portlet</artifactId>
@@ -5,11 +5,11 @@ Here you'll find examples of what is possible with the Struts Portlet integratio
<ul>
<li><a href="<s:url action="formExample"/>">A simple form</a></li>
<li><a href="<s:url action="formExamplePrg" method="input"/>">Form example with proper PRG</a></li>
<li><a href="<s:url action="formExampleModelDriven" method="input"/>">Model driven example</li>
<li><a href="<s:url action="formExampleModelDriven" method="input"/>">Model driven example</a>/li>
<li><a href="<s:url action="validationExample"/>">Validation</a></li>
<li><a href="<s:url action="tokenExample"/>">Token</a></li>
<li><a href="<s:url action="springExample"/>">Spring integration</a></li>
<li><a href="<s:url action="fileUpload" method="input"/>">File upload</li>
<li><a href="<s:url action="fileUpload" method="input"/>">File upload</a></li>
<li><a href="<s:url action="freeMarkerExample"/>">FreeMarker</a></li>
<li><a href="<s:url action="velocityHelloWorld"/>">Velocity</a></li>
<li><a href="<s:url action="index" namespace="/tiles"/>">Form Example Validation with Tiles</a></li>
+2 -2
View File
@@ -26,12 +26,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-showcase</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-archetypes</artifactId>
@@ -2,7 +2,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-archetypes</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-archetypes</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -2,7 +2,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-archetypes</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -2,7 +2,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-archetypes</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -2,7 +2,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-archetypes</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -2,7 +2,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-archetypes</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-archetypes</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-assembly</artifactId>
+3 -3
View File
@@ -10,7 +10,7 @@
</parent>
<artifactId>struts2-bom</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
<packaging>pom</packaging>
<name>Struts 2 Bill of Materials</name>
@@ -25,7 +25,7 @@
</licenses>
<properties>
<struts-version.version>2.3.26</struts-version.version>
<struts-version.version>2.3.32</struts-version.version>
</properties>
<build>
@@ -197,6 +197,6 @@
</dependencyManagement>
<scm>
<tag>STRUTS_2_3_26</tag>
<tag>STRUTS_2_3_32</tag>
</scm>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-core</artifactId>
<packaging>jar</packaging>
@@ -272,6 +272,13 @@ public final class StrutsConstants {
/** actions names' whitelist **/
public static final String STRUTS_ALLOWED_ACTION_NAMES = "struts.allowed.action.names";
/** default action name to use when action didn't match the whitelist **/
public static final String STRUTS_DEFAULT_ACTION_NAME = "struts.default.action.name";
/** methods names' whitelist **/
public static final String STRUTS_ALLOWED_METHOD_NAMES = "struts.allowed.method.names";
/** default method name to use when method didn't match the whitelist **/
public static final String STRUTS_DEFAULT_METHOD_NAME = "struts.default.method.name";
/** enables action: prefix **/
public static final String STRUTS_MAPPER_ACTION_PREFIX_ENABLED = "struts.mapper.action.prefix.enabled";
@@ -22,14 +22,12 @@
package org.apache.struts2.components;
import java.io.Writer;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import org.apache.struts2.StrutsException;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.LocaleProvider;
import com.opensymphony.xwork2.TextProviderFactory;
import com.opensymphony.xwork2.TextProvider;
@@ -95,6 +93,8 @@ public class I18n extends Component {
protected String name;
protected Container container;
private TextProvider textProvider;
private TextProvider defaultTextProvider;
private LocaleProvider localeProvider;
public I18n(ValueStack stack) {
super(stack);
@@ -105,26 +105,31 @@ public class I18n extends Component {
this.container = container;
}
@Inject
public void setTextProvider(TextProvider textProvider) {
this.defaultTextProvider = textProvider;
}
@Inject
public void setLocaleProvider(LocaleProvider localeProvider) {
this.localeProvider = localeProvider;
}
public boolean start(Writer writer) {
boolean result = super.start(writer);
try {
String name = this.findString(this.name, "name", "Resource bundle name is required. Example: foo or foo_en");
ResourceBundle bundle = (ResourceBundle) findValue("getTexts('" + name + "')");
ResourceBundle bundle = defaultTextProvider.getTexts(name);
if (bundle == null) {
bundle = LocalizedTextUtil.findResourceBundle(name, (Locale) getStack().getContext().get(ActionContext.LOCALE));
bundle = LocalizedTextUtil.findResourceBundle(name, localeProvider.getLocale());
}
if (bundle != null) {
final Locale locale = (Locale) getStack().getContext().get(ActionContext.LOCALE);
TextProviderFactory tpf = new TextProviderFactory();
container.inject(tpf);
textProvider = tpf.createInstance(bundle, new LocaleProvider() {
public Locale getLocale() {
return locale;
}
});
textProvider = tpf.createInstance(bundle, localeProvider);
getStack().push(textProvider);
pushed = true;
}
@@ -22,6 +22,8 @@ package org.apache.struts2.dispatcher;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.StrutsConstants;
@@ -39,6 +41,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.LinkedList;
import java.util.StringTokenizer;
/**
@@ -93,6 +96,7 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
*/
protected String encoding;
protected boolean devMode;
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
@@ -101,29 +105,34 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
* New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
public void setServeStaticContent(String val) {
serveStatic = "true".equals(val);
public void setServeStaticContent(String serveStaticContent) {
this.serveStatic = BooleanUtils.toBoolean(serveStaticContent);
}
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE
* setting.
*
* @param val
* @param serveStaticBrowserCache
* New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
public void setServeStaticBrowserCache(String val) {
serveStaticBrowserCache = "true".equals(val);
public void setServeStaticBrowserCache(String serveStaticBrowserCache) {
this.serveStaticBrowserCache = BooleanUtils.toBoolean(serveStaticBrowserCache);
}
/**
* Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
* @param val New setting
* @param encoding New setting
*/
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public void setEncoding(String val) {
encoding = val;
public void setEncoding(String encoding) {
this.encoding = encoding;
}
@Inject(StrutsConstants.STRUTS_DEVMODE)
public void setDevMode(String devMode) {
this.devMode = Boolean.parseBoolean(devMode);
}
/*
@@ -141,7 +150,16 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
}
protected String getAdditionalPackages() {
return "org.apache.struts2.static template org.apache.struts2.interceptor.debugging static";
List<String> packages = new LinkedList<String>();
packages.add("org.apache.struts2.static");
packages.add("template");
packages.add("static");
if (devMode) {
packages.add("org.apache.struts2.interceptor.debugging");
}
return StringUtils.join(packages.iterator(), ' ');
}
/**
@@ -273,7 +291,7 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
* @param name resource name
* @param packagePrefix The package prefix to use to locate the resource
* @return full path
* @throws UnsupportedEncodingException
* @throws UnsupportedEncodingException If there is a encoding problem
*/
protected String buildPath(String name, String packagePrefix) throws UnsupportedEncodingException {
String resourcePath;
@@ -211,7 +211,11 @@ public class Dispatcher {
*/
@Inject(StrutsConstants.STRUTS_DEVMODE)
public void setDevMode(String mode) {
devMode = "true".equals(mode);
devMode = Boolean.parseBoolean(mode);
}
public boolean isDevMode() {
return devMode;
}
/**
@@ -265,6 +269,10 @@ public class Dispatcher {
this.handleException = Boolean.parseBoolean(handleException);
}
public boolean isHandleException() {
return handleException;
}
@Inject
public void setDispatcherErrorHandler(DispatcherErrorHandler errorHandler) {
this.errorHandler = errorHandler;
@@ -33,6 +33,7 @@ import org.apache.commons.lang3.StringUtils;
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;
@@ -120,6 +121,11 @@ public class DefaultActionMapper implements ActionMapper {
protected boolean alwaysSelectFullNamespace = false;
protected PrefixTrie prefixTrie = null;
protected Pattern allowedActionNames = Pattern.compile("[a-zA-Z0-9._!/\\-]*");
protected String defaultActionName = "index";
protected Pattern allowedMethodNames = Pattern.compile("[a-zA-Z_]*[0-9]*");
protected String defaultMethodName = "execute";
private boolean allowActionPrefix = false;
private boolean allowActionCrossNamespaceAccess = false;
@@ -136,7 +142,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(cleanupMethodName(key.substring(METHOD_PREFIX.length())));
}
}
});
@@ -148,7 +154,7 @@ public class DefaultActionMapper implements ActionMapper {
if (allowDynamicMethodCalls) {
int bang = name.indexOf('!');
if (bang != -1) {
String method = name.substring(bang + 1);
String method = cleanupMethodName(name.substring(bang + 1));
mapping.setMethod(method);
name = name.substring(0, bang);
}
@@ -204,6 +210,21 @@ public class DefaultActionMapper implements ActionMapper {
this.allowedActionNames = Pattern.compile(allowedActionNames);
}
@Inject(value = StrutsConstants.STRUTS_DEFAULT_ACTION_NAME, required = false)
public void setDefaultActionName(String defaultActionName) {
this.defaultActionName = defaultActionName;
}
@Inject(value = StrutsConstants.STRUTS_ALLOWED_METHOD_NAMES, required = false)
public void setAllowedMethodNames(String allowedMethodNames) {
this.allowedMethodNames = Pattern.compile(allowedMethodNames);
}
@Inject(value = StrutsConstants.STRUTS_DEFAULT_METHOD_NAME, required = false)
public void setDefaultMethodName(String defaultMethodName) {
this.defaultMethodName = defaultMethodName;
}
@Inject(value = StrutsConstants.STRUTS_MAPPER_ACTION_PREFIX_ENABLED)
public void setAllowActionPrefix(String allowActionPrefix) {
this.allowActionPrefix = "true".equalsIgnoreCase(allowActionPrefix);
@@ -375,7 +396,7 @@ public class DefaultActionMapper implements ActionMapper {
}
/**
* Cleans up action name from suspicious characters
* Checks action name against allowed pattern if not matched returns default action name
*
* @param rawActionName action name extracted from URI
* @return safe action name
@@ -384,18 +405,23 @@ public class DefaultActionMapper implements ActionMapper {
if (allowedActionNames.matcher(rawActionName).matches()) {
return rawActionName;
} else {
if (LOG.isWarnEnabled()) {
LOG.warn("Action [#0] does not match allowed action names pattern [#1], cleaning it up!",
rawActionName, allowedActionNames);
}
String cleanActionName = rawActionName;
for (String chunk : allowedActionNames.split(rawActionName)) {
cleanActionName = cleanActionName.replace(chunk, "");
}
if (LOG.isDebugEnabled()) {
LOG.debug("Cleaned action name [#0]", cleanActionName);
}
return cleanActionName;
LOG.warn("{} did not match allowed action names {} - default action {} will be used!", rawActionName, allowedActionNames, defaultActionName);
return defaultActionName;
}
}
/**
* Checks method name (when DMI is enabled) against allowed pattern if not matched returns default action name
*
* @param rawMethodName method name extracted from URI
* @return safe method name
*/
protected String cleanupMethodName(final String rawMethodName) {
if (allowedMethodNames.matcher(rawMethodName).matches()) {
return rawMethodName;
} else {
LOG.warn("{} did not match allowed method names {} - default method {} will be used!", rawMethodName, allowedMethodNames, defaultMethodName);
return defaultMethodName;
}
}
@@ -120,7 +120,11 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
if (LOG.isDebugEnabled()) {
LOG.debug("Preparing error message for key: [#0]", errorKey);
}
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
if (LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, null, new Object[0]) == null) {
return LocalizedTextUtil.findText(this.getClass(), "struts.messages.error.uploading", defaultLocale, null, new Object[] { e.getMessage() });
} else {
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, null, args);
}
}
protected void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException {
@@ -539,7 +539,11 @@ public class JakartaStreamMultiPartRequest implements MultiPartRequest {
String errorKey = "struts.message.upload.error." + e.getClass().getSimpleName();
if (LOG.isDebugEnabled())
LOG.debug("Preparing error message for key: [#0]", errorKey);
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
if (LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, null, new Object[0]) == null) {
return LocalizedTextUtil.findText(this.getClass(), "struts.messages.error.uploading", defaultLocale, null, new Object[] { e.getMessage() });
} else {
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, null, args);
}
}
/**
@@ -108,7 +108,11 @@ public class MultiPartRequestWrapper extends StrutsRequestWrapper {
if (LOG.isDebugEnabled()) {
LOG.debug("Preparing error message for key: [#0]", errorKey);
}
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
if (LocalizedTextUtil.findText(this.getClass(), errorKey, getLocale(), null, new Object[0]) == null) {
return LocalizedTextUtil.findText(this.getClass(), "struts.messages.error.uploading", defaultLocale, null, new Object[] { e.getMessage() });
} else {
return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, null, args);
}
}
/**
@@ -168,7 +168,9 @@ public class PrepareOperations {
request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);
}
} catch (Exception ex) {
dispatcher.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
if (dispatcher.isHandleException() || dispatcher.isDevMode()) {
dispatcher.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
}
}
}
@@ -21,10 +21,12 @@ package org.apache.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletActionRedirectResult;
import org.apache.struts2.dispatcher.ServletRedirectResult;
import java.util.Map;
@@ -68,7 +70,10 @@ class MessageStorePreResultListener implements PreResultListener {
boolean isRedirect = false;
try {
isRedirect = invocation.getResult() instanceof ServletRedirectResult;
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);
}
@@ -44,11 +44,11 @@ public class ComponentUtils {
* @return true if it is an expression
*/
public static boolean isExpression(String expr) {
return expr.startsWith("%{") && expr.endsWith("}");
return expr != null && expr.startsWith("%{") && expr.endsWith("}");
}
public static boolean containsExpression(String expr) {
return expr.contains("%{") && expr.contains("}");
return expr != null && expr.contains("%{") && expr.contains("}");
}
}
@@ -19,4 +19,16 @@ public class URLDecoderUtil {
return UDecoder.URLDecode(sequence, charset);
}
/**
* Decodes a <code>x-www-form-urlencoded</code> string.
* @param sequence the String to decode
* @param charset The name of a supported character encoding.
* @param isQueryString whether input is a query string. If <code>true</code> other decoding rules apply.
* @return the newly decoded <code>String</code>
* @exception IllegalArgumentException If the encoding is not valid
*/
public static String decode(String sequence, String charset, boolean isQueryString) {
return UDecoder.URLDecode(sequence, charset, isQueryString);
}
}
@@ -24,6 +24,18 @@ package org.apache.struts2.views.util;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.StrutsConstants;
@@ -179,9 +191,9 @@ public class DefaultUrlHelper implements UrlHelper {
//if the action was not explicitly set grab the params from the request
if (escapeAmp) {
buildParametersString(params, link, AMP);
buildParametersString(params, link, AMP, true);
} else {
buildParametersString(params, link, "&");
buildParametersString(params, link, "&", true);
}
String result = link.toString();
@@ -202,6 +214,10 @@ public class DefaultUrlHelper implements UrlHelper {
}
public void buildParametersString(Map<String, Object> params, StringBuilder link, String paramSeparator) {
buildParametersString(params, link, paramSeparator, true);
}
public void buildParametersString(Map<String, Object> params, StringBuilder link, String paramSeparator, boolean encode) {
if ((params != null) && (params.size() > 0)) {
if (!link.toString().contains("?")) {
link.append("?");
@@ -219,7 +235,7 @@ public class DefaultUrlHelper implements UrlHelper {
if (value instanceof Iterable) {
for (Iterator iterator = ((Iterable) value).iterator(); iterator.hasNext();) {
Object paramValue = iterator.next();
link.append(buildParameterSubstring(name, paramValue != null ? paramValue.toString() : StringUtils.EMPTY));
link.append(buildParameterSubstring(name, paramValue != null ? paramValue.toString() : StringUtils.EMPTY, encode));
if (iterator.hasNext()) {
link.append(paramSeparator);
@@ -229,14 +245,14 @@ public class DefaultUrlHelper implements UrlHelper {
Object[] array = (Object[]) value;
for (int i = 0; i < array.length; i++) {
Object paramValue = array[i];
link.append(buildParameterSubstring(name, paramValue != null ? paramValue.toString() : StringUtils.EMPTY));
link.append(buildParameterSubstring(name, paramValue != null ? paramValue.toString() : StringUtils.EMPTY, encode));
if (i < array.length - 1) {
link.append(paramSeparator);
}
}
} else {
link.append(buildParameterSubstring(name, value != null ? value.toString() : StringUtils.EMPTY));
link.append(buildParameterSubstring(name, value != null ? value.toString() : StringUtils.EMPTY, encode));
}
if (iter.hasNext()) {
@@ -250,11 +266,11 @@ public class DefaultUrlHelper implements UrlHelper {
return HTTP_PROTOCOL.equals(scheme) || HTTPS_PROTOCOL.equals(scheme);
}
private String buildParameterSubstring(String name, String value) {
private String buildParameterSubstring(String name, String value, boolean encode) {
StringBuilder builder = new StringBuilder();
builder.append(encode(name));
builder.append(encode ? encode(name) : name);
builder.append('=');
builder.append(encode(value));
builder.append(encode ? encode(value) : value);
return builder.toString();
}
@@ -283,7 +299,7 @@ public class DefaultUrlHelper implements UrlHelper {
*/
public String decode( String input ) {
try {
return URLDecoderUtil.decode(input, encoding);
return URLDecoderUtil.decode(input, encoding, false);
} catch (Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Could not decode URL parameter '#0', returning value un-decoded", input);
@@ -292,6 +308,22 @@ public class DefaultUrlHelper implements UrlHelper {
}
}
/**
* Decodes the URL using {@link URLDecoderUtil#decode(String, String, boolean)} with the encoding specified in the configuration.
*
* @param input the input to decode
* @param isQueryString whether input is a query string. If <code>true</code> other decoding rules apply.
* @return the encoded string
*/
public String decode( String input, boolean isQueryString ) {
try {
return URLDecoderUtil.decode(input, encoding, isQueryString);
} catch (Exception e) {
LOG.warn("Could not decode URL parameter '{}', returning value un-decoded", input);
return input;
}
}
public Map<String, Object> parseQueryString(String queryString, boolean forceValueArray) {
Map<String, Object> queryParams = new LinkedHashMap<String, Object>();
if (queryString != null) {
@@ -308,8 +340,8 @@ public class DefaultUrlHelper implements UrlHelper {
paramValue = tmpParams[1];
}
if (paramName != null) {
paramName = decode(paramName);
String translatedParamValue = decode(paramValue);
paramName = decode(paramName, true);
String translatedParamValue = decode(paramValue, true);
if (queryParams.containsKey(paramName) || forceValueArray) {
// WW-1619 append new param value to existing value(s)
@@ -448,12 +448,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");
+4 -1
View File
@@ -46,10 +46,13 @@
java.lang.Class,
java.lang.ClassLoader,
java.lang.Shutdown,
java.lang.ProcessBuilder,
ognl.OgnlContext,
ognl.MemberAccess,
ognl.ClassResolver,
ognl.TypeConverter,
ognl.MemberAccess,
ognl.DefaultMemberAccess,
com.opensymphony.xwork2.ognl.SecurityMemberAccess,
com.opensymphony.xwork2.ActionContext" />
<!-- this must be valid regex, each '.' in package name must be escaped! -->
@@ -61,6 +61,9 @@
</#if>
<#else>
<input type="submit"<#rt/>
<#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>
@@ -164,21 +164,4 @@ public class UIBeanTest extends StrutsInternalTestCase {
assertEquals("12", txtFld.getTheme());
}
// I couldn't figure out how to make this test work. Bailing for now.
// public void testEscapeLabel() throws Exception {
// ValueStack stack = ActionContext.getContext().getValueStack();
// MockHttpServletRequest req = new MockHttpServletRequest();
// MockHttpServletResponse res = new MockHttpServletResponse();
// stack.push(this);
//
// TextField txtFld = new TextField(stack, req, res);
// txtFld.setKey("test['foo']");
// txtFld.evaluateParams();
// assertEquals("test_label", txtFld.getParameters().get("label"));
// }
//
// public String getText(String key) {
// assertEquals("test[\\'foo\\']", key);
// return "test_label";
// }
}
@@ -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.dispatcher.StrutsResultSupport;
import org.apache.struts2.views.jsp.StrutsMockHttpServletRequest;
@@ -162,8 +163,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
public void testGetMappingWithNamespaceSlash() throws Exception {
req.setupGetRequestURI("/my.hh/abc.action");
req.setupGetServletPath("/my.hh/abc.action");
req.setupGetRequestURI("/my-hh/abc.action");
req.setupGetServletPath("/my-hh/abc.action");
req.setupGetAttribute(null);
req.addExpectedGetAttributeName("javax.servlet.include.servlet_path");
@@ -180,7 +181,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
mapping = mapper.getMapping(req, configManager);
assertEquals("", mapping.getNamespace());
assertEquals("my.hh/abc", mapping.getName());
assertEquals("my-hh/abc", mapping.getName());
}
public void testGetMappingWithUnknownNamespace() throws Exception {
@@ -845,13 +846,13 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals(actionName, mapper.cleanupActionName(actionName));
actionName = "${action}";
assertEquals("action", mapper.cleanupActionName(actionName));
assertEquals(mapper.defaultActionName, mapper.cleanupActionName(actionName));
actionName = "${${%{action}}}";
assertEquals("action", mapper.cleanupActionName(actionName));
assertEquals(mapper.defaultActionName, mapper.cleanupActionName(actionName));
actionName = "${#foo='action',#foo}";
assertEquals("fooactionfoo", mapper.cleanupActionName(actionName));
assertEquals(mapper.defaultActionName, mapper.cleanupActionName(actionName));
actionName = "test-action";
assertEquals("test-action", mapper.cleanupActionName(actionName));
@@ -863,4 +864,19 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("test!bar.action", mapper.cleanupActionName(actionName));
}
public void testAllowedMethodNames() throws Exception {
DefaultActionMapper mapper = new DefaultActionMapper();
assertEquals("", mapper.cleanupMethodName(""));
assertEquals("test", mapper.cleanupMethodName("test"));
assertEquals("test_method", mapper.cleanupMethodName("test_method"));
assertEquals("_test", mapper.cleanupMethodName("_test"));
assertEquals("test1", mapper.cleanupMethodName("test1"));
assertEquals(mapper.defaultMethodName, mapper.cleanupMethodName("2test"));
assertEquals(mapper.defaultMethodName, mapper.cleanupMethodName("%{exp}"));
assertEquals(mapper.defaultMethodName, mapper.cleanupMethodName("${%{foo}}"));
assertEquals(mapper.defaultMethodName, mapper.cleanupMethodName("${#foo='method',#foo}"));
}
}
@@ -4,9 +4,13 @@ import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.mock.MockActionProxy;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsInternalTestCase;
import org.apache.struts2.dispatcher.ServletActionRedirectResult;
import org.apache.struts2.dispatcher.ServletRedirectResult;
import org.easymock.EasyMock;
import javax.servlet.http.HttpServletRequest;
@@ -138,8 +142,13 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
EasyMock.expectLastCall().andReturn(action);
EasyMock.expectLastCall().anyTimes();
mockActionInvocation.getResult();
EasyMock.expectLastCall().andReturn(new ServletActionRedirectResult());
mockActionInvocation.getProxy();
MockActionProxy actionProxy = new MockActionProxy();
ResultConfig resultConfig = new ResultConfig.Builder(Action.SUCCESS, ServletRedirectResult.class.getName()).build();
ActionConfig actionConfig = new ActionConfig.Builder("", "test", action.getClass().getName()).addResultConfig(resultConfig).build();
actionProxy.setConfig(actionConfig);
EasyMock.expectLastCall().andReturn(actionProxy);
EasyMock.expectLastCall().anyTimes();
EasyMock.replay(mockActionInvocation);
@@ -213,8 +222,13 @@ public class MessageStorePreResultListenerTest extends StrutsInternalTestCase {
mockActionInvocation.getAction();
EasyMock.expectLastCall().andReturn(action);
mockActionInvocation.getResult();
EasyMock.expectLastCall().andReturn(new ServletActionRedirectResult());
mockActionInvocation.getProxy();
MockActionProxy actionProxy = new MockActionProxy();
ResultConfig resultConfig = new ResultConfig.Builder(Action.SUCCESS, ServletRedirectResult.class.getName()).build();
ActionConfig actionConfig = new ActionConfig.Builder("", "test", action.getClass().getName()).addResultConfig(resultConfig).build();
actionProxy.setConfig(actionConfig);
EasyMock.expectLastCall().andReturn(actionProxy);
EasyMock.expectLastCall().anyTimes();
EasyMock.replay(mockActionInvocation);
@@ -93,6 +93,10 @@ public class ComponentUtilsTest extends StrutsInternalTestCase {
assertFalse(actual);
}
public void testIsExpressionIsFalseWhenNull() throws Exception {
assertFalse(ComponentUtils.isExpression(null));
}
public void testContainsExpressionIsTrue() throws Exception {
// given
String anExpression = "%{foo}";
@@ -125,6 +129,10 @@ public class ComponentUtilsTest extends StrutsInternalTestCase {
// then
assertFalse(actual);
}
public void testContainsExpressionIsFalseWhenNull() throws Exception {
assertFalse(ComponentUtils.containsExpression(null));
}
}
class MockConfigurationProvider implements ConfigurationProvider {
@@ -68,4 +68,11 @@ public class URLDecoderUtilTest {
assertEquals("xxxx\u00ea", result);
}
@Test
public void testURLDecodePlusCharAsSpace() {
String result = URLDecoderUtil.decode("a+b", "UTF-8", true);
assertEquals("a b", result);
}
}
@@ -179,8 +179,7 @@ public class ActionTagTest extends AbstractTagTest {
assertTrue(stack.getContext().containsKey(ServletActionContext.PAGE_CONTEXT));
assertTrue(stack.getContext().get(ServletActionContext.PAGE_CONTEXT)instanceof PageContext);
assertNotNull(result);
assertFalse(result.isExecuted());
assertNull(result); // result is never executed, hence never set into invocation
}
public void testExecuteButResetReturnSameInvocation() throws Exception {
@@ -657,8 +657,7 @@ public class URLTagTest extends AbstractUITagTest {
tag.doEndTag();
Object allowMethodAccess = stack.findValue("\u0023_memberAccess['allowStaticMethodAccess']");
assertNotNull(allowMethodAccess);
assertEquals(Boolean.FALSE, allowMethodAccess);
assertNull(allowMethodAccess);
assertNull(session.get("foo"));
@@ -237,7 +237,7 @@ public class SubmitTest extends AbstractUITagTest {
tag.doStartTag();
tag.doEndTag();
assertEquals("<input type=\"submit\" id=\"myname\" name=\"myname\" value=\"Submit\"/>", writer.toString().trim());
assertEquals("<input type=\"submit\" value=\"Submit\" id=\"myname\" name=\"myname\"/>", writer.toString().trim());
}
/**
@@ -281,4 +281,20 @@ public class TextfieldTest extends AbstractUITagTest {
verify(TextFieldTag.class.getResource("Textfield-11.txt"));
}
public void testNameEvaluation() throws Exception {
TestAction testAction = (TestAction) action;
testAction.setArray(new String[]{"test", "bar"});
testAction.setFooInt(1);
TextFieldTag tag = new TextFieldTag();
tag.setPageContext(pageContext);
tag.setName("array[%{fooInt}]");
tag.doStartTag();
tag.doEndTag();
verify(TextFieldTag.class.getResource("Textfield-12.txt"));
}
}
@@ -21,21 +21,23 @@
package org.apache.struts2.views.util;
import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Scope.Strategy;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsInternalTestCase;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsInternalTestCase;
import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Scope.Strategy;
/**
* Test case for DefaultUrlHelper.
@@ -393,7 +395,15 @@ public class DefaultUrlHelperTest extends StrutsInternalTestCase {
assertEquals(result, expectedResult);
}
public void testDecodeSpacesInQueryString() throws Exception {
Map<String, Object> queryParameters = urlHelper.parseQueryString("name=value+with+space", false);
assertTrue(queryParameters.containsKey("name"));
assertEquals("value with space", queryParameters.get("name"));
}
public void setUp() throws Exception {
super.setUp();
stubContainer = new StubContainer(container);
@@ -1,3 +1,3 @@
<tr>
<td colspan="2"><div align="left"><input type="submit" id="myname" name="myname" value="bar" disabled="disabled" tabindex="1"/></div></td>
<td colspan="2"><div align="left"><input type="submit" value="bar" id="myname" name="myname" disabled="disabled" tabindex="1"/></div></td>
</tr>
@@ -1,3 +1,3 @@
<tr>
<td colspan="2"><div align="right"><input type="submit" id="myname" name="myname" value="Submit" title="mytitle"/></div></td>
<td colspan="2"><div align="right"><input type="submit" value="Submit" id="myname" name="myname" title="mytitle"/></div></td>
</tr>
@@ -1,3 +1,3 @@
<tr>
<td colspan="2"><div align="right"><input type="image" alt="bar" id="myname" name="myname" value="bar" disabled="disabled"/></div></td>
<td colspan="2"><div align="right"><input type="image" alt="bar" id="myname" name="myname" disabled="disabled"/></div></td>
</tr>
@@ -1,3 +1,3 @@
<tr>
<td colspan="2"><div align="right"><input type="image" alt="mylabel" src="some.gif" id="myname" name="myname" value="bar"/></div></td>
<td colspan="2"><div align="right"><input type="image" alt="mylabel" src="some.gif" id="myname" name="myname"/></div></td>
</tr>
@@ -0,0 +1,4 @@
<tr>
<td class="tdLabel"></td>
<td><input type="text" name="array[1]" value="bar" id="array_1_"/></td>
</tr>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-codebehind-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-config-browser-plugin</artifactId>
@@ -50,6 +50,7 @@ public class ShowBeansAction extends ActionNamesAction {
@Inject
public void setContainer(Container container) {
super.setContainer(container);
bindings = new TreeMap<String, Set<Binding>>();
bindings.put(ObjectFactory.class.getName(), addBindings(container, ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY));
bindings.put(XWorkConverter.class.getName(), addBindings(container, XWorkConverter.class, StrutsConstants.STRUTS_XWORKCONVERTER));
@@ -36,6 +36,7 @@ public class ShowConstantsAction extends ActionNamesAction {
@Inject
public void setContainer(Container container) {
super.setContainer(container);
constants = new HashMap<String, String>();
for (String key : container.getInstanceNames(String.class)) {
constants.put(key, container.getInstance(String.class, key));
@@ -22,7 +22,7 @@
-->
<#include "tigris-macros.ftl">
<@startPage pageTitle="Actions in namespace"/>
<h3>Actions in <#if namespace == ""> default namespace <#else> ${namespace} </#if></h3>
<h3>Actions in <#if namespace == ""> default namespace <#else> ${namespace?html} </#if></h3>
<table>
<tr>
<td>
@@ -29,7 +29,7 @@
<tr><td>Action name:</td><td>${actionName}</td></tr>
<tr><td>Namespace:</td><td> ${namespace}</td></tr>
<tr><td>Action class:</td><td> ${config.className}</td></tr>
<tr><td>Action method:</td><td> <#if config.methodName?exists>${config.methodName}</#if></td></tr>
<tr><td>Action method:</td><td> <#if config.methodName??>${config.methodName}</#if></td></tr>
<tr><td>Parameters:</td><td> <#list config.params?keys as p>
${p}
</#list></td></tr>
@@ -41,9 +41,9 @@
</table>
<!-- URLTag is faulty -->
<@s.url id="url" action="showConfig" includeParams="none">
<@s.param name="namespace">${namespace}</@s.param>
<@s.param name="actionName">${actionName}</@s.param>
<@s.url var="url" action="showConfig" includeParams="none">
<@s.param name="namespace">${namespace?html}</@s.param>
<@s.param name="actionName">${actionName?html}</@s.param>
</@s.url>
<#assign url = url + "&amp;detailView=">
<!-- Set all to false -->
@@ -25,7 +25,7 @@
<#call startPage pageTitle="Validator Details"/>
<table>
<tr><td>Validated Class:</td><td>${action.stripPackage(clazz)}</td></tr>
<tr><td>Context:</td><td>${context}</td></tr>
<tr><td>Context:</td><td>${context?html}</td></tr>
<tr><td>Validator Number:</td><td>${selected}</td></tr>
<tr><td>Validator Type:</td><td>${action.stripPackage(selectedValidator.class)}</td></tr>
</table>
+1 -1
View File
@@ -3,7 +3,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-convention-plugin</artifactId>
@@ -43,6 +43,7 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
import javax.servlet.ServletContext;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -332,27 +333,34 @@ public class ConventionUnknownHandler implements UnknownHandler {
Map<String, ResultTypeConfig> resultsByExtension) {
try {
boolean traceEnabled = LOG.isTraceEnabled();
if (traceEnabled)
if (traceEnabled) {
LOG.trace("Checking ServletContext for [#0]", path);
}
if (servletContext.getResource(path) != null) {
if (traceEnabled)
LOG.trace("Found");
URL resource = servletContext.getResource(path);
if (resource != null && resource.getPath().endsWith(path)) {
if (traceEnabled) {
LOG.trace("Found resource #0", resource);
}
return buildResult(path, resultCode, resultsByExtension.get(ext), actionContext);
}
if (traceEnabled)
LOG.trace("Checking ClasLoader for #0", path);
if (traceEnabled) {
LOG.trace("Checking ClassLoader for #0", path);
}
String classLoaderPath = path.startsWith("/") ? path.substring(1, path.length()) : path;
if (ClassLoaderUtil.getResource(classLoaderPath, getClass()) != null) {
if (traceEnabled)
LOG.trace("Found");
resource = ClassLoaderUtil.getResource(classLoaderPath, getClass());
if (resource != null && resource.getPath().endsWith(classLoaderPath)) {
if (traceEnabled) {
LOG.trace("Found resource #0", resource);
}
return buildResult(path, resultCode, resultsByExtension.get(ext), actionContext);
}
} catch (MalformedURLException e) {
if (LOG.isErrorEnabled())
if (LOG.isErrorEnabled()) {
LOG.error("Unable to parse template path: [#0] skipping...", path);
}
}
return null;
@@ -107,14 +107,26 @@ public class ConventionsServiceImpl implements ConventionsService {
public Map<String, ResultTypeConfig> getResultTypesByExtension(PackageConfig packageConfig) {
Map<String, ResultTypeConfig> results = packageConfig.getAllResultTypeConfigs();
ResultTypeConfig dispatcher = disableParse(results.get("dispatcher"));
ResultTypeConfig velocity = disableParse(results.get("velocity"));
ResultTypeConfig freemarker = disableParse(results.get("freemarker"));
Map<String, ResultTypeConfig> resultsByExtension = new HashMap<String, ResultTypeConfig>();
resultsByExtension.put("jsp", results.get("dispatcher"));
resultsByExtension.put("jspf", results.get("dispatcher"));
resultsByExtension.put("jspx", results.get("dispatcher"));
resultsByExtension.put("vm", results.get("velocity"));
resultsByExtension.put("ftl", results.get("freemarker"));
resultsByExtension.put("html", results.get("dispatcher"));
resultsByExtension.put("htm", results.get("dispatcher"));
resultsByExtension.put("jsp", dispatcher);
resultsByExtension.put("jspf", dispatcher);
resultsByExtension.put("jspx", dispatcher);
resultsByExtension.put("vm", velocity);
resultsByExtension.put("ftl", freemarker);
resultsByExtension.put("html", dispatcher);
resultsByExtension.put("htm", dispatcher);
return resultsByExtension;
}
private ResultTypeConfig disableParse(ResultTypeConfig resultConfig) {
if (resultConfig != null) {
return new ResultTypeConfig.Builder(resultConfig).addParam("parse", "false").build();
}
return null;
}
}
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<artifactId>struts2-plugins</artifactId>
<groupId>org.apache.struts</groupId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-jasperreports-plugin</artifactId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-java8-support-plugin</artifactId>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-jsf-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-json-plugin</artifactId>
@@ -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<String> errors = new ArrayList<String>();
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<String> errors;
public List<String> getErrors() {
return errors;
}
public void setErrors(List<String> errors) {
this.errors = errors;
}
}
private class AnnotatedBean extends Bean{
private URL url;
@@ -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"
}
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-pell-multipart-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-rest-plugin</artifactId>
@@ -112,6 +112,7 @@ public class RestActionMapper extends DefaultActionMapper {
private boolean allowDynamicMethodCalls = false;
public RestActionMapper() {
this.defaultMethodName = indexMethodName;
}
public String getIdParameterName() {
@@ -290,7 +291,7 @@ public class RestActionMapper extends DefaultActionMapper {
fullName = fullName.substring(0, lastSlashPos);
}
mapping.setName(fullName);
mapping.setName(cleanupActionName(fullName));
}
return mapping;
}
@@ -311,7 +312,7 @@ public class RestActionMapper extends DefaultActionMapper {
mapping.setName(actionName);
if (allowDynamicMethodCalls) {
mapping.setMethod(actionMethod);
mapping.setMethod(cleanupMethodName(actionMethod));
} else {
mapping.setMethod(null);
}
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-struts1-plugin</artifactId>
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</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.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-tiles-plugin</artifactId>
@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts2.tiles;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.LocaleProvider;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.TextProviderFactory;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.tiles.context.TilesRequestContext;
import org.apache.tiles.evaluator.AbstractAttributeEvaluator;
import org.apache.tiles.servlet.context.ServletUtil;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public class I18NAttributeEvaluator extends AbstractAttributeEvaluator {
private static final Logger LOG = LoggerFactory.getLogger(I18NAttributeEvaluator.class);
public Object evaluate(String expression, TilesRequestContext request) {
Object result = expression;
HttpServletRequest httpRequest = ServletUtil.getServletRequest(request).getRequest();
ActionContext ctx = ServletActionContext.getActionContext(httpRequest);
if (ctx == null) {
LOG.error("Cannot obtain HttpServletRequest from [{}]", request.getClass().getName());
throw new ConfigurationException("There is no ActionContext for current request!");
}
TextProviderFactory tpf = new TextProviderFactory();
ctx.getContainer().inject(tpf);
LocaleProvider localeProvider = ctx.getContainer().getInstance(LocaleProvider.class);
TextProvider textProvider = tpf.createInstance(ctx.getActionInvocation().getAction().getClass(), localeProvider);
if (textProvider != null) {
LOG.debug("Trying find text [{}] using TextProvider {}", expression, textProvider);
result = textProvider.getText(expression);
}
return result;
}
public void init(Map<String, String> initParameters) {
}
}
@@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts2.tiles;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import ognl.OgnlException;
import org.apache.struts2.ServletActionContext;
import org.apache.tiles.context.TilesRequestContext;
import org.apache.tiles.evaluator.AbstractAttributeEvaluator;
import org.apache.tiles.evaluator.EvaluationException;
import org.apache.tiles.servlet.context.ServletUtil;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public class StrutsAttributeEvaluator extends AbstractAttributeEvaluator {
private static final Logger LOG = LoggerFactory.getLogger(StrutsAttributeEvaluator.class);
public Object evaluate(String expression, TilesRequestContext request) {
try {
HttpServletRequest httpRequest = ServletUtil.getServletRequest(request).getRequest();
ActionContext ctx = ServletActionContext.getActionContext(httpRequest);
if (ctx == null) {
LOG.error("Cannot obtain HttpServletRequest from [{}]", request.getClass().getName());
throw new ConfigurationException("There is no ActionContext for current request!");
}
OgnlUtil ognlUtil = ctx.getContainer().getInstance(OgnlUtil.class);
LOG.debug("Trying evaluate expression [{}] using OgnlUtil's getValue", expression);
Object result = ognlUtil.getValue(expression, ctx.getContextMap(), ctx.getValueStack().getRoot());
LOG.debug("Final result of evaluating expression [{}] is: {}", expression, result);
return result;
} catch (OgnlException e) {
throw new EvaluationException(e);
}
}
public void init(Map<String, String> initParameters) {
}
}
@@ -63,6 +63,8 @@ import org.apache.tiles.renderer.impl.ChainedDelegateAttributeRenderer;
import org.apache.tiles.servlet.context.ServletUtil;
import org.apache.tiles.util.URLUtil;
import com.opensymphony.xwork2.util.TextParseUtil;
import javax.el.ArrayELResolver;
import javax.el.BeanELResolver;
import javax.el.CompositeELResolver;
@@ -73,6 +75,7 @@ import javax.el.ResourceBundleELResolver;
import javax.servlet.ServletContext;
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -80,9 +83,10 @@ import java.util.Set;
/**
* Dedicated Struts factory to build Tiles container with support for:
* - Freemarker
* - OGNL (as default)
* - I18N using Struts resource bundles
* - S2 ro access Struts' ValueStack
* - OGNL
* - EL
* - Wildcards
*
* If you need additional features create your own listener and factory,
* you can base on code from Tiles' CompleteAutoloadTilesContainerFactory
@@ -105,6 +109,14 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory {
*/
public static final String TILES_DEFAULT_PATTERN = "tiles*.xml";
/**
* Supported expression languages
*/
public static final String OGNL = "OGNL";
public static final String EL = "EL";
public static final String S2 = "S2";
public static final String I18N = "I18N";
@Override
protected BasicTilesContainer instantiateContainer(TilesApplicationContext applicationContext) {
CachingTilesContainer tilesContainer = new CachingTilesContainer();
@@ -179,8 +191,14 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory {
LocaleResolver resolver) {
BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory(new DirectAttributeEvaluator());
attributeEvaluatorFactory.registerAttributeEvaluator("OGNL", createOGNLEvaluator());
attributeEvaluatorFactory.registerAttributeEvaluator("EL", createELEvaluator(applicationContext));
attributeEvaluatorFactory.registerAttributeEvaluator(S2, createStrutsEvaluator());
attributeEvaluatorFactory.registerAttributeEvaluator(I18N, createI18NEvaluator());
attributeEvaluatorFactory.registerAttributeEvaluator(OGNL, createOGNLEvaluator());
ELAttributeEvaluator elEvaluator = createELEvaluator(applicationContext);
if (elEvaluator != null) {
attributeEvaluatorFactory.registerAttributeEvaluator(EL, elEvaluator);
}
return attributeEvaluatorFactory;
}
@@ -201,7 +219,12 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory {
@Override
protected List<URL> getSourceURLs(TilesApplicationContext applicationContext, TilesRequestContextFactory contextFactory) {
try {
Set<URL> finalSet = applicationContext.getResources(getTilesDefinitionPattern(applicationContext.getInitParams()));
Set<URL> finalSet = new HashSet<URL>();
Set<String> definitions = getTilesDefinitions(applicationContext.getInitParams());
for (String definition : definitions) {
finalSet.addAll(applicationContext.getResources(definition));
}
return URLUtil.getBaseTilesDefinitionURLs(finalSet);
} catch (IOException e) {
@@ -209,11 +232,14 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory {
}
}
protected String getTilesDefinitionPattern(Map<String, String> params) {
protected Set<String> getTilesDefinitions(Map<String, String> 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;
if (params.containsKey(BasicTilesContainer.DEFINITIONS_CONFIG)) {
return TextParseUtil.commaDelimitedStringToSet(params.get(BasicTilesContainer.DEFINITIONS_CONFIG));
}
return TextParseUtil.commaDelimitedStringToSet(TILES_DEFAULT_PATTERN);
}
protected ELAttributeEvaluator createELEvaluator(TilesApplicationContext applicationContext) {
@@ -241,6 +267,14 @@ public class StrutsTilesContainerFactory extends BasicTilesContainerFactory {
return evaluator;
}
protected StrutsAttributeEvaluator createStrutsEvaluator() {
return new StrutsAttributeEvaluator();
}
protected I18NAttributeEvaluator createI18NEvaluator() {
return new I18NAttributeEvaluator();
}
protected OGNLAttributeEvaluator createOGNLEvaluator() {
try {
PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class);
@@ -22,7 +22,10 @@ package org.apache.struts2.tiles;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.definition.DefinitionsFactory;
import org.apache.tiles.factory.AbstractTilesContainerFactory;
import org.apache.tiles.impl.BasicTilesContainer;
import org.apache.tiles.servlet.context.ServletTilesApplicationContext;
import org.apache.tiles.startup.AbstractTilesInitializer;
import javax.servlet.ServletContext;
@@ -33,8 +36,20 @@ public class StrutsTilesInitializer extends AbstractTilesInitializer {
@Override
protected TilesApplicationContext createTilesApplicationContext(TilesApplicationContext preliminaryContext) {
LOG.debug("Initializing Tiles wildcard support ...");
return new StrutsWildcardServletTilesApplicationContext((ServletContext) preliminaryContext.getContext());
ServletContext servletContext = (ServletContext) preliminaryContext.getContext();
if (isStaticDefinition(servletContext)) {
LOG.trace("Found definitions config in web.xml, using standard Servlet support ....");
return new ServletTilesApplicationContext(servletContext);
} else {
LOG.trace("Initializing Struts Tiles wildcard support ...");
return new StrutsWildcardServletTilesApplicationContext(servletContext);
}
}
protected boolean isStaticDefinition(ServletContext servletContext) {
return servletContext.getInitParameter(DefinitionsFactory.DEFINITIONS_CONFIG) != null ||
servletContext.getInitParameter(BasicTilesContainer.DEFINITIONS_CONFIG) != null;
}
@Override
@@ -50,8 +50,12 @@ public class StrutsWildcardServletTilesApplicationContext extends ServletTilesAp
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);
}
+1 -1
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<artifactId>struts2-tiles3-plugin</artifactId>
+5 -5
View File
@@ -9,7 +9,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>struts2-parent</artifactId>
<version>2.3.26</version>
<version>2.3.32</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_3_26</tag>
<tag>STRUTS_2_3_32</tag>
</scm>
<issueManagement>
@@ -86,7 +86,7 @@
<properties>
<currentVersion>${project.version}</currentVersion>
<struts2.springPlatformVersion>3.0.5.RELEASE</struts2.springPlatformVersion>
<ognl.version>3.0.13</ognl.version>
<ognl.version>3.0.19</ognl.version>
<asm.version>3.3</asm.version>
<asm5.version>5.0.2</asm5.version>
<tiles.version>2.2.2</tiles.version>
@@ -759,12 +759,12 @@
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.3.26</version>
<version>2.3.32</version>
</parent>
<groupId>org.apache.struts.xwork</groupId>

Some files were not shown because too many files have changed in this diff Show More