diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100755
index 000000000..d475a89ce
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,110 @@
+/*
+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.
+*/
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100755
index 000000000..08ebbb67f
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100755
index 000000000..42fa4da21
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip
\ No newline at end of file
diff --git a/README.md b/README.md
index 7cc25411c..a17ccdaee 100644
--- a/README.md
+++ b/README.md
@@ -28,9 +28,9 @@ The Apache Struts web framework is a free open-source solution for creating Java
## Documentation
-More information can be found on the [homepage](https://struts.apache.org/). Please read the [Security Guide](https://struts.apache.org/security/)
+More information can be found on the [homepage](https://struts.apache.org/). Please read the [Security Guide](https://struts.apache.org/security/),
and the [JavaDocs](https://struts.apache.org/maven/struts2-core/apidocs/index.html) can be browsed.
-Questions related to the usage of the Apache Struts should be posted to the [user mailing list](https://struts.apache.org/mail.html).
+Questions related to the usage of Apache Struts should be posted to the [user mailing list](https://struts.apache.org/mail.html).
## Description
@@ -43,13 +43,15 @@ In practice, we find that unless these concerns are separated, larger applicatio
One way to separate concerns in a software application is to use a Model-View-Controller (MVC) architecture. The Model
represents the business or database code, the View represents the page design code, and the Controller represents
the navigational code. The Struts framework is designed to help developers create web applications that utilize
-a MVC architecture.
+an MVC architecture.
The framework provides three key components:
-A “request” handler provided by the application developer that is mapped to a standard URI. A “response” handler that
-transfers control to another resource which completes the response. A tag library that helps developers create interactive
-form-based applications with server pages. The framework’s architecture and tags are buzzword compliant. Struts works well
+- A “request” handler provided by the application developer that is mapped to a standard URI.
+- A “response” handler that transfers control to another resource which completes the response.
+- A tag library that helps developers create interactive form-based applications with server pages.
+
+The framework’s architecture and tags are buzzword compliant. Struts works well
with conventional REST applications and with technologies like SOAP and AJAX.
## The Apache Struts Project
@@ -65,7 +67,7 @@ platform into a coherent whole. Our goal is to leverage existing standards by pr
enterprise-grade applications that are easy to maintain over time.
The Apache Struts Project offered two major versions of the Struts framework. Currently we are only maintaining the Struts 2
-version. It is recommended to upgrade all Struts 1.x application to Struts 2. Please do not start new application development
+version. It is recommended to upgrade all Struts 1.x applications to Struts 2. Please do not start new application development
using Struts 1.x, as we are no longer issuing security patches.
Struts 2 was originally known as WebWork 2. After working independently for several years, the WebWork and Struts
@@ -74,25 +76,25 @@ to difficult problems.
## Why should you use Apache Struts?
-Apache Struts is a modern, maintained and full-featured web framework. It has been there for years and give the huge user
-base it is unlikely it will go away anytime soon in the future. Not only that we have dedicated users and developers
-on the project. Apache Struts is licensed to the Apache License 2.0 and this will not change. We maintain a clean IP
+Apache Struts is a modern, maintained and full-featured web framework. As it has been around for years and grown a huge user
+base it is unlikely it will go away anytime soon. Not only that, we have dedicated users and developers
+on the project. Apache Struts is licensed under the Apache License 2.0 and this will not change. We maintain a clean IP
and you are “safe” to use the project. Sometimes you are not “safe” to use a project when a company controls the SCM.
Access to Source Code doesn’t mean it is free. With Apache Struts, you are not only free to “do what you want with it”,
-you can even contribute (which is not always the case). And best of it: you can become a part of the core team too.
+you can even contribute (which is not always the case). And best of all: you can become a part of the core team too.
It is usually very easy to integrate other technologies with Apache Struts. If you are using an ORM like Apache Cayenne,
-Hibernate or JDBC you will not have any restrictions. Apache Struts is not even tied too much to a frontend technology.
+Hibernate or JDBC, you will not have any restrictions. Apache Struts is not even tied too much to a frontend technology.
In old days it was JSP, then came Velocity and Freemarker. Nowadays you might build your web application with just static
-HTML and AngularJS. Or you want to use Sitemesh or Tiles. This all is no problem due to Struts elegant and easy to use
+HTML and AngularJS. Or you might want to use Sitemesh or Tiles. This all is no problem due to Struts' elegant and easy-to-use
extension mechanisms.
-Unlike other, component oriented frameworks, we do not aim to hide the stateless nature of the web. We think it is
+Unlike other, component-oriented frameworks, we do not aim to hide the stateless nature of the web. We think it is
perfectly acceptable to build upon a Request/Response cycle. We also think the MVC pattern is not so bad, just because
it is old. In fact, we believe the Apache Struts architecture is clean and easy to understand.
-Of course, if you wish to build components on the server side which render on the front end side, you are most likely
-wrong with Struts. This is a different approach which promises to reduce the amount of HTML/JavaScript knowledge needed
+Of course, if you wish to build components on the server side which render on the front end side, you will most likely
+not want Struts. This is a different approach which promises to reduce the amount of HTML/JavaScript knowledge needed
and to create reusable components for the view layer. Projects like Wicket and Tapestry serve this purpose very well.
-As with every framework you need to decide if it makes sense for you to build components or if you are better with
-the Struts-approach.
+As with every framework, you need to decide if it makes sense for you to build components or if you prefer
+the Struts approach.
diff --git a/assembly/pom.xml b/assembly/pom.xml
index 9db215a0c..4a72c940e 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -111,7 +111,7 @@
make-assembly
package
- attached
+ single
diff --git a/assembly/src/main/resources/docs-urls.txt b/assembly/src/main/resources/docs-urls.txt
index 845dab8cf..d96c3ea23 100644
--- a/assembly/src/main/resources/docs-urls.txt
+++ b/assembly/src/main/resources/docs-urls.txt
@@ -1,6 +1,6 @@
-http://struts.apache.org/getting-started/
-http://struts.apache.org/security/
-http://struts.apache.org/core-developers/
-http://struts.apache.org/tag-developers/
-http://struts.apache.org/maven-archetypes/
-http://struts.apache.org/plugins/
+https://struts.apache.org/getting-started/
+https://struts.apache.org/security/
+https://struts.apache.org/core-developers/
+https://struts.apache.org/tag-developers/
+https://struts.apache.org/maven-archetypes/
+https://struts.apache.org/plugins/
diff --git a/core/pom.xml b/core/pom.xml
index 17d57ea02..c4a723cbf 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -178,25 +178,6 @@
-
- default-tools.jar
-
-
- java.vendor
- Sun Microsystems Inc.
-
-
-
-
- com.sun
- tools
- 1.5.0
- system
- ${java.home}/../lib/tools.jar
-
-
-
-
diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java b/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
index 1550eb98f..b84289746 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java
@@ -201,13 +201,10 @@ public class ActionChainResult implements Result {
* @param invocation the DefaultActionInvocation calling the action call stack
*/
public void execute(ActionInvocation invocation) throws Exception {
- // if the finalNamespace wasn't explicitly defined, assume the current one
- if (this.namespace == null) {
- this.namespace = invocation.getProxy().getNamespace();
- }
-
ValueStack stack = ActionContext.getContext().getValueStack();
- String finalNamespace = TextParseUtil.translateVariables(namespace, stack);
+ String finalNamespace = this.namespace != null
+ ? TextParseUtil.translateVariables(namespace, stack)
+ : invocation.getProxy().getNamespace();
String finalActionName = TextParseUtil.translateVariables(actionName, stack);
String finalMethodName = this.methodName != null
? TextParseUtil.translateVariables(this.methodName, stack)
diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/CollectionConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/CollectionConverter.java
index 730e4af8b..b7f707f40 100644
--- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/CollectionConverter.java
+++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/CollectionConverter.java
@@ -21,7 +21,6 @@ package com.opensymphony.xwork2.conversion.impl;
import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer;
import com.opensymphony.xwork2.conversion.TypeConverter;
import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.util.XWorkList;
import java.lang.reflect.Member;
import java.util.Collection;
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/XWorkList.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkList.java
similarity index 98%
rename from core/src/main/java/com/opensymphony/xwork2/util/XWorkList.java
rename to core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkList.java
index 666ff5f1e..38da102be 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/XWorkList.java
+++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkList.java
@@ -16,13 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package com.opensymphony.xwork2.util;
+package com.opensymphony.xwork2.conversion.impl;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.conversion.TypeConverter;
-import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java
index 011361431..040080824 100644
--- a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java
@@ -150,8 +150,8 @@ public class PrefixMethodInvocationUtil {
public static Method getPrefixedMethod(String[] prefixes, String methodName, Object action) {
assert(prefixes != null);
String capitalizedMethodName = capitalizeMethodName(methodName);
- for (String prefixe : prefixes) {
- String prefixedMethodName = prefixe + capitalizedMethodName;
+ for (String prefix : prefixes) {
+ String prefixedMethodName = prefix + capitalizedMethodName;
try {
return action.getClass().getMethod(prefixedMethodName, EMPTY_CLASS_ARRAY);
}
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 808efef9d..c44cf6f4a 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -61,14 +61,20 @@ public class OgnlUtil {
private boolean enableExpressionCache = true;
private boolean enableEvalExpression;
- private Set> excludedClasses = Collections.emptySet();
- private Set excludedPackageNamePatterns = Collections.emptySet();
- private Set excludedPackageNames = Collections.emptySet();
+ private Set> excludedClasses;
+ private Set excludedPackageNamePatterns;
+ private Set excludedPackageNames;
private Container container;
private boolean allowStaticMethodAccess;
private boolean disallowProxyMemberAccess;
+ public OgnlUtil() {
+ excludedClasses = new HashSet<>();
+ excludedPackageNamePatterns = new HashSet<>();
+ excludedPackageNames = new HashSet<>();
+ }
+
@Inject
public void setXWorkConverter(XWorkConverter conv) {
this.defaultConverter = new OgnlTypeConverterWrapper(conv);
@@ -95,6 +101,13 @@ public class OgnlUtil {
@Inject(value = StrutsConstants.STRUTS_EXCLUDED_CLASSES, required = false)
public void setExcludedClasses(String commaDelimitedClasses) {
+ Set> excludedClasses = new HashSet<>();
+ excludedClasses.addAll(this.excludedClasses);
+ excludedClasses.addAll(parseExcludedClasses(commaDelimitedClasses));
+ this.excludedClasses = Collections.unmodifiableSet(excludedClasses);
+ }
+
+ private Set> parseExcludedClasses(String commaDelimitedClasses) {
Set classNames = TextParseUtil.commaDelimitedStringToSet(commaDelimitedClasses);
Set> classes = new HashSet<>();
@@ -106,11 +119,18 @@ public class OgnlUtil {
}
}
- excludedClasses = Collections.unmodifiableSet(classes);
+ return classes;
}
@Inject(value = StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false)
public void setExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) {
+ Set excludedPackageNamePatterns = new HashSet<>();
+ excludedPackageNamePatterns.addAll(this.excludedPackageNamePatterns);
+ excludedPackageNamePatterns.addAll(parseExcludedPackageNamePatterns(commaDelimitedPackagePatterns));
+ this.excludedPackageNamePatterns = Collections.unmodifiableSet(excludedPackageNamePatterns);
+ }
+
+ private Set parseExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) {
Set packagePatterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackagePatterns);
Set packageNamePatterns = new HashSet<>();
@@ -118,12 +138,19 @@ public class OgnlUtil {
packageNamePatterns.add(Pattern.compile(pattern));
}
- excludedPackageNamePatterns = Collections.unmodifiableSet(packageNamePatterns);
+ return packageNamePatterns;
}
@Inject(value = StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAMES, required = false)
public void setExcludedPackageNames(String commaDelimitedPackageNames) {
- excludedPackageNames = Collections.unmodifiableSet(TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackageNames));
+ Set excludedPackageNames = new HashSet<>();
+ excludedPackageNames.addAll(this.excludedPackageNames);
+ excludedPackageNames.addAll(parseExcludedPackageNames(commaDelimitedPackageNames));
+ this.excludedPackageNames = Collections.unmodifiableSet(excludedPackageNames);
+ }
+
+ private Set parseExcludedPackageNames(String commaDelimitedPackageNames) {
+ return TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackageNames);
}
public Set> getExcludedClasses() {
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
index 05db70fc9..2002669f2 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
@@ -81,29 +81,31 @@ public class SecurityMemberAccess implements MemberAccess {
@Override
public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
LOG.debug("Checking access for [target: {}, member: {}, property: {}]", target, member, propertyName);
-
+
+ Class targetClass = target.getClass();
+ Class memberClass = member.getDeclaringClass();
+
if (checkEnumAccess(target, member)) {
- LOG.trace("Allowing access to enum: {}", target);
+ LOG.trace("Allowing access to enum: target class [{}] of target [{}], member [{}]", targetClass, target, member);
return true;
}
- Class targetClass = target.getClass();
- Class memberClass = member.getDeclaringClass();
-
if (Modifier.isStatic(member.getModifiers()) && allowStaticMethodAccess) {
- LOG.debug("Support for accessing static methods [target: {}, member: {}, property: {}] is deprecated!", target, member, propertyName);
+ LOG.debug("Support for accessing static methods [target: {}, targetClass: {}, member: {}, property: {}] is deprecated!",
+ target, targetClass, member, propertyName);
if (!isClassExcluded(member.getDeclaringClass())) {
targetClass = member.getDeclaringClass();
}
}
if (isPackageExcluded(targetClass.getPackage(), memberClass.getPackage())) {
- LOG.warn("Package of target [{}] or package of member [{}] are excluded!", target, member);
+ LOG.warn("Package [{}] of target class [{}] of target [{}] or package [{}] of member [{}] are excluded!", targetClass.getPackage(), targetClass,
+ target, memberClass.getPackage(), member);
return false;
}
if (isClassExcluded(targetClass)) {
- LOG.warn("Target class [{}] is excluded!", target);
+ LOG.warn("Target class [{}] of target [{}] is excluded!", targetClass, target);
return false;
}
@@ -113,7 +115,7 @@ public class SecurityMemberAccess implements MemberAccess {
}
if (disallowProxyMemberAccess && ProxyUtil.isProxyMember(member, target)) {
- LOG.warn("Access to proxy [{}] is blocked!", member);
+ LOG.warn("Access to proxy is blocked! Target class [{}] of target [{}], member [{}]", targetClass, target, member);
return false;
}
@@ -154,9 +156,9 @@ public class SecurityMemberAccess implements MemberAccess {
if (targetPackage == null || memberPackage == null) {
LOG.warn("The use of the default (unnamed) package is discouraged!");
}
-
- final String targetPackageName = targetPackage == null ? "" : targetPackage.getName();
- final String memberPackageName = memberPackage == null ? "" : memberPackage.getName();
+
+ String targetPackageName = targetPackage == null ? "" : targetPackage.getName();
+ String memberPackageName = memberPackage == null ? "" : memberPackage.getName();
for (Pattern pattern : excludedPackageNamePatterns) {
if (pattern.matcher(targetPackageName).matches() || pattern.matcher(memberPackageName).matches()) {
@@ -164,9 +166,11 @@ public class SecurityMemberAccess implements MemberAccess {
}
}
- for (String packageName : excludedPackageNames) {
- if (targetPackageName.startsWith(packageName) || targetPackageName.equals(packageName)
- || memberPackageName.startsWith(packageName) || memberPackageName.equals(packageName)) {
+ targetPackageName = targetPackageName + ".";
+ memberPackageName = memberPackageName + ".";
+
+ for (String packageName: excludedPackageNames) {
+ if (targetPackageName.startsWith(packageName) || memberPackageName.startsWith(packageName)) {
return true;
}
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java
index f5fe7e1df..21d6cc0ad 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java
@@ -70,7 +70,9 @@ public class DefaultFileManager implements FileManager {
return null;
}
InputStream is = openFile(fileUrl);
- monitorFile(fileUrl);
+ if (reloadingConfigs) {
+ monitorFile(fileUrl);
+ }
return is;
}
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java
index a0fea58c4..9fb05348e 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java
@@ -37,9 +37,7 @@ public class JarEntryRevision extends Revision {
private long lastModified;
public static Revision build(URL fileUrl, FileManager fileManager) {
- StrutsJarURLConnection conn = null;
- try {
- conn = StrutsJarURLConnection.openConnection(fileUrl);
+ try (StrutsJarURLConnection conn = StrutsJarURLConnection.openConnection(fileUrl)) {
conn.setUseCaches(false);
URL url = fileManager.normalizeToFileProtocol(fileUrl);
if (url != null) {
@@ -51,14 +49,6 @@ public class JarEntryRevision extends Revision {
LOG.warn("Could not create JarEntryRevision for [{}]!", fileUrl, e);
return null;
}
- finally {
- if(null != conn) {
- try {
- conn.getInputStream().close();
- } catch (IOException ignored) {
- }
- }
- }
}
private JarEntryRevision(URL jarFileURL, long lastModified) {
@@ -70,21 +60,12 @@ public class JarEntryRevision extends Revision {
}
public boolean needsReloading() {
- StrutsJarURLConnection conn = null;
long lastLastModified = lastModified;
- try {
- conn = StrutsJarURLConnection.openConnection(jarFileURL);
+ try (StrutsJarURLConnection conn = StrutsJarURLConnection.openConnection(jarFileURL)) {
conn.setUseCaches(false);
lastLastModified = conn.getJarEntry().getTime();
- } catch (IOException ignored) {
- }
- finally {
- if(null != conn) {
- try {
- conn.getInputStream().close();
- } catch (IOException ignored) {
- }
- }
+ } catch (Throwable e) {
+ LOG.warn("Could not check if needsReloading for [{}]!", jarFileURL, e);
}
return lastModified < lastLastModified;
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java
index 44a376aaf..e733ac7ce 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/fs/StrutsJarURLConnection.java
@@ -44,7 +44,7 @@ import java.util.jar.JarFile;
* While {@link JarURLConnection#parseSpecs(URL)} is private, then we had to extend {@link URLConnection} instead
* @since 2.5.15
*/
-class StrutsJarURLConnection extends URLConnection {
+class StrutsJarURLConnection extends URLConnection implements AutoCloseable {
private static final String FILE_URL_PREFIX = "file:";
private JarURLConnection jarURLConnection;
@@ -123,8 +123,8 @@ class StrutsJarURLConnection extends URLConnection {
Path tmpFile = Files.createTempFile("jar_cache", null);
try {
Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING);
- JarFile jarFile = new JarFile(tmpFile.toFile(), true, JarFile.OPEN_READ);
- tmpFile.toFile().deleteOnExit();
+ JarFile jarFile = new JarFile(tmpFile.toFile(), true, JarFile.OPEN_READ
+ | JarFile.OPEN_DELETE);
return jarFile;
} catch (Throwable thr) {
try {
@@ -171,6 +171,20 @@ class StrutsJarURLConnection extends URLConnection {
}
}
+ @Override
+ public void close() throws Exception {
+ try {
+ getInputStream().close();
+ } catch (IOException ignored) {
+ }
+ if (jarURLConnection == null) {
+ try {
+ jarFile.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+
static StrutsJarURLConnection openConnection(URL url) throws IOException {
return new StrutsJarURLConnection(url);
}
diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index d01e15088..81a4f803a 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -282,6 +282,11 @@ public final class StrutsConstants {
public static final String STRUTS_EXPRESSION_PARSER = "struts.expression.parser";
+ /** namespaces names' whitelist **/
+ public static final String STRUTS_ALLOWED_NAMESPACE_NAMES = "struts.allowed.namespace.names";
+ /** default namespace name to use when namespace didn't match the whitelist **/
+ public static final String STRUTS_DEFAULT_NAMESPACE_NAME = "struts.default.namespace.name";
+
/** 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 **/
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 224e36a7c..06c31d4b3 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
@@ -31,7 +31,6 @@ 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;
@@ -117,6 +116,10 @@ public class DefaultActionMapper implements ActionMapper {
protected boolean allowSlashesInActionNames = false;
protected boolean alwaysSelectFullNamespace = false;
protected PrefixTrie prefixTrie = null;
+
+ protected Pattern allowedNamespaceNames = Pattern.compile("[a-zA-Z0-9._/\\-]*");
+ protected String defaultNamespaceName = "/";
+
protected Pattern allowedActionNames = Pattern.compile("[a-zA-Z0-9._!/\\-]*");
protected String defaultActionName = "index";
@@ -202,6 +205,16 @@ public class DefaultActionMapper implements ActionMapper {
this.alwaysSelectFullNamespace = BooleanUtils.toBoolean(alwaysSelectFullNamespace);
}
+ @Inject(value = StrutsConstants.STRUTS_ALLOWED_NAMESPACE_NAMES, required = false)
+ public void setAllowedNamespaceNames(String allowedNamespaceNames) {
+ this.allowedNamespaceNames = Pattern.compile(allowedNamespaceNames);
+ }
+
+ @Inject(value = StrutsConstants.STRUTS_DEFAULT_NAMESPACE_NAME, required = false)
+ public void setDefaultNamespaceName(String defaultNamespaceName) {
+ this.defaultNamespaceName = defaultNamespaceName;
+ }
+
@Inject(value = StrutsConstants.STRUTS_ALLOWED_ACTION_NAMES, required = false)
public void setAllowedActionNames(String allowedActionNames) {
this.allowedActionNames = Pattern.compile(allowedActionNames);
@@ -389,10 +402,28 @@ public class DefaultActionMapper implements ActionMapper {
}
}
- mapping.setNamespace(namespace);
+ mapping.setNamespace(cleanupNamespaceName(namespace));
mapping.setName(cleanupActionName(name));
}
+ /**
+ * Checks namespace name against allowed pattern if not matched returns default namespace
+ *
+ * @param rawNamespace name extracted from URI
+ * @return safe namespace name
+ */
+ protected String cleanupNamespaceName(final String rawNamespace) {
+ if (allowedNamespaceNames.matcher(rawNamespace).matches()) {
+ return rawNamespace;
+ } else {
+ LOG.warn(
+ "{} did not match allowed namespace names {} - default namespace {} will be used!",
+ rawNamespace, allowedNamespaceNames, defaultNamespaceName
+ );
+ return defaultNamespaceName;
+ }
+ }
+
/**
* Checks action name against allowed pattern if not matched returns default action name
*
diff --git a/core/src/main/java/org/apache/struts2/result/PostbackResult.java b/core/src/main/java/org/apache/struts2/result/PostbackResult.java
index d040fbbb7..1a275d52e 100644
--- a/core/src/main/java/org/apache/struts2/result/PostbackResult.java
+++ b/core/src/main/java/org/apache/struts2/result/PostbackResult.java
@@ -134,6 +134,7 @@ public class PostbackResult extends StrutsResultSupport {
if (actionName != null) {
actionName = conditionalParse(actionName, invocation);
+ parseLocation = false;
if (namespace == null) {
namespace = invocation.getProxy().getNamespace();
} else {
diff --git a/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java b/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java
index b5356ad15..ed6825b12 100644
--- a/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java
+++ b/core/src/main/java/org/apache/struts2/result/ServletActionRedirectResult.java
@@ -159,6 +159,7 @@ public class ServletActionRedirectResult extends ServletRedirectResult implement
*/
public void execute(ActionInvocation invocation) throws Exception {
actionName = conditionalParse(actionName, invocation);
+ parseLocation = false;
if (namespace == null) {
namespace = invocation.getProxy().getNamespace();
} else {
diff --git a/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java b/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java
index a21e095d8..d5307d279 100644
--- a/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java
+++ b/core/src/main/java/org/apache/struts2/result/StrutsResultSupport.java
@@ -122,6 +122,8 @@ public abstract class StrutsResultSupport implements Result, StrutsStatics {
/** use UTF-8 as this is the recommended encoding by W3C to avoid incompatibilities. */
public static final String DEFAULT_URL_ENCODING = "UTF-8";
+ protected boolean parseLocation = true;
+
private boolean parse;
private boolean encode;
private String location;
@@ -200,7 +202,7 @@ public abstract class StrutsResultSupport implements Result, StrutsStatics {
* @throws Exception if an error occurs while executing the result.
*/
public void execute(ActionInvocation invocation) throws Exception {
- lastFinalLocation = conditionalParse(location, invocation);
+ lastFinalLocation = parseLocation ? conditionalParse(location, invocation) : location;
doExecute(lastFinalLocation, invocation);
}
diff --git a/core/src/main/resources/struts-default.xml b/core/src/main/resources/struts-default.xml
index b0fcdd81f..15cc5f9f7 100644
--- a/core/src/main/resources/struts-default.xml
+++ b/core/src/main/resources/struts-default.xml
@@ -45,11 +45,6 @@
java.lang.ClassLoader,
java.lang.Shutdown,
java.lang.ProcessBuilder,
- ognl.OgnlContext,
- ognl.ClassResolver,
- ognl.TypeConverter,
- ognl.MemberAccess,
- com.opensymphony.xwork2.ognl.SecurityMemberAccess,
com.opensymphony.xwork2.ActionContext" />
@@ -59,16 +54,16 @@
+ javassist.,
+ com.opensymphony.xwork2.ognl.,
+ com.opensymphony.xwork2.security.,
+ com.opensymphony.xwork2.util." />
diff --git a/core/src/test/java/com/opensymphony/xwork2/ChainResultTest.java b/core/src/test/java/com/opensymphony/xwork2/ChainResultTest.java
index 68def20c5..9c2208e44 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ChainResultTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ChainResultTest.java
@@ -72,6 +72,41 @@ public class ChainResultTest extends XWorkTestCase {
}
}
+ public void testWithNoNamespace() throws Exception {
+ ActionChainResult result = new ActionChainResult();
+ result.setActionName("${actionName}");
+
+ String expectedActionName = "testActionName";
+ String expectedNamespace = "${1-1}";
+ Map values = new HashMap<>();
+ values.put("actionName", expectedActionName);
+
+ ValueStack stack = ActionContext.getContext().getValueStack();
+ stack.push(values);
+
+ Mock actionProxyMock = new Mock(ActionProxy.class);
+ actionProxyMock.expect("execute");
+ actionProxyMock.expectAndReturn("getNamespace", expectedNamespace);
+ actionProxyMock.expectAndReturn("getActionName", expectedActionName);
+ actionProxyMock.expectAndReturn("getMethod", null);
+
+ ActionProxy actionProxy = (ActionProxy) actionProxyMock.proxy();
+ ActionProxyFactory testActionProxyFactory = new NamespaceActionNameTestActionProxyFactory(expectedNamespace, expectedActionName, actionProxy);
+ result.setActionProxyFactory(testActionProxyFactory);
+
+ Mock invocationMock = new Mock(ActionInvocation.class);
+ invocationMock.matchAndReturn("getProxy", actionProxy);
+ try {
+
+ ActionContext testContext = new ActionContext(stack.getContext());
+ ActionContext.setContext(testContext);
+ result.execute((ActionInvocation) invocationMock.proxy());
+ actionProxyMock.verify();
+ } finally {
+ ActionContext.setContext(null);
+ }
+ }
+
public void testRecursiveChain() throws Exception {
ActionProxy proxy = actionProxyFactory.createActionProxy("", "InfiniteRecursionChain", null, null);
@@ -88,7 +123,7 @@ public class ChainResultTest extends XWorkTestCase {
private String expectedActionName;
private String expectedNamespace;
- public NamespaceActionNameTestActionProxyFactory(String expectedNamespace, String expectedActionName, ActionProxy returnVal) {
+ NamespaceActionNameTestActionProxyFactory(String expectedNamespace, String expectedActionName, ActionProxy returnVal) {
this.expectedNamespace = expectedNamespace;
this.expectedActionName = expectedActionName;
this.returnVal = returnVal;
diff --git a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java
index 252e1ba6a..b66c2ff57 100644
--- a/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProviderTest.java
@@ -78,12 +78,14 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
}
public void testNeedsReload() throws Exception {
- container.getInstance(FileManagerFactory.class).setReloadingConfigs("true");
final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-actions.xml";
- ConfigurationProvider provider = buildConfigurationProvider(filename);
- container.getInstance(FileManagerFactory.class).setReloadingConfigs("true");
+ ConfigurationProvider provider = new XmlConfigurationProvider(filename, true);
+ container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(true);
+ container.inject(provider);
+ provider.init(configuration);
+ provider.loadPackages();
- assertTrue(!provider.needsReload()); // Revision exists and timestamp didn't change
+ assertFalse(provider.needsReload()); // Revision exists and timestamp didn't change
File file = new File(getClass().getResource("/" + filename).toURI());
assertTrue("not exists: " + file.toString(), file.exists());
@@ -92,6 +94,24 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
assertTrue(provider.needsReload());
}
+ public void testNeedsReloadNotReloadingConfigs() throws Exception {
+ final String filename = "com/opensymphony/xwork2/config/providers/xwork-test-actions.xml";
+ buildConfigurationProvider(filename);
+ ConfigurationProvider provider = new XmlConfigurationProvider(filename, true);
+ container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(false);
+ container.inject(provider);
+ provider.init(configuration);
+ provider.loadPackages();
+
+ assertFalse(provider.needsReload()); // Revision exists and timestamp didn't change
+
+ File file = new File(getClass().getResource("/" + filename).toURI());
+ assertTrue("not exists: " + file.toString(), file.exists());
+ changeFileTime(file);
+
+ assertFalse(provider.needsReload());
+ }
+
public void testInheritence() throws Exception {
final String filename = "com/opensymphony/xwork2/config/providers/xwork-include-parent.xml";
ConfigurationProvider provider = buildConfigurationProvider(filename);
@@ -155,10 +175,13 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
public void testEmptySpaces() throws Exception {
final String filename = "com/opensymphony/xwork2/config/providers/xwork- test.xml";
+ ConfigurationProvider provider = new XmlConfigurationProvider(filename, true);
container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(true);
+ container.inject(provider);
+ provider.init(configuration);
+ provider.loadPackages();
- ConfigurationProvider provider = buildConfigurationProvider(filename);
- assertTrue(!provider.needsReload());
+ assertFalse(provider.needsReload());
URI uri = ClassLoaderUtil.getResource(filename, ConfigurationProvider.class).toURI();
@@ -170,6 +193,27 @@ public class XmlConfigurationProviderTest extends ConfigurationTestBase {
assertTrue(provider.needsReload());
}
+ public void testEmptySpacesNotReloadingConfigs() throws Exception {
+ final String filename = "com/opensymphony/xwork2/config/providers/xwork- test.xml";
+ buildConfigurationProvider(filename);
+ ConfigurationProvider provider = new XmlConfigurationProvider(filename, true);
+ container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(false);
+ container.inject(provider);
+ provider.init(configuration);
+ provider.loadPackages();
+
+ assertFalse(provider.needsReload());
+
+ URI uri = ClassLoaderUtil.getResource(filename, ConfigurationProvider.class).toURI();
+
+ File file = new File(uri);
+
+ assertTrue(file.exists());
+ changeFileTime(file);
+
+ assertFalse(provider.needsReload());
+ }
+
public void testConfigsInJarFiles() throws Exception {
container.getInstance(FileManagerFactory.class).getFileManager().setReloadingConfigs(true);
testProvider("xwork-jar.xml");
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/XWorkListTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkListTest.java
similarity index 98%
rename from core/src/test/java/com/opensymphony/xwork2/util/XWorkListTest.java
rename to core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkListTest.java
index 21c8f03a9..a94d63caa 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/XWorkListTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkListTest.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package com.opensymphony.xwork2.util;
+package com.opensymphony.xwork2.conversion.impl;
import com.opensymphony.xwork2.XWorkTestCase;
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilStrutsTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilStrutsTest.java
new file mode 100644
index 000000000..c644bfed4
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilStrutsTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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 com.opensymphony.xwork2.ognl;
+
+import com.opensymphony.xwork2.test.TestArrayBean;
+import org.apache.struts2.StrutsInternalTestCase;
+
+public class OgnlUtilStrutsTest extends StrutsInternalTestCase {
+
+ private OgnlUtil ognlUtil;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ ognlUtil = container.getInstance(OgnlUtil.class);
+ }
+
+ public void testDefaultExcludes() {
+ ognlUtil.setExcludedClasses("");
+ ognlUtil.setExcludedPackageNames("");
+ ognlUtil.setExcludedPackageNamePatterns("");
+ assertTrue(ognlUtil.getExcludedClasses().size() > 0);
+ assertTrue(ognlUtil.getExcludedPackageNames().size() > 0);
+
+ try {
+ ognlUtil.getExcludedClasses().clear();
+ fail("Missing the expected Exception");
+ } catch (Exception ex) {
+ assertTrue(ex instanceof UnsupportedOperationException);
+ }
+ try {
+ ognlUtil.getExcludedPackageNames().clear();
+ fail("Missing the expected Exception");
+ } catch (Exception ex) {
+ assertTrue(ex instanceof UnsupportedOperationException);
+ }
+ try {
+ ognlUtil.getExcludedPackageNamePatterns().clear();
+ fail("Missing the expected Exception");
+ } catch (Exception ex) {
+ assertTrue(ex instanceof UnsupportedOperationException);
+ }
+ }
+
+ public void testAccessToSizeMethod() throws Exception {
+ // given
+ TestArrayBean bean = new TestArrayBean();
+ bean.getPersons().add("Alice");
+ bean.getPersons().add("Mich");
+
+ // when
+ Object value = ognlUtil.getValue("persons.size() > 0", ognlUtil.createDefaultContext(bean), bean);
+
+ // then
+ assertTrue(value instanceof Boolean);
+ assertTrue((Boolean) value);
+ }
+
+}
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 3b3c8ae01..bca4f136d 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
@@ -41,7 +41,7 @@ public class OgnlUtilTest extends XWorkTestCase {
ognlUtil = container.getInstance(OgnlUtil.class);
}
- public void testCanSetADependentObject() throws Exception {
+ public void testCanSetADependentObject() {
String dogName = "fido";
OgnlRuntime.setNullHandler(Owner.class, new NullHandler() {
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/SecurityMemberAccessTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/SecurityMemberAccessTest.java
index c78e9abee..ddb3f2826 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/SecurityMemberAccessTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/SecurityMemberAccessTest.java
@@ -22,7 +22,6 @@ import com.opensymphony.xwork2.util.TextParseUtil;
import junit.framework.TestCase;
import java.lang.reflect.Member;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -62,7 +61,7 @@ public class SecurityMemberAccessTest extends TestCase {
String propertyName = "stringField";
Member member = FooBar.class.getDeclaredMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
- Set> excluded = new HashSet>();
+ Set> excluded = new HashSet<>();
excluded.add(FooBar.class);
sma.setExcludedClasses(excluded);
@@ -108,7 +107,7 @@ public class SecurityMemberAccessTest extends TestCase {
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
- Set> excluded = new HashSet>();
+ Set> excluded = new HashSet<>();
excluded.add(BarInterface.class);
sma.setExcludedClasses(excluded);
@@ -126,7 +125,7 @@ public class SecurityMemberAccessTest extends TestCase {
String propertyName = "fooLogic";
Member member = FooBar.class.getMethod(propertyName);
- Set> excluded = new HashSet>();
+ Set> excluded = new HashSet<>();
excluded.add(BarInterface.class);
sma.setExcludedClasses(excluded);
@@ -158,7 +157,7 @@ public class SecurityMemberAccessTest extends TestCase {
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
- Set> excluded = new HashSet>();
+ Set> excluded = new HashSet<>();
excluded.add(FooBarInterface.class);
sma.setExcludedClasses(excluded);
@@ -173,7 +172,7 @@ public class SecurityMemberAccessTest extends TestCase {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- Set excluded = new HashSet();
+ Set excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
sma.setExcludedPackageNamePatterns(excluded);
@@ -191,7 +190,7 @@ public class SecurityMemberAccessTest extends TestCase {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- Set excluded = new HashSet();
+ Set excluded = new HashSet<>();
excluded.add(FooBar.class.getPackage().getName());
sma.setExcludedPackageNames(excluded);
@@ -205,11 +204,11 @@ public class SecurityMemberAccessTest extends TestCase {
assertFalse("stringField is accessible!", actual);
}
- public void testDefaultPackageExclusion() throws Exception {
+ public void testDefaultPackageExclusion() {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- Set excluded = new HashSet();
+ Set excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
sma.setExcludedPackageNamePatterns(excluded);
@@ -220,11 +219,11 @@ public class SecurityMemberAccessTest extends TestCase {
assertFalse("default package is excluded!", actual);
}
- public void testDefaultPackageExclusion2() throws Exception {
+ public void testDefaultPackageExclusion2() {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- Set excluded = new HashSet();
+ Set excluded = new HashSet<>();
excluded.add(Pattern.compile("^$"));
sma.setExcludedPackageNamePatterns(excluded);
@@ -317,10 +316,10 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveDoubleWithNames() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang.,ognl,javax"));
+ sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("ognl.,javax."));
- Set> excluded = new HashSet>();
+ Set> excluded = new HashSet<>();
excluded.add(Object.class);
excluded.add(Runtime.class);
excluded.add(System.class);
@@ -369,7 +368,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveDoubleWithPackageRegExs() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- Set patterns = new HashSet();
+ Set patterns = new HashSet<>();
patterns.add(Pattern.compile("^java\\.lang\\..*"));
sma.setExcludedPackageNamePatterns(patterns);
@@ -386,7 +385,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessMemberAccessIsAccessible() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- Set> excluded = new HashSet>();
+ Set> excluded = new HashSet<>();
excluded.add(ognl.MemberAccess.class);
sma.setExcludedClasses(excluded);
@@ -404,7 +403,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessMemberAccessIsBlocked() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(false);
- Set> excluded = new HashSet>();
+ Set> excluded = new HashSet<>();
excluded.add(SecurityMemberAccess.class);
sma.setExcludedClasses(excluded);
@@ -419,6 +418,21 @@ public class SecurityMemberAccessTest extends TestCase {
assertFalse(accessible);
}
+ public void testPackageNameExclusionAsCommaDelimited() {
+ // given
+ SecurityMemberAccess sma = new SecurityMemberAccess(false);
+
+
+ sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang."));
+
+ // when
+ boolean actual = sma.isPackageExcluded(String.class.getPackage(), null);
+ actual &= sma.isPackageExcluded(null, String.class.getPackage());
+
+ // then
+ assertTrue("package java.lang. is accessible!", actual);
+ }
+
}
class FooBar implements FooBarInterface {
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/TestArrayBean.java b/core/src/test/java/com/opensymphony/xwork2/test/TestArrayBean.java
new file mode 100644
index 000000000..a92a8ffd1
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/TestArrayBean.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.opensymphony.xwork2.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestArrayBean {
+
+ private List persons = new ArrayList<>();
+
+ public void setPersons(List persons) {
+ this.persons = persons;
+ }
+
+ public List getPersons() {
+ return persons;
+ }
+}
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java b/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java
index 32d24853e..c13e87383 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/DefaultFileManagerTest.java
@@ -21,16 +21,9 @@ package com.opensymphony.xwork2.util;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.FileManagerFactory;
import com.opensymphony.xwork2.XWorkTestCase;
-import com.opensymphony.xwork2.util.fs.DefaultFileManager;
-import org.apache.struts2.util.fs.JBossFileManager;
-import java.io.IOException;
import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-import java.net.URLStreamHandlerFactory;
+import java.net.*;
/**
* FileManager Tester.
@@ -49,23 +42,40 @@ public class DefaultFileManagerTest extends XWorkTestCase {
fileManager = container.getInstance(FileManagerFactory.class).getFileManager();
}
- public void disabled_testGetFileInJar() throws Exception {
- testLoadFile("xwork-jar.xml");
- testLoadFile("xwork - jar.xml");
- testLoadFile("xwork-zip.xml");
- testLoadFile("xwork - zip.xml");
- testLoadFile("xwork-jar2.xml");
- testLoadFile("xwork - jar2.xml");
- testLoadFile("xwork-zip2.xml");
- testLoadFile("xwork - zip2.xml");
+ public void testGetFileInJar() throws Exception {
+ testLoadFile("xwork-jar.xml", false);
+ testLoadFile("xwork - jar.xml", false);
+ testLoadFile("xwork-zip.xml", false);
+ testLoadFile("xwork - zip.xml", false);
+ testLoadFile("xwork-jar2.xml", false);
+ testLoadFile("xwork - jar2.xml", false);
+ testLoadFile("xwork-zip2.xml", false);
+ testLoadFile("xwork - zip2.xml", false);
+
+ testLoadFile("xwork-jar.xml", true);
+ testLoadFile("xwork - jar.xml", true);
+ testLoadFile("xwork-zip.xml", true);
+ testLoadFile("xwork - zip.xml", true);
+ testLoadFile("xwork-jar2.xml", true);
+ testLoadFile("xwork - jar2.xml", true);
+ testLoadFile("xwork-zip2.xml", true);
+ testLoadFile("xwork - zip2.xml", true);
}
- private void testLoadFile(String fileName) {
- fileManager.setReloadingConfigs(true);
+ private void testLoadFile(String fileName, boolean reloadConfigs) throws Exception {
+ fileManager.setReloadingConfigs(reloadConfigs);
URL url = ClassLoaderUtil.getResource(fileName, DefaultFileManagerTest.class);
InputStream file = fileManager.loadFile(url);
assertNotNull(file);
- assertTrue(fileManager.fileNeedsReloading(fileName));
+ file.close();
+ assertFalse(fileManager.fileNeedsReloading(url.toString()));
+
+ long now = System.currentTimeMillis();
+ JarURLConnection conn = (JarURLConnection) url.openConnection();
+ conn.getJarEntry().setTime(now + 60000);
+ conn.getInputStream().close();
+
+ assertEquals(reloadConfigs, fileManager.fileNeedsReloading(url.toString()));
}
public void testReloadingConfigs() throws Exception {
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java b/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java
index 54a10b90a..6969ccd3f 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/fs/JarEntryRevisionTest.java
@@ -21,7 +21,9 @@ package com.opensymphony.xwork2.util.fs;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.FileManagerFactory;
import com.opensymphony.xwork2.XWorkTestCase;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.filefilter.WildcardFileFilter;
import java.io.File;
import java.io.FileOutputStream;
@@ -30,6 +32,8 @@ import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
@@ -113,6 +117,20 @@ public class JarEntryRevisionTest extends XWorkTestCase {
assertTrue(entry.needsReloading());
}
+ @Override
+ protected void tearDown() throws Exception {
+ Path tmpFile = Files.createTempFile("jar_cache", null);
+ Path tmpFolder = tmpFile.getParent();
+ int count = FileUtils.listFiles(tmpFolder.toFile(), new WildcardFileFilter("jar_cache*"),
+ null).size();
+ if (tmpFile.toFile().delete()) {
+ count--;
+ }
+ assertEquals(0, count);
+
+ super.tearDown();
+ }
+
/**
* WW-4901 Simulating container implementation of {@link URL#openConnection()}
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java b/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java
index 196b43766..cef15345c 100644
--- a/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java
+++ b/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java
@@ -47,6 +47,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
@@ -134,7 +135,7 @@ public class DispatcherTest extends StrutsInternalTestCase {
assertEquals("utf-8", req.getCharacterEncoding());
}
-
+
public void testPrepareMultipartRequest() throws Exception {
MockHttpServletRequest req = new MockHttpServletRequest();
MockHttpServletResponse res = new MockHttpServletResponse();
@@ -175,9 +176,9 @@ public class DispatcherTest extends StrutsInternalTestCase {
}
public void testDispatcherListener() throws Exception {
-
+
final DispatcherListenerState state = new DispatcherListenerState();
-
+
Dispatcher.addDispatcherListener(new DispatcherListener() {
public void dispatcherDestroyed(Dispatcher du) {
state.isDestroyed = true;
@@ -186,21 +187,21 @@ public class DispatcherTest extends StrutsInternalTestCase {
state.isInitialized = true;
}
});
-
-
+
+
assertFalse(state.isDestroyed);
assertFalse(state.isInitialized);
-
+
Dispatcher du = initDispatcher(new HashMap() );
-
+
assertTrue(state.isInitialized);
-
+
du.cleanup();
assertTrue(state.isDestroyed);
}
-
-
+
+
public void testConfigurationManager() {
Dispatcher du;
final InternalConfigurationManager configurationManager = new InternalConfigurationManager(Container.DEFAULT_NAME);
@@ -208,26 +209,42 @@ public class DispatcherTest extends StrutsInternalTestCase {
du = new MockDispatcher(new MockServletContext(), new HashMap(), configurationManager);
du.init();
Dispatcher.setInstance(du);
-
+
assertFalse(configurationManager.destroyConfiguration);
-
+
du.cleanup();
-
+
assertTrue(configurationManager.destroyConfiguration);
-
+
}
finally {
Dispatcher.setInstance(null);
}
}
-
+
+ public void testInitLoadsDefaultConfig() {
+ Dispatcher du = new Dispatcher(new MockServletContext(), new HashMap());
+ du.init();
+ Configuration config = du.getConfigurationManager().getConfiguration();
+ assertNotNull(config);
+ HashSet expected = new HashSet();
+ expected.add("struts-default.xml");
+ expected.add("struts-plugin.xml");
+ expected.add("struts.xml");
+ assertEquals(expected, config.getLoadedFileNames());
+ assertTrue(config.getPackageConfigs().size() > 0);
+ PackageConfig packageConfig = config.getPackageConfig("struts-default");
+ assertTrue(packageConfig.getInterceptorConfigs().size() > 0);
+ assertTrue(packageConfig.getResultTypeConfigs().size() > 0);
+ }
+
public void testObjectFactoryDestroy() throws Exception {
ConfigurationManager cm = new ConfigurationManager(Container.DEFAULT_NAME);
Dispatcher du = new MockDispatcher(new MockServletContext(), new HashMap(), cm);
Mock mockConfiguration = new Mock(Configuration.class);
cm.setConfiguration((Configuration)mockConfiguration.proxy());
-
+
Mock mockContainer = new Mock(Container.class);
String reloadConfigs = container.getInstance(String.class, StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD);
mockContainer.expectAndReturn("getInstance", C.args(C.eq(String.class), C.eq(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD)),
@@ -248,18 +265,18 @@ public class DispatcherTest extends StrutsInternalTestCase {
mockConfiguration.verify();
mockContainer.verify();
}
-
- public void testInterceptorDestroy() throws Exception {
+
+ public void testInterceptorDestroy() throws Exception {
Mock mockInterceptor = new Mock(Interceptor.class);
mockInterceptor.matchAndReturn("hashCode", 0);
mockInterceptor.expect("destroy");
-
+
InterceptorMapping interceptorMapping = new InterceptorMapping("test", (Interceptor) mockInterceptor.proxy());
-
+
InterceptorStackConfig isc = new InterceptorStackConfig.Builder("test").addInterceptor(interceptorMapping).build();
-
+
PackageConfig packageConfig = new PackageConfig.Builder("test").addInterceptorStackConfig(isc).build();
-
+
Map packageConfigs = new HashMap();
packageConfigs.put("test", packageConfig);
@@ -273,14 +290,14 @@ public class DispatcherTest extends StrutsInternalTestCase {
mockConfiguration.matchAndReturn("getPackageConfigs", packageConfigs);
mockConfiguration.matchAndReturn("getContainer", mockContainer.proxy());
mockConfiguration.expect("destroy");
-
+
ConfigurationManager configurationManager = new ConfigurationManager(Container.DEFAULT_NAME);
configurationManager.setConfiguration((Configuration) mockConfiguration.proxy());
-
+
Dispatcher dispatcher = new MockDispatcher(new MockServletContext(), new HashMap(), configurationManager);
dispatcher.init();
dispatcher.cleanup();
-
+
mockInterceptor.verify();
mockContainer.verify();
mockConfiguration.verify();
@@ -363,8 +380,8 @@ public class DispatcherTest extends StrutsInternalTestCase {
destroyConfiguration = true;
}
}
-
-
+
+
class DispatcherListenerState {
public boolean isInitialized = false;
public boolean isDestroyed = false;
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 3c012e8a8..479494b16 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
@@ -27,12 +27,12 @@ import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
import com.opensymphony.xwork2.inject.Container;
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;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -65,7 +65,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
};
}
- public void testGetMapping() throws Exception {
+ public void testGetMapping() {
req.setupGetRequestURI("/my/namespace/actionName.action");
req.setupGetServletPath("/my/namespace/actionName.action");
req.setupGetAttribute(null);
@@ -79,7 +79,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(mapping.getMethod());
}
- public void testGetMappingWithMethod() throws Exception {
+ public void testGetMappingWithMethod() {
req.setupGetParameterMap(new HashMap());
req.setupGetRequestURI("/my/namespace/actionName!add.action");
req.setupGetServletPath("/my/namespace/actionName!add.action");
@@ -95,7 +95,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("add", mapping.getMethod());
}
- public void testGetMappingWithSlashedName() throws Exception {
+ public void testGetMappingWithSlashedName() {
req.setupGetRequestURI("/my/foo/actionName.action");
req.setupGetServletPath("/my/foo/actionName.action");
@@ -111,7 +111,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(mapping.getMethod());
}
- public void testGetMappingWithSlashedNameAtRootButNoSlashPackage() throws Exception {
+ public void testGetMappingWithSlashedNameAtRootButNoSlashPackage() {
req.setupGetRequestURI("/foo/actionName.action");
req.setupGetServletPath("/foo/actionName.action");
@@ -127,7 +127,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(mapping.getMethod());
}
- public void testGetMappingWithSlashedNameAtRoot() throws Exception {
+ public void testGetMappingWithSlashedNameAtRoot() {
config = new DefaultConfiguration();
PackageConfig pkg = new PackageConfig.Builder("myns")
.namespace("/my/namespace").build();
@@ -158,7 +158,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
- public void testGetMappingWithNamespaceSlash() throws Exception {
+ public void testGetMappingWithNamespaceSlash() {
req.setupGetRequestURI("/my-hh/abc.action");
req.setupGetServletPath("/my-hh/abc.action");
@@ -181,7 +181,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("my-hh/abc", mapping.getName());
}
- public void testGetMappingWithUnknownNamespace() throws Exception {
+ public void testGetMappingWithUnknownNamespace() {
req.setupGetRequestURI("/bo/foo/actionName.action");
req.setupGetServletPath("/bo/foo/actionName.action");
req.setupGetAttribute(null);
@@ -195,7 +195,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(mapping.getMethod());
}
- public void testGetMappingWithUnknownNamespaceButFullNamespaceSelect() throws Exception {
+ public void testGetMappingWithUnknownNamespaceButFullNamespaceSelect() {
req.setupGetRequestURI("/bo/foo/actionName.action");
req.setupGetServletPath("/bo/foo/actionName.action");
req.setupGetAttribute(null);
@@ -210,7 +210,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(mapping.getMethod());
}
- public void testGetMappingWithActionName_methodAndName() throws Exception {
+ public void testGetMappingWithActionName_methodAndName() {
DefaultActionMapper mapper = new DefaultActionMapper();
mapper.setAllowDynamicMethodCalls("true");
ActionMapping mapping = mapper.getMappingFromActionName("actionName!add");
@@ -218,24 +218,24 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("add", mapping.getMethod());
}
- public void testGetMappingWithActionName_name() throws Exception {
+ public void testGetMappingWithActionName_name() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping mapping = mapper.getMappingFromActionName("actionName");
assertEquals("actionName", mapping.getName());
- assertEquals(null, mapping.getMethod());
+ assertNull(mapping.getMethod());
}
- public void testGetMappingWithActionName_noDynamicMethod() throws Exception {
+ public void testGetMappingWithActionName_noDynamicMethod() {
DefaultActionMapper mapper = new DefaultActionMapper();
mapper.setAllowDynamicMethodCalls("false");
ActionMapping mapping = mapper.getMappingFromActionName("actionName!add");
assertEquals("actionName!add", mapping.getName());
- assertEquals(null, mapping.getMethod());
+ assertNull(mapping.getMethod());
}
- public void testGetMappingWithActionName_noDynamicMethodColonPrefix() throws Exception {
+ public void testGetMappingWithActionName_noDynamicMethodColonPrefix() {
- Map parameterMap = new HashMap();
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.METHOD_PREFIX + "someMethod", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -247,16 +247,16 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
ActionMapping actionMapping = defaultActionMapper.getMapping(request, configManager);
assertEquals("someServletPath", actionMapping.getName());
- assertEquals(null, actionMapping.getMethod());
+ assertNull(actionMapping.getMethod());
}
- public void testGetMappingWithActionName_null() throws Exception {
+ public void testGetMappingWithActionName_null() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping mapping = mapper.getMappingFromActionName(null);
assertNull(mapping);
}
- public void testGetUri() throws Exception {
+ public void testGetUri() {
req.setupGetParameterMap(new HashMap());
req.setupGetRequestURI("/my/namespace/actionName.action");
req.setupGetServletPath("/my/namespace/actionName.action");
@@ -268,7 +268,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/my/namespace/actionName.action", mapper.getUriFromActionMapping(mapping));
}
- public void testGetUriWithSemicolonPresent() throws Exception {
+ public void testGetUriWithSemicolonPresent() {
req.setupGetParameterMap(new HashMap());
req.setupGetRequestURI("/my/namespace/actionName.action;abc=123rty56");
req.setupGetServletPath("/my/namespace/actionName.action;abc=123rty56");
@@ -280,7 +280,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/my/namespace/actionName.action", mapper.getUriFromActionMapping(mapping));
}
- public void testGetUriWithMethod() throws Exception {
+ public void testGetUriWithMethod() {
req.setupGetParameterMap(new HashMap());
req.setupGetRequestURI("/my/namespace/actionName!add.action");
req.setupGetServletPath("/my/namespace/actionName!add.action");
@@ -293,8 +293,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/my/namespace/actionName!add.action", mapper.getUriFromActionMapping(mapping));
}
- public void testGetUriWithOriginalExtension() throws Exception {
- ActionMapping mapping = new ActionMapping("actionName", "/ns", null, new HashMap());
+ public void testGetUriWithOriginalExtension() {
+ ActionMapping mapping = new ActionMapping("actionName", "/ns", null, new HashMap());
ActionMapping orig = new ActionMapping();
orig.setExtension("foo");
@@ -304,7 +304,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/ns/actionName.foo", mapper.getUriFromActionMapping(mapping));
}
- public void testGetMappingWithNoExtension() throws Exception {
+ public void testGetMappingWithNoExtension() {
req.setupGetParameterMap(new HashMap());
req.setupGetRequestURI("/my/namespace/actionName");
req.setupGetServletPath("/my/namespace/actionName");
@@ -320,7 +320,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(mapping.getMethod());
}
- public void testGetMappingWithNoExtensionButUriHasExtension() throws Exception {
+ public void testGetMappingWithNoExtensionButUriHasExtension() {
req.setupGetParameterMap(new HashMap());
req.setupGetRequestURI("/my/namespace/actionName.html");
req.setupGetServletPath("/my/namespace/actionName.html");
@@ -340,7 +340,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
// === test name & namespace ===
// =============================
- public void testParseNameAndNamespace1() throws Exception {
+ public void testParseNameAndNamespace1() {
ActionMapping actionMapping = new ActionMapping();
DefaultActionMapper defaultActionMapper = new DefaultActionMapper();
@@ -350,7 +350,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals(actionMapping.getNamespace(), "");
}
- public void testParseNameAndNamespace2() throws Exception {
+ public void testParseNameAndNamespace2() {
ActionMapping actionMapping = new ActionMapping();
DefaultActionMapper defaultActionMapper = new DefaultActionMapper();
@@ -360,7 +360,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals(actionMapping.getNamespace(), "/");
}
- public void testParseNameAndNamespace3() throws Exception {
+ public void testParseNameAndNamespace3() {
ActionMapping actionMapping = new ActionMapping();
DefaultActionMapper defaultActionMapper = new DefaultActionMapper();
@@ -370,7 +370,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals(actionMapping.getNamespace(), "/my");
}
- public void testParseNameAndNamespace_NoSlashes() throws Exception {
+ public void testParseNameAndNamespace_NoSlashes() {
ActionMapping actionMapping = new ActionMapping();
DefaultActionMapper defaultActionMapper = new DefaultActionMapper();
@@ -381,7 +381,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals(actionMapping.getNamespace(), "");
}
- public void testParseNameAndNamespace_AllowSlashes() throws Exception {
+ public void testParseNameAndNamespace_AllowSlashes() {
ActionMapping actionMapping = new ActionMapping();
DefaultActionMapper defaultActionMapper = new DefaultActionMapper();
@@ -397,8 +397,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
// === test special prefix ===
// ===========================
- public void testActionPrefixWhenDisabled() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefixWhenDisabled() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -411,8 +411,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("someServletPath", actionMapping.getName());
}
- public void testActionPrefixWhenEnabled() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefixWhenEnabled() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -426,8 +426,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("myAction", actionMapping.getName());
}
- public void testActionPrefixWhenSlashesAndCrossNamespaceDisabled() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefixWhenSlashesAndCrossNamespaceDisabled() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "my/Action", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -442,8 +442,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("my/Action", actionMapping.getName());
}
- public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespaceDisabled() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespaceDisabled() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "my/Action", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -458,8 +458,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("Action", actionMapping.getName());
}
- public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespace() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespace() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "my/Action", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -475,8 +475,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("my/Action", actionMapping.getName());
}
- public void testActionPrefixWhenCrossNamespace() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefixWhenCrossNamespace() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "/my/Action", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -491,8 +491,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/my/Action", actionMapping.getName());
}
- public void testActionPrefix_fromImageButton() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefix_fromImageButton() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction", "");
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction.x", "");
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction.y", "");
@@ -508,8 +508,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("myAction", actionMapping.getName());
}
- public void testActionPrefix_fromIEImageButton() throws Exception {
- Map parameterMap = new HashMap();
+ public void testActionPrefix_fromIEImageButton() {
+ Map parameterMap = new HashMap<>();
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction.x", "");
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction.y", "");
@@ -524,8 +524,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("myAction", actionMapping.getName());
}
- public void testRedirectPrefix() throws Exception {
- Map parameterMap = new HashMap();
+ public void testRedirectPrefix() {
+ Map parameterMap = new HashMap<>();
parameterMap.put("redirect:" + "http://www.google.com", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -540,8 +540,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(result);
}
- public void testUnsafeRedirectPrefix() throws Exception {
- Map parameterMap = new HashMap();
+ public void testUnsafeRedirectPrefix() {
+ Map parameterMap = new HashMap<>();
parameterMap.put("redirect:" + "http://%{3*4}", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -556,8 +556,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(result);
}
- public void testRedirectActionPrefix() throws Exception {
- Map parameterMap = new HashMap();
+ public void testRedirectActionPrefix() {
+ Map parameterMap = new HashMap<>();
parameterMap.put("redirectAction:" + "myAction", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -573,8 +573,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(result);
}
- public void testUnsafeRedirectActionPrefix() throws Exception {
- Map parameterMap = new HashMap();
+ public void testUnsafeRedirectActionPrefix() {
+ Map parameterMap = new HashMap<>();
parameterMap.put("redirectAction:" + "%{3*4}", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -590,8 +590,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(result);
}
- public void testRedirectActionPrefixWithEmptyExtension() throws Exception {
- Map parameterMap = new HashMap();
+ public void testRedirectActionPrefixWithEmptyExtension() {
+ Map parameterMap = new HashMap<>();
parameterMap.put("redirectAction:" + "myAction", "");
StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -608,8 +608,8 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertNull(result);
}
- public void testCustomActionPrefix() throws Exception {
- Map parameterMap = new HashMap();
+ public void testCustomActionPrefix() {
+ Map parameterMap = new HashMap<>();
parameterMap.put("foo:myAction", "");
final StrutsMockHttpServletRequest request = new StrutsMockHttpServletRequest();
@@ -627,39 +627,39 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals(actionMapping.getName(), "myAction");
}
- public void testDropExtension() throws Exception {
+ public void testDropExtension() {
DefaultActionMapper mapper = new DefaultActionMapper();
String name = mapper.dropExtension("foo.action", new ActionMapping());
- assertTrue("Name not right: "+name, "foo".equals(name));
+ assertEquals("Name not right: " + name, "foo", name);
name = mapper.dropExtension("foo.action.action", new ActionMapping());
- assertTrue("Name not right: "+name, "foo.action".equals(name));
+ assertEquals("Name not right: " + name, "foo.action", name);
}
- public void testDropExtensionWhenBlank() throws Exception {
+ public void testDropExtensionWhenBlank() {
DefaultActionMapper mapper = new DefaultActionMapper();
mapper.setExtensions("action,,");
String name = mapper.dropExtension("foo.action", new ActionMapping());
- assertTrue("Name not right: "+name, "foo".equals(name));
+ assertEquals("Name not right: " + name, "foo", name);
name = mapper.dropExtension("foo", new ActionMapping());
- assertTrue("Name not right: "+name, "foo".equals(name));
+ assertEquals("Name not right: " + name, "foo", name);
assertNull(mapper.dropExtension("foo.bar", new ActionMapping()));
assertNull(mapper.dropExtension("foo.", new ActionMapping()));
}
- public void testDropExtensionEmbeddedDot() throws Exception {
+ public void testDropExtensionEmbeddedDot() {
DefaultActionMapper mapper = new DefaultActionMapper();
mapper.setExtensions("action,,");
String name = mapper.dropExtension("/foo/bar-1.0/baz.action", new ActionMapping());
- assertTrue("Name not right: "+name, "/foo/bar-1.0/baz".equals(name));
+ assertEquals("Name not right: " + name, "/foo/bar-1.0/baz", name);
name = mapper.dropExtension("/foo/bar-1.0/baz", new ActionMapping());
- assertTrue("Name not right: "+name, "/foo/bar-1.0/baz".equals(name));
+ assertEquals("Name not right: " + name, "/foo/bar-1.0/baz", name);
}
- public void testGetUriFromActionMapper1() throws Exception {
+ public void testGetUriFromActionMapper1() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setMethod("myMethod");
@@ -670,7 +670,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myNamespace/myActionName!myMethod.action", uri);
}
- public void testGetUriFromActionMapper2() throws Exception {
+ public void testGetUriFromActionMapper2() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setMethod("myMethod");
@@ -681,7 +681,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myActionName!myMethod.action", uri);
}
- public void testGetUriFromActionMapper3() throws Exception {
+ public void testGetUriFromActionMapper3() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setMethod("myMethod");
@@ -693,7 +693,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
}
- public void testGetUriFromActionMapper4() throws Exception {
+ public void testGetUriFromActionMapper4() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setName("myActionName");
@@ -703,7 +703,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myActionName.action", uri);
}
- public void testGetUriFromActionMapper5() throws Exception {
+ public void testGetUriFromActionMapper5() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setName("myActionName");
@@ -714,7 +714,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
}
//
- public void testGetUriFromActionMapper6() throws Exception {
+ public void testGetUriFromActionMapper6() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setMethod("myMethod");
@@ -725,7 +725,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myNamespace/myActionName!myMethod.action?test=bla", uri);
}
- public void testGetUriFromActionMapper7() throws Exception {
+ public void testGetUriFromActionMapper7() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setMethod("myMethod");
@@ -736,7 +736,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myActionName!myMethod.action?test=bla", uri);
}
- public void testGetUriFromActionMapper8() throws Exception {
+ public void testGetUriFromActionMapper8() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setMethod("myMethod");
@@ -748,7 +748,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
}
- public void testGetUriFromActionMapper9() throws Exception {
+ public void testGetUriFromActionMapper9() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setName("myActionName?test=bla");
@@ -758,7 +758,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myActionName.action?test=bla", uri);
}
- public void testGetUriFromActionMapper10() throws Exception {
+ public void testGetUriFromActionMapper10() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setName("myActionName?test=bla");
@@ -768,7 +768,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myActionName.action?test=bla", uri);
}
- public void testGetUriFromActionMapper11() throws Exception {
+ public void testGetUriFromActionMapper11() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setName("myActionName.action");
@@ -778,7 +778,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myActionName.action", uri);
}
- public void testGetUriFromActionMapper12() throws Exception {
+ public void testGetUriFromActionMapper12() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setName("myActionName.action");
@@ -788,7 +788,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myActionName.action", uri);
}
- public void testGetUriFromActionMapper_justActionAndMethod() throws Exception {
+ public void testGetUriFromActionMapper_justActionAndMethod() {
DefaultActionMapper mapper = new DefaultActionMapper();
ActionMapping actionMapping = new ActionMapping();
actionMapping.setMethod("myMethod");
@@ -799,7 +799,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("myActionName!myMethod", uri);
}
- public void testGetUriFromActionMapperWhenBlankExtension() throws Exception {
+ public void testGetUriFromActionMapperWhenBlankExtension() {
DefaultActionMapper mapper = new DefaultActionMapper();
mapper.setExtensions(",,");
ActionMapping actionMapping = new ActionMapping();
@@ -811,7 +811,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("/myNamespace/myActionName!myMethod", uri);
}
- public void testSetExtension() throws Exception {
+ public void testSetExtension() {
DefaultActionMapper mapper = new DefaultActionMapper();
mapper.setExtensions("");
assertNull(mapper.extensions);
@@ -828,15 +828,40 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals(Arrays.asList("html", "", "xml"), mapper.extensions);
mapper.setExtensions("xml");
- assertEquals(Arrays.asList("xml"), mapper.extensions);
+ assertEquals(Collections.singletonList("xml"), mapper.extensions);
mapper.setExtensions(",");
- assertEquals(Arrays.asList(""), mapper.extensions);
+ assertEquals(Collections.singletonList(""), mapper.extensions);
}
- public void testAllowedActionNames() throws Exception {
+ public void testAllowedNamespaceNames() {
+ DefaultActionMapper mapper = new DefaultActionMapper();
+
+ String namespace = "/";
+ assertEquals(namespace, mapper.cleanupNamespaceName(namespace));
+
+ namespace = "${namespace}";
+ assertEquals(mapper.defaultNamespaceName, mapper.cleanupNamespaceName(namespace));
+
+ namespace = "${${%{namespace}}}";
+ assertEquals(mapper.defaultNamespaceName, mapper.cleanupNamespaceName(namespace));
+
+ namespace = "${#foo='namespace',#foo}";
+ assertEquals(mapper.defaultNamespaceName, mapper.cleanupNamespaceName(namespace));
+
+ namespace = "/test-namespace/namespace/";
+ assertEquals("/test-namespace/namespace/", mapper.cleanupNamespaceName(namespace));
+
+ namespace = "/test_namespace/namespace-test/";
+ assertEquals("/test_namespace/namespace-test/", mapper.cleanupNamespaceName(namespace));
+
+ namespace = "/test_namespace/namespace.test/";
+ assertEquals("/test_namespace/namespace.test/", mapper.cleanupActionName(namespace));
+ }
+
+ public void testAllowedActionNames() {
DefaultActionMapper mapper = new DefaultActionMapper();
String actionName = "action";
@@ -861,7 +886,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
assertEquals("test!bar.action", mapper.cleanupActionName(actionName));
}
- public void testAllowedMethodNames() throws Exception {
+ public void testAllowedMethodNames() {
DefaultActionMapper mapper = new DefaultActionMapper();
assertEquals("", mapper.cleanupMethodName(""));
diff --git a/core/src/test/java/org/apache/struts2/result/PostbackResultTest.java b/core/src/test/java/org/apache/struts2/result/PostbackResultTest.java
new file mode 100644
index 000000000..32c0cca31
--- /dev/null
+++ b/core/src/test/java/org/apache/struts2/result/PostbackResultTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.result;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.ActionProxy;
+import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsInternalTestCase;
+import org.apache.struts2.dispatcher.mapper.ActionMapper;
+import org.easymock.IMocksControl;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+
+import static org.easymock.EasyMock.createControl;
+import static org.easymock.EasyMock.expect;
+
+
+public class PostbackResultTest extends StrutsInternalTestCase {
+
+ public void testWithNoNamespace() throws Exception {
+
+ ActionContext context = ActionContext.getContext();
+ ValueStack stack = context.getValueStack();
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ MockHttpServletResponse res = new MockHttpServletResponse();
+ context.put(ServletActionContext.HTTP_REQUEST, req);
+ context.put(ServletActionContext.HTTP_RESPONSE, res);
+
+ PostbackResult result = new PostbackResult();
+ result.setActionName("myAction${1-1}");
+ result.setPrependServletContext(false);
+
+ IMocksControl control = createControl();
+ ActionProxy mockActionProxy = control.createMock(ActionProxy.class);
+ ActionInvocation mockInvocation = control.createMock(ActionInvocation.class);
+ expect(mockInvocation.getInvocationContext()).andReturn(context).anyTimes();
+ expect(mockInvocation.getStack()).andReturn(stack).anyTimes();
+ expect(mockInvocation.getProxy()).andReturn(mockActionProxy);
+ expect(mockActionProxy.getNamespace()).andReturn("${1-1}");
+
+ control.replay();
+ result.setActionMapper(container.getInstance(ActionMapper.class));
+ result.execute(mockInvocation);
+ assertEquals("