mirror of
https://github.com/apache/struts.git
synced 2026-08-07 23:57:03 +00:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 930fef7679 | |||
| d2d01dfe93 | |||
| 056228cd1e | |||
| 39de8827cb | |||
| 60a1a2642a | |||
| d25a342bd2 | |||
| 6870fb7f79 | |||
| e62ae2ee7a | |||
| 83dc967eac | |||
| dd1588d3eb | |||
| 6194d3fc88 | |||
| bd0d514de9 | |||
| cde8a288f9 | |||
| ac868ae3ab | |||
| feb5ab1333 | |||
| 458acb89e5 | |||
| 88c2d216e3 | |||
| 61735542c2 | |||
| 0b41b68da4 | |||
| dbcca3512e | |||
| 6ec2bdc197 | |||
| 9b9aa10059 | |||
| 6c216de38e | |||
| a89b7c11af | |||
| 918182344c | |||
| 52e8d46364 | |||
| c59f294fb9 | |||
| 86e5bd7f52 | |||
| bea6fb599d | |||
| 4a3917176d | |||
| a746fc872a | |||
| 949e069f53 | |||
| 4db5cdc473 | |||
| afc8f20440 | |||
| 75d7bf481c | |||
| d86539ed07 | |||
| f0b3a1d213 | |||
| 2306f5f7fa | |||
| ed7f9dd4cb | |||
| cf53b59647 | |||
| 6dd6e5cfb7 | |||
| b9a0c497d3 | |||
| 2f95b9a130 | |||
| 103e3b174e | |||
| 2776b34b44 | |||
| 287e3bc8cb | |||
| 677ccebe83 | |||
| f11ac901d3 | |||
| 3fddfb6eb5 | |||
| 744c1f409d | |||
| 54a4dce7bf | |||
| 16eb7fa768 |
+1
-1
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-blank</artifactId>
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.apache.struts2.interceptor.validation.SkipValidation;
|
||||
|
||||
public class Login extends ExampleSupport {
|
||||
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jboss-blank</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-mailreader</artifactId>
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-portlet</artifactId>
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-showcase</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
<name>Struts 2 Rest Showcase Webapp</name>
|
||||
<description>Struts 2 Rest Showcase Example</description>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-showcase</artifactId>
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-archetypes</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+9
-13
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-assembly</artifactId>
|
||||
@@ -82,33 +82,29 @@
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>cwiki-docs</id>
|
||||
<id>docs</id>
|
||||
<phase>prepare-package</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<mkdir dir="${project.build.directory}/cwiki/" />
|
||||
<target>
|
||||
<mkdir dir="${project.build.directory}/docs/" />
|
||||
<exec executable="wget">
|
||||
<arg value="-erobots=off" />
|
||||
<arg value="-nH" />
|
||||
<arg value="--cut-dirs=3" />
|
||||
<arg value="-x" />
|
||||
<arg value="-nv" />
|
||||
<arg value="-E" />
|
||||
<arg value="-L" />
|
||||
<arg value="-l 0" />
|
||||
<arg value="-np" />
|
||||
<arg value="--directory-prefix=${project.build.directory}/cwiki" />
|
||||
<arg value="--directory-prefix=${project.build.directory}/docs" />
|
||||
<arg value="--no-check-certificate" />
|
||||
<arg value="-r" />
|
||||
<arg value="http://struts.apache.org/docs/" />
|
||||
<arg value="-i" />
|
||||
<arg value="src/main/resources/docs-urls.txt" />
|
||||
</exec>
|
||||
<delete>
|
||||
<fileset dir="${project.build.directory}/cwiki/" includes="**/index.*" />
|
||||
</delete>
|
||||
<copy file="${project.build.directory}/cwiki/home.html" tofile="${project.build.directory}/cwiki/index.html" />
|
||||
</tasks>
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
<!-- Include the Confluence docs in the assembly -->
|
||||
<fileSet>
|
||||
<directory>target/cwiki</directory>
|
||||
<directory>target/docs</directory>
|
||||
<outputDirectory>docs/docs</outputDirectory>
|
||||
</fileSet>
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
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/
|
||||
+3
-3
@@ -10,7 +10,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-bom</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Struts 2 Bill of Materials</name>
|
||||
@@ -25,7 +25,7 @@
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<struts-version.version>2.3.33</struts-version.version>
|
||||
<struts-version.version>2.3.37</struts-version.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@@ -197,6 +197,6 @@
|
||||
</dependencyManagement>
|
||||
|
||||
<scm>
|
||||
<tag>STRUTS_2_3_33</tag>
|
||||
<tag>STRUTS_2_3_37</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-admin-bundle</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-demo-bundle</artifactId>
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
|
||||
+3
-7
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -46,15 +46,11 @@
|
||||
<configuration>
|
||||
<A>uri=/struts-tags,tlibVersion=${tlib.version},jspVersion=2.0,shortName=s,displayName=Struts Tags,
|
||||
outFile=${basedir}/target/classes/META-INF/struts-tags.tld,
|
||||
description="To make it easier to access dynamic data;
|
||||
the Apache Struts framework includes a library of custom tags.
|
||||
The tags interact with the framework's validation and internationalization features;
|
||||
to ensure that input is correct and output is localized.
|
||||
The Struts Tags can be used with JSP FreeMarker or Velocity.",
|
||||
description='To make it easier to access dynamic data the Apache Struts framework includes a library of custom tags. The tags interact with the framework validation and internationalization features to ensure that input is correct and output is localized. The Struts Tags can be used with JSP FreeMarker or Velocity.',
|
||||
outTemplatesDir=${basedir}/src/site/resources/tags
|
||||
</A>
|
||||
<resourceTargetPath>target</resourceTargetPath>
|
||||
<fork>false</fork>
|
||||
<fork>true</fork>
|
||||
<force>true</force>
|
||||
<nocompile>true</nocompile>
|
||||
<showWarnings>true</showWarnings>
|
||||
|
||||
@@ -270,6 +270,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 **/
|
||||
|
||||
@@ -127,6 +127,8 @@ public class PostbackResult extends StrutsResultSupport {
|
||||
|
||||
if (actionName != null) {
|
||||
actionName = conditionalParse(actionName, invocation);
|
||||
parseLocation = false;
|
||||
|
||||
if (namespace == null) {
|
||||
namespace = invocation.getProxy().getNamespace();
|
||||
} else {
|
||||
|
||||
@@ -164,6 +164,8 @@ 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 {
|
||||
|
||||
@@ -118,6 +118,8 @@ public abstract class StrutsResultSupport implements Result, StrutsStatics {
|
||||
private String location;
|
||||
private String lastFinalLocation;
|
||||
|
||||
protected boolean parseLocation = true;
|
||||
|
||||
public StrutsResultSupport() {
|
||||
this(null, true, false);
|
||||
}
|
||||
@@ -187,7 +189,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +120,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";
|
||||
|
||||
@@ -166,8 +170,8 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
}
|
||||
}
|
||||
if (!allowSlashesInActionNames && !allowActionCrossNamespaceAccess) {
|
||||
if (actionName.lastIndexOf("/") != -1) {
|
||||
actionName = actionName.substring(actionName.lastIndexOf("/") + 1);
|
||||
if (actionName.lastIndexOf('/') != -1) {
|
||||
actionName = actionName.substring(actionName.lastIndexOf('/') + 1);
|
||||
}
|
||||
}
|
||||
mapping.setName(actionName);
|
||||
@@ -205,6 +209,16 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
this.alwaysSelectFullNamespace = "true".equals(val);
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -274,7 +288,7 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
ActionMapping mapping = new ActionMapping();
|
||||
String uri = RequestUtils.getUri(request);
|
||||
|
||||
int indexOfSemicolon = uri.indexOf(";");
|
||||
int indexOfSemicolon = uri.indexOf(';');
|
||||
uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri;
|
||||
|
||||
uri = dropExtension(uri, mapping);
|
||||
@@ -294,7 +308,7 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
if (allowDynamicMethodCalls) {
|
||||
// handle "name!method" convention.
|
||||
String name = mapping.getName();
|
||||
int exclamation = name.lastIndexOf("!");
|
||||
int exclamation = name.lastIndexOf('!');
|
||||
if (exclamation != -1) {
|
||||
mapping.setName(name.substring(0, exclamation));
|
||||
|
||||
@@ -343,7 +357,7 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
*/
|
||||
protected void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {
|
||||
String namespace, name;
|
||||
int lastSlash = uri.lastIndexOf("/");
|
||||
int lastSlash = uri.lastIndexOf('/');
|
||||
if (lastSlash == -1) {
|
||||
namespace = "";
|
||||
name = uri;
|
||||
@@ -391,10 +405,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
|
||||
*
|
||||
|
||||
@@ -46,6 +46,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -306,8 +307,8 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
Map<String, Object> params = ac.getParameters();
|
||||
|
||||
params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
|
||||
params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
|
||||
params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
|
||||
putWithCheck(params, contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
|
||||
putWithCheck(params, fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -326,6 +327,30 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
return invocation.invoke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes existing parameters that contain the given name (case-insensitive) before adding the parameter.
|
||||
* Minimal invasiv solution to fix CVE-2023-50164 and CVE-2024-53677 for the 2.3.x branch.
|
||||
* For example, malicious parameters "uploadFileName" (CVE-2023-50164) or "top.uploadFileName" (CVE-2024-53677)
|
||||
* would be removed from the map before adding the legitimate parameter "UploadFileName".
|
||||
*
|
||||
* @param params - parameters to update.
|
||||
* @param key - parameter name (compared with existing ones).
|
||||
* @param value - parameter value.
|
||||
*/
|
||||
private void putWithCheck(Map<String, Object> params, String key, Object value) {
|
||||
// Remove existing map entry if it contains the given key (a check for case-
|
||||
// insensitive equality does not catch all OGNL expressions, cf. CVE-2024-53677).
|
||||
Iterator<Map.Entry<String, Object>> iterator = params.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Object> entry = iterator.next();
|
||||
if (entry.getKey().toLowerCase().contains(key.toLowerCase())) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
// Add new entry
|
||||
params.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for added functionality. Checks if the proposed file is acceptable based on contentType and size.
|
||||
*
|
||||
|
||||
@@ -34,6 +34,7 @@ import freemarker.cache.FileTemplateLoader;
|
||||
import freemarker.cache.MultiTemplateLoader;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import freemarker.cache.WebappTemplateLoader;
|
||||
import freemarker.core.TemplateClassResolver;
|
||||
import freemarker.ext.jsp.TaglibFactory;
|
||||
import freemarker.ext.servlet.HttpRequestHashModel;
|
||||
import freemarker.ext.servlet.HttpRequestParametersHashModel;
|
||||
@@ -344,6 +345,9 @@ public class FreemarkerManager {
|
||||
configuration.setLocalizedLookup(false);
|
||||
configuration.setWhitespaceStripping(true);
|
||||
|
||||
LOG.debug("Sets NewBuiltinClassResolver to TemplateClassResolver.SAFER_RESOLVER");
|
||||
configuration.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,12 +47,6 @@
|
||||
java.lang.ClassLoader,
|
||||
java.lang.Shutdown,
|
||||
java.lang.ProcessBuilder,
|
||||
ognl.OgnlContext,
|
||||
ognl.ClassResolver,
|
||||
ognl.TypeConverter,
|
||||
ognl.MemberAccess,
|
||||
ognl.DefaultMemberAccess,
|
||||
com.opensymphony.xwork2.ognl.SecurityMemberAccess,
|
||||
com.opensymphony.xwork2.ActionContext" />
|
||||
|
||||
<!-- this must be valid regex, each '.' in package name must be escaped! -->
|
||||
@@ -60,7 +54,18 @@
|
||||
<!-- constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^(?!javax\.servlet\..+)(javax\..+)" / -->
|
||||
|
||||
<!-- this is simpler version of the above used with string comparison -->
|
||||
<constant name="struts.excludedPackageNames" value="java.lang.,ognl,javax" />
|
||||
<constant name="struts.excludedPackageNames"
|
||||
value="
|
||||
ognl.,
|
||||
javax.,
|
||||
freemarker.core.,
|
||||
freemarker.template.,
|
||||
freemarker.ext.rhino.,
|
||||
sun.reflect.,
|
||||
javassist.,
|
||||
com.opensymphony.xwork2.ognl.,
|
||||
com.opensymphony.xwork2.security.,
|
||||
com.opensymphony.xwork2.util." />
|
||||
|
||||
<bean class="com.opensymphony.xwork2.ObjectFactory" name="struts"/>
|
||||
<bean type="com.opensymphony.xwork2.factory.ResultFactory" name="struts" class="org.apache.struts2.factory.StrutsResultFactory" />
|
||||
|
||||
+86
-61
@@ -68,7 +68,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);
|
||||
@@ -82,7 +82,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");
|
||||
@@ -98,7 +98,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");
|
||||
@@ -114,7 +114,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");
|
||||
@@ -130,7 +130,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();
|
||||
@@ -161,7 +161,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");
|
||||
@@ -184,7 +184,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);
|
||||
@@ -198,7 +198,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);
|
||||
@@ -213,7 +213,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");
|
||||
@@ -221,22 +221,22 @@ 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();
|
||||
parameterMap.put(DefaultActionMapper.METHOD_PREFIX + "someMethod", "");
|
||||
@@ -250,16 +250,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");
|
||||
@@ -271,7 +271,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");
|
||||
@@ -283,7 +283,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");
|
||||
@@ -296,7 +296,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("/my/namespace/actionName!add.action", mapper.getUriFromActionMapping(mapping));
|
||||
}
|
||||
|
||||
public void testGetUriWithOriginalExtension() throws Exception {
|
||||
public void testGetUriWithOriginalExtension() {
|
||||
ActionMapping mapping = new ActionMapping("actionName", "/ns", null, new HashMap());
|
||||
|
||||
ActionMapping orig = new ActionMapping();
|
||||
@@ -307,7 +307,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");
|
||||
@@ -323,7 +323,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");
|
||||
@@ -343,7 +343,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();
|
||||
@@ -353,7 +353,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();
|
||||
@@ -363,7 +363,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();
|
||||
@@ -373,7 +373,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();
|
||||
@@ -384,7 +384,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();
|
||||
@@ -400,7 +400,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
// === test special prefix ===
|
||||
// ===========================
|
||||
|
||||
public void testActionPrefixWhenDisabled() throws Exception {
|
||||
public void testActionPrefixWhenDisabled() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction", "");
|
||||
|
||||
@@ -414,7 +414,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("someServletPath", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testActionPrefixWhenEnabled() throws Exception {
|
||||
public void testActionPrefixWhenEnabled() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction", "");
|
||||
|
||||
@@ -429,7 +429,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("myAction", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testActionPrefixWhenSlashesAndCrossNamespaceDisabled() throws Exception {
|
||||
public void testActionPrefixWhenSlashesAndCrossNamespaceDisabled() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "my/Action", "");
|
||||
|
||||
@@ -445,7 +445,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("my/Action", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespaceDisabled() throws Exception {
|
||||
public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespaceDisabled() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "my/Action", "");
|
||||
|
||||
@@ -461,7 +461,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("Action", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespace() throws Exception {
|
||||
public void testActionPrefixWhenSlashesButSlashesDisabledAndCrossNamespace() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "my/Action", "");
|
||||
|
||||
@@ -478,7 +478,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("my/Action", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testActionPrefixWhenCrossNamespace() throws Exception {
|
||||
public void testActionPrefixWhenCrossNamespace() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "/my/Action", "");
|
||||
|
||||
@@ -494,7 +494,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("/my/Action", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testActionPrefix_fromImageButton() throws Exception {
|
||||
public void testActionPrefix_fromImageButton() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction", "");
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction.x", "");
|
||||
@@ -511,7 +511,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("myAction", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testActionPrefix_fromIEImageButton() throws Exception {
|
||||
public void testActionPrefix_fromIEImageButton() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction.x", "");
|
||||
parameterMap.put(DefaultActionMapper.ACTION_PREFIX + "myAction.y", "");
|
||||
@@ -527,7 +527,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertEquals("myAction", actionMapping.getName());
|
||||
}
|
||||
|
||||
public void testRedirectPrefix() throws Exception {
|
||||
public void testRedirectPrefix() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put("redirect:" + "http://www.google.com", "");
|
||||
|
||||
@@ -543,7 +543,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
public void testUnsafeRedirectPrefix() throws Exception {
|
||||
public void testUnsafeRedirectPrefix() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put("redirect:" + "http://%{3*4}", "");
|
||||
|
||||
@@ -559,7 +559,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
public void testRedirectActionPrefix() throws Exception {
|
||||
public void testRedirectActionPrefix() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put("redirectAction:" + "myAction", "");
|
||||
|
||||
@@ -576,7 +576,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
public void testUnsafeRedirectActionPrefix() throws Exception {
|
||||
public void testUnsafeRedirectActionPrefix() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put("redirectAction:" + "%{3*4}", "");
|
||||
|
||||
@@ -593,7 +593,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
public void testRedirectActionPrefixWithEmptyExtension() throws Exception {
|
||||
public void testRedirectActionPrefixWithEmptyExtension() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put("redirectAction:" + "myAction", "");
|
||||
|
||||
@@ -611,7 +611,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
public void testCustomActionPrefix() throws Exception {
|
||||
public void testCustomActionPrefix() {
|
||||
Map parameterMap = new HashMap();
|
||||
parameterMap.put("foo:myAction", "");
|
||||
|
||||
@@ -630,7 +630,7 @@ 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");
|
||||
assertTrue("Name not right: "+name, "foo".equals(name));
|
||||
@@ -640,7 +640,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
|
||||
}
|
||||
|
||||
public void testDropExtensionWhenBlank() throws Exception {
|
||||
public void testDropExtensionWhenBlank() {
|
||||
DefaultActionMapper mapper = new DefaultActionMapper();
|
||||
mapper.setExtensions("action,,");
|
||||
String name = mapper.dropExtension("foo.action");
|
||||
@@ -651,7 +651,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertNull(mapper.dropExtension("foo."));
|
||||
}
|
||||
|
||||
public void testDropExtensionEmbeddedDot() throws Exception {
|
||||
public void testDropExtensionEmbeddedDot() {
|
||||
DefaultActionMapper mapper = new DefaultActionMapper();
|
||||
mapper.setExtensions("action,,");
|
||||
|
||||
@@ -662,7 +662,7 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
assertTrue("Name not right: "+name, "/foo/bar-1.0/baz".equals(name));
|
||||
}
|
||||
|
||||
public void testGetUriFromActionMapper1() throws Exception {
|
||||
public void testGetUriFromActionMapper1() {
|
||||
DefaultActionMapper mapper = new DefaultActionMapper();
|
||||
ActionMapping actionMapping = new ActionMapping();
|
||||
actionMapping.setMethod("myMethod");
|
||||
@@ -673,7 +673,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");
|
||||
@@ -684,7 +684,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");
|
||||
@@ -696,7 +696,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");
|
||||
@@ -706,7 +706,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");
|
||||
@@ -717,7 +717,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");
|
||||
@@ -728,7 +728,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");
|
||||
@@ -739,7 +739,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");
|
||||
@@ -751,7 +751,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");
|
||||
@@ -761,7 +761,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");
|
||||
@@ -771,7 +771,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");
|
||||
@@ -781,7 +781,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");
|
||||
@@ -791,7 +791,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");
|
||||
@@ -802,7 +802,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();
|
||||
@@ -814,7 +814,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);
|
||||
@@ -839,7 +839,32 @@ public class DefaultActionMapperTest extends StrutsInternalTestCase {
|
||||
|
||||
}
|
||||
|
||||
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";
|
||||
@@ -864,7 +889,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(""));
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.util;
|
||||
|
||||
import com.opensymphony.xwork2.ognl.OgnlUtil;
|
||||
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();
|
||||
} catch (Exception ex){
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
}
|
||||
try {
|
||||
ognlUtil.getExcludedPackageNames().clear();
|
||||
} catch (Exception ex){
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
}
|
||||
try {
|
||||
ognlUtil.getExcludedPackageNamePatterns().clear();
|
||||
} catch (Exception ex){
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-cdi-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-codebehind-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-config-browser-plugin</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-convention-plugin</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-dwr-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-embeddedjsp-plugin</artifactId>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-gxp-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jasperreports-plugin</artifactId>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-java8-support-plugin</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-javatemplates-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jfreechart-plugin</artifactId>
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ChartResultTest extends StrutsTestCase {
|
||||
public void testChart() throws Exception {
|
||||
EasyMock.expect(responseMock.getOutputStream()).andReturn(os);
|
||||
EasyMock.replay(responseMock, mockActionProxy, actionInvocation);
|
||||
|
||||
|
||||
ChartResult result = new ChartResult();
|
||||
|
||||
result.setChart(mockChart);
|
||||
@@ -65,7 +65,7 @@ public class ChartResultTest extends StrutsTestCase {
|
||||
EasyMock.verify(responseMock);
|
||||
assertTrue(os.isWritten());
|
||||
}
|
||||
|
||||
|
||||
public void testContentTypePng() throws Exception {
|
||||
EasyMock.expect(responseMock.getOutputStream()).andReturn(os);
|
||||
responseMock.setContentType("image/png");
|
||||
@@ -82,7 +82,7 @@ public class ChartResultTest extends StrutsTestCase {
|
||||
EasyMock.verify(responseMock);
|
||||
assertTrue(os.isWritten());
|
||||
}
|
||||
|
||||
|
||||
public void testContentTypeJpg() throws Exception {
|
||||
EasyMock.expect(responseMock.getOutputStream()).andReturn(os);
|
||||
responseMock.setContentType("image/jpg");
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jsf-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-json-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-junit-plugin</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-oval-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-pell-multipart-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-plexus-plugin</artifactId>
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-portlet-tiles-plugin</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-portlet-plugin</artifactId>
|
||||
|
||||
+2
@@ -174,6 +174,8 @@ public class PortletActionRedirectResult extends PortletResult {
|
||||
*/
|
||||
public void execute(ActionInvocation invocation) throws Exception {
|
||||
actionName = conditionalParse(actionName, invocation);
|
||||
parseLocation = false;
|
||||
|
||||
String portletNamespace = (String)invocation.getInvocationContext().get(PortletConstants.PORTLET_NAMESPACE);
|
||||
if (portletMode != null) {
|
||||
Map<PortletMode, String> namespaceMap = getNamespaceMap(invocation);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-plugin</artifactId>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
package org.apache.struts2.rest;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import org.apache.struts2.rest.handler.ContentTypeHandler;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -58,10 +59,16 @@ public interface ContentTypeHandlerManager {
|
||||
* @param target The object to return, usually the action object
|
||||
* @return The new result code to process
|
||||
* @throws IOException If unable to write to the response
|
||||
*
|
||||
* @deprecated use version which requires {@link ActionInvocation}
|
||||
*/
|
||||
@Deprecated
|
||||
String handleResult(ActionConfig actionConfig, Object methodResult, Object target)
|
||||
throws IOException;
|
||||
|
||||
String handleResult(ActionInvocation actionInvocation, Object methodResult, Object target)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Finds the extension in the url
|
||||
*
|
||||
|
||||
@@ -61,7 +61,7 @@ public class ContentTypeInterceptor implements Interceptor {
|
||||
if (request.getContentLength() > 0) {
|
||||
InputStream is = request.getInputStream();
|
||||
InputStreamReader reader = new InputStreamReader(is);
|
||||
handler.toObject(reader, target);
|
||||
handler.toObject(invocation, reader, target);
|
||||
}
|
||||
return invocation.invoke();
|
||||
}
|
||||
|
||||
+16
-4
@@ -21,9 +21,12 @@
|
||||
|
||||
package org.apache.struts2.rest;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.rest.handler.ContentTypeHandler;
|
||||
|
||||
@@ -41,6 +44,8 @@ import java.util.Set;
|
||||
*/
|
||||
public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManager {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DefaultContentTypeHandlerManager.class);
|
||||
|
||||
/** ContentTypeHandlers keyed by the extension */
|
||||
Map<String, ContentTypeHandler> handlersByExtension = new HashMap<String, ContentTypeHandler>();
|
||||
/** ContentTypeHandlers keyed by the content-type */
|
||||
@@ -115,7 +120,7 @@ public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManag
|
||||
|
||||
/**
|
||||
* Gets the handler for the response by looking at the extension of the request
|
||||
* @param req The request
|
||||
* @param request The request
|
||||
* @return The appropriate handler
|
||||
*
|
||||
* WW-4588: modified to get a handler for the response side and auto generate the response type
|
||||
@@ -153,20 +158,27 @@ public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManag
|
||||
return handler;
|
||||
}
|
||||
|
||||
public String handleResult(ActionConfig actionConfig, Object methodResult, Object target) throws IOException {
|
||||
LOG.warn("This method is deprecated!");
|
||||
return readResultCode(methodResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the result using handlers to generate content type-specific content
|
||||
*
|
||||
* @param actionConfig The action config for the current request
|
||||
* @param invocation The action invocation for the current request
|
||||
* @param methodResult The object returned from the action method
|
||||
* @param target The object to return, usually the action object
|
||||
* @return The new result code to process
|
||||
* @throws IOException If unable to write to the response
|
||||
*/
|
||||
public String handleResult(ActionConfig actionConfig, Object methodResult, Object target) throws IOException {
|
||||
public String handleResult(ActionInvocation invocation, Object methodResult, Object target) throws IOException {
|
||||
String resultCode = readResultCode(methodResult);
|
||||
Integer statusCode = readStatusCode(methodResult);
|
||||
HttpServletRequest req = ServletActionContext.getRequest();
|
||||
HttpServletResponse res = ServletActionContext.getResponse();
|
||||
ActionConfig actionConfig = invocation.getProxy().getConfig();
|
||||
|
||||
if(statusCode != null) {
|
||||
res.setStatus(statusCode);
|
||||
}
|
||||
@@ -178,7 +190,7 @@ public class DefaultContentTypeHandlerManager implements ContentTypeHandlerManag
|
||||
resultCode = extCode;
|
||||
} else {
|
||||
StringWriter writer = new StringWriter();
|
||||
resultCode = handler.fromObject(target, resultCode, writer);
|
||||
resultCode = handler.fromObject(invocation, target, resultCode, writer);
|
||||
String text = writer.toString();
|
||||
if (text.length() > 0) {
|
||||
byte[] data = text.getBytes("UTF-8");
|
||||
|
||||
@@ -229,9 +229,7 @@ public class RestActionInvocation extends DefaultActionInvocation {
|
||||
if (handler != null && !(handler instanceof HtmlHandler)) {
|
||||
|
||||
// Specific representation (json, xml...)
|
||||
resultCode = handlerSelector.handleResult(
|
||||
this.getProxy().getConfig(), httpHeaders, target);
|
||||
|
||||
resultCode = handlerSelector.handleResult(this, httpHeaders, target);
|
||||
} else {
|
||||
|
||||
// Normal struts execution (html o other struts result)
|
||||
|
||||
@@ -359,7 +359,7 @@ public class RestActionMapper extends DefaultActionMapper {
|
||||
name = uri.substring(namespace.length() + 1);
|
||||
}
|
||||
|
||||
mapping.setNamespace(namespace);
|
||||
mapping.setNamespace(cleanupNamespaceName(namespace));
|
||||
mapping.setName(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -221,7 +221,7 @@ public class RestWorkflowInterceptor extends MethodFilterInterceptor {
|
||||
|
||||
errors.put("actionErrors", validationAwareAction.getActionErrors());
|
||||
errors.put("fieldErrors", validationAwareAction.getFieldErrors());
|
||||
return manager.handleResult(invocation.getProxy().getConfig(), info, errors);
|
||||
return manager.handleResult(invocation, info, errors);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
abstract public class AbstractContentTypeHandler implements ContentTypeHandler {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractContentTypeHandler.class);
|
||||
|
||||
public void toObject(Reader in, Object target) throws IOException {
|
||||
LOG.warn("This method is deprecated!");
|
||||
}
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer stream) throws IOException {
|
||||
LOG.warn("This method is deprecated!");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.rest.handler;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface AllowedClassNames {
|
||||
Set<String> allowedClassNames();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.rest.handler;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface AllowedClasses {
|
||||
Set<Class<?>> allowedClasses();
|
||||
}
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
package org.apache.struts2.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
@@ -34,9 +36,15 @@ public interface ContentTypeHandler {
|
||||
* Populates an object using data from the input stream
|
||||
* @param in The input stream, usually the body of the request
|
||||
* @param target The target, usually the action class
|
||||
* @throws IOException If unable to write to the output stream
|
||||
*
|
||||
* @deprecated use version which requires {@link ActionInvocation}
|
||||
*/
|
||||
@Deprecated
|
||||
void toObject(Reader in, Object target) throws IOException;
|
||||
|
||||
|
||||
void toObject(ActionInvocation invocation, Reader in, Object target) throws IOException;
|
||||
|
||||
/**
|
||||
* Writes content to the stream
|
||||
*
|
||||
@@ -45,9 +53,14 @@ public interface ContentTypeHandler {
|
||||
* @param stream The output stream, usually the response
|
||||
* @return The new result code
|
||||
* @throws IOException If unable to write to the output stream
|
||||
*
|
||||
* @deprecated use version which requires {@link ActionInvocation}
|
||||
*/
|
||||
@Deprecated
|
||||
String fromObject(Object obj, String resultCode, Writer stream) throws IOException;
|
||||
|
||||
|
||||
String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer stream) throws IOException;
|
||||
|
||||
/**
|
||||
* Gets the content type for this handler
|
||||
*
|
||||
|
||||
+12
-6
@@ -20,6 +20,8 @@
|
||||
*/
|
||||
package org.apache.struts2.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@@ -34,21 +36,25 @@ import java.io.Reader;
|
||||
* {@link http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4}
|
||||
*
|
||||
*/
|
||||
public class FormUrlEncodedHandler implements ContentTypeHandler {
|
||||
public class FormUrlEncodedHandler extends AbstractContentTypeHandler {
|
||||
|
||||
public static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer out) throws IOException {
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer out) throws IOException {
|
||||
throw new IOException("Conversion from Object to '"+getContentType()+"' is not supported");
|
||||
}
|
||||
|
||||
/** No transformation is required as the framework handles this data */
|
||||
public void toObject(Reader in, Object target) {
|
||||
/**
|
||||
* No transformation is required as the framework handles this data
|
||||
*
|
||||
* @param in The input stream, usually the body of the request
|
||||
* @param target The target, usually the action class
|
||||
*/
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The extension is not used by this handler
|
||||
* @return
|
||||
* @return The extension is not used by this handler
|
||||
*/
|
||||
public String getExtension() {
|
||||
return null;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
package org.apache.struts2.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
@@ -28,13 +30,13 @@ import java.io.Writer;
|
||||
/**
|
||||
* Handles HTML content, usually just a simple passthrough to the framework
|
||||
*/
|
||||
public class HtmlHandler implements ContentTypeHandler {
|
||||
public class HtmlHandler extends AbstractContentTypeHandler {
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer out) throws IOException {
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer out) throws IOException {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public void toObject(Reader in, Object target) {
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) {
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
|
||||
package org.apache.struts2.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.ObjectReader;
|
||||
import org.codehaus.jackson.map.SerializationConfig.Feature;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@@ -34,20 +35,19 @@ import java.io.Writer;
|
||||
/**
|
||||
* Handles JSON content using jackson-lib
|
||||
*/
|
||||
public class JacksonLibHandler implements ContentTypeHandler {
|
||||
public class JacksonLibHandler extends AbstractContentTypeHandler {
|
||||
|
||||
private static final String DEFAULT_CONTENT_TYPE = "application/json";
|
||||
private String defaultEncoding = "ISO-8859-1";
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
public void toObject(Reader in, Object target) throws IOException {
|
||||
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) throws IOException {
|
||||
mapper.configure(Feature.WRITE_NULL_MAP_VALUES, false);
|
||||
ObjectReader or = mapper.readerForUpdating(target);
|
||||
or.readValue(in); //, new TypeReference<clazz>);
|
||||
or.readValue(in);
|
||||
}
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer stream) throws IOException {
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer stream) throws IOException {
|
||||
mapper.configure(Feature.WRITE_NULL_MAP_VALUES, false);
|
||||
mapper.writeValue(stream, obj);
|
||||
return null;
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import net.sf.json.JSONArray;
|
||||
import net.sf.json.JSONObject;
|
||||
import net.sf.json.JsonConfig;
|
||||
@@ -37,12 +38,12 @@ import com.opensymphony.xwork2.inject.Inject;
|
||||
/**
|
||||
* Handles JSON content using json-lib
|
||||
*/
|
||||
public class JsonLibHandler implements ContentTypeHandler {
|
||||
public class JsonLibHandler extends AbstractContentTypeHandler {
|
||||
|
||||
private static final String DEFAULT_CONTENT_TYPE = "application/json";
|
||||
private String defaultEncoding = "ISO-8859-1";
|
||||
|
||||
public void toObject(Reader in, Object target) throws IOException {
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char[] buffer = new char[1024];
|
||||
int len = 0;
|
||||
@@ -63,7 +64,7 @@ public class JsonLibHandler implements ContentTypeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer stream) throws IOException {
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer stream) throws IOException {
|
||||
if (obj != null) {
|
||||
if (isArray(obj)) {
|
||||
JSONArray jsonArray = JSONArray.fromObject(obj);
|
||||
|
||||
+12
-6
@@ -20,6 +20,8 @@
|
||||
*/
|
||||
package org.apache.struts2.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
import java.io.Writer;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@@ -35,21 +37,25 @@ import java.io.Reader;
|
||||
* {@link http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4}
|
||||
*
|
||||
*/
|
||||
public class MultipartFormDataHandler implements ContentTypeHandler {
|
||||
public class MultipartFormDataHandler extends AbstractContentTypeHandler {
|
||||
|
||||
public static final String CONTENT_TYPE = "multipart/form-data";
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer out) throws IOException {
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer out) throws IOException {
|
||||
throw new IOException("Conversion from Object to '"+getContentType()+"' is not supported");
|
||||
}
|
||||
|
||||
/** No transformation is required as the framework handles this data */
|
||||
public void toObject(Reader in, Object target) {
|
||||
/**
|
||||
* No transformation is required as the framework handles this data
|
||||
*
|
||||
* @param in The input stream, usually the body of the request
|
||||
* @param target The target, usually the action class
|
||||
*/
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The extension is not used by this handler
|
||||
* @return
|
||||
* @return The extension is not used by this handler
|
||||
*/
|
||||
public String getExtension() {
|
||||
return null;
|
||||
|
||||
@@ -21,34 +21,98 @@
|
||||
|
||||
package org.apache.struts2.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.ModelDriven;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.security.ArrayTypePermission;
|
||||
import com.thoughtworks.xstream.security.ExplicitTypePermission;
|
||||
import com.thoughtworks.xstream.security.NoTypePermission;
|
||||
import com.thoughtworks.xstream.security.NullPermission;
|
||||
import com.thoughtworks.xstream.security.PrimitiveTypePermission;
|
||||
import com.thoughtworks.xstream.security.TypePermission;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Handles XML content
|
||||
*/
|
||||
public class XStreamHandler implements ContentTypeHandler {
|
||||
public class XStreamHandler extends AbstractContentTypeHandler {
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer out) throws IOException {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(XStreamHandler.class);
|
||||
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer out) throws IOException {
|
||||
if (obj != null) {
|
||||
XStream xstream = createXStream();
|
||||
XStream xstream = createXStream(invocation);
|
||||
xstream.toXML(obj, out);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void toObject(Reader in, Object target) {
|
||||
XStream xstream = createXStream();
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) {
|
||||
XStream xstream = createXStream(invocation);
|
||||
xstream.fromXML(in, target);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated use version with {@link ActionInvocation}
|
||||
*/
|
||||
@Deprecated
|
||||
protected XStream createXStream() {
|
||||
LOG.warn("You are using a deprecated API!");
|
||||
return new XStream();
|
||||
}
|
||||
|
||||
protected XStream createXStream(ActionInvocation invocation) {
|
||||
XStream stream = new XStream();
|
||||
LOG.debug("Clears existing permissions");
|
||||
stream.addPermission(NoTypePermission.NONE);
|
||||
|
||||
LOG.debug("Adds per action permissions");
|
||||
addPerActionPermission(invocation, stream);
|
||||
|
||||
LOG.debug("Adds default permissions");
|
||||
addDefaultPermissions(invocation, stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
private void addPerActionPermission(ActionInvocation invocation, XStream stream) {
|
||||
Object action = invocation.getAction();
|
||||
if (action instanceof AllowedClasses) {
|
||||
Set<Class<?>> allowedClasses = ((AllowedClasses) action).allowedClasses();
|
||||
stream.addPermission(new ExplicitTypePermission(allowedClasses.toArray(new Class[allowedClasses.size()])));
|
||||
}
|
||||
if (action instanceof AllowedClassNames) {
|
||||
Set<String> allowedClassNames = ((AllowedClassNames) action).allowedClassNames();
|
||||
stream.addPermission(new ExplicitTypePermission(allowedClassNames.toArray(new String[allowedClassNames.size()])));
|
||||
}
|
||||
if (action instanceof XStreamPermissionProvider) {
|
||||
Collection<TypePermission> permissions = ((XStreamPermissionProvider) action).getTypePermissions();
|
||||
for (TypePermission permission : permissions) {
|
||||
stream.addPermission(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void addDefaultPermissions(ActionInvocation invocation, XStream stream) {
|
||||
stream.addPermission(new ExplicitTypePermission(new Class[]{invocation.getAction().getClass()}));
|
||||
if (invocation.getAction() instanceof ModelDriven) {
|
||||
stream.addPermission(new ExplicitTypePermission(new Class[]{((ModelDriven) invocation.getAction()).getModel().getClass()}));
|
||||
}
|
||||
stream.addPermission(NullPermission.NULL);
|
||||
stream.addPermission(PrimitiveTypePermission.PRIMITIVES);
|
||||
stream.addPermission(ArrayTypePermission.ARRAYS);
|
||||
stream.addPermission(CollectionTypePermission.COLLECTIONS);
|
||||
stream.addPermission(new ExplicitTypePermission(new Class[]{Date.class}));
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return "application/xml";
|
||||
}
|
||||
@@ -56,4 +120,15 @@ public class XStreamHandler implements ContentTypeHandler {
|
||||
public String getExtension() {
|
||||
return "xml";
|
||||
}
|
||||
|
||||
private static class CollectionTypePermission implements TypePermission {
|
||||
|
||||
private static final TypePermission COLLECTIONS = new CollectionTypePermission();
|
||||
|
||||
public boolean allows(Class type) {
|
||||
return type != null && type.isInterface() &&
|
||||
(Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.rest.handler;
|
||||
|
||||
import com.thoughtworks.xstream.security.TypePermission;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface XStreamPermissionProvider {
|
||||
Collection<TypePermission> getTypePermissions();
|
||||
}
|
||||
+17
-5
@@ -24,10 +24,14 @@ package org.apache.struts2.rest;
|
||||
import com.mockobjects.dynamic.C;
|
||||
import com.mockobjects.dynamic.Mock;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.mock.MockActionInvocation;
|
||||
import com.opensymphony.xwork2.mock.MockActionProxy;
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.rest.handler.AbstractContentTypeHandler;
|
||||
import org.apache.struts2.rest.handler.ContentTypeHandler;
|
||||
import org.apache.struts2.rest.handler.FormUrlEncodedHandler;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
@@ -49,6 +53,7 @@ public class ContentTypeHandlerManagerTest extends TestCase {
|
||||
private DefaultContentTypeHandlerManager mgr;
|
||||
private MockHttpServletResponse mockResponse;
|
||||
private MockHttpServletRequest mockRequest;
|
||||
private MockActionInvocation invocation;
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
@@ -59,6 +64,9 @@ public class ContentTypeHandlerManagerTest extends TestCase {
|
||||
ActionContext.setContext(new ActionContext(new HashMap()));
|
||||
ServletActionContext.setRequest(mockRequest);
|
||||
ServletActionContext.setResponse(mockResponse);
|
||||
|
||||
invocation = new MockActionInvocation();
|
||||
invocation.setProxy(new MockActionProxy());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,9 +79,9 @@ public class ContentTypeHandlerManagerTest extends TestCase {
|
||||
public void testHandleResultOK() throws IOException {
|
||||
|
||||
String obj = "mystring";
|
||||
ContentTypeHandler handler = new ContentTypeHandler() {
|
||||
public void toObject(Reader in, Object target) {}
|
||||
public String fromObject(Object obj, String resultCode, Writer stream) throws IOException {
|
||||
ContentTypeHandler handler = new AbstractContentTypeHandler() {
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) {}
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer stream) throws IOException {
|
||||
stream.write(obj.toString());
|
||||
return resultCode;
|
||||
}
|
||||
@@ -82,7 +90,11 @@ public class ContentTypeHandlerManagerTest extends TestCase {
|
||||
};
|
||||
mgr.handlersByExtension.put("xml", handler);
|
||||
mgr.setDefaultExtension("xml");
|
||||
mgr.handleResult(new ActionConfig.Builder("", "", "").build(), new DefaultHttpHeaders().withStatus(SC_OK), obj);
|
||||
ActionConfig actionConfig = new ActionConfig.Builder("", "", "").build();
|
||||
MockActionProxy proxy = new MockActionProxy();
|
||||
proxy.setConfig(actionConfig);
|
||||
invocation.setProxy(proxy);
|
||||
mgr.handleResult(invocation, new DefaultHttpHeaders().withStatus(SC_OK), obj);
|
||||
|
||||
assertEquals(obj.getBytes().length, mockResponse.getContentLength());
|
||||
}
|
||||
@@ -92,7 +104,7 @@ public class ContentTypeHandlerManagerTest extends TestCase {
|
||||
Mock mockHandlerXml = new Mock(ContentTypeHandler.class);
|
||||
mockHandlerXml.matchAndReturn("getExtension", "xml");
|
||||
mgr.handlersByExtension.put("xml", (ContentTypeHandler) mockHandlerXml.proxy());
|
||||
mgr.handleResult(null, new DefaultHttpHeaders().withStatus(SC_NOT_MODIFIED), new Object());
|
||||
mgr.handleResult(invocation, new DefaultHttpHeaders().withStatus(SC_NOT_MODIFIED), new Object());
|
||||
|
||||
assertEquals(0, mockResponse.getContentLength());
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,8 +1,10 @@
|
||||
package org.apache.struts2.rest;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.XWorkTestCase;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.Scope;
|
||||
import org.apache.struts2.rest.handler.AbstractContentTypeHandler;
|
||||
import org.apache.struts2.rest.handler.ContentTypeHandler;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@@ -113,13 +115,13 @@ class DummyContainer implements Container {
|
||||
private ContentTypeHandler handler;
|
||||
|
||||
DummyContainer(final String contentType, final String extension) {
|
||||
handler = new ContentTypeHandler() {
|
||||
handler = new AbstractContentTypeHandler() {
|
||||
|
||||
public void toObject(Reader in, Object target) throws IOException {
|
||||
public void toObject(ActionInvocation invocation, Reader in, Object target) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public String fromObject(Object obj, String resultCode, Writer stream) throws IOException {
|
||||
public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer stream) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ public class RestWorkflowInterceptorTest extends TestCase {
|
||||
Mock mockActionInvocation = new Mock(ActionInvocation.class);
|
||||
Mock mockActionProxy = new Mock(ActionProxy.class);
|
||||
mockActionProxy.expectAndReturn("getConfig", null);
|
||||
mockActionInvocation.expectAndReturn("getProxy", mockActionProxy.proxy());
|
||||
mockActionInvocation.expectAndReturn("getAction", action);
|
||||
Mock mockContentTypeHandlerManager = new Mock(ContentTypeHandlerManager.class);
|
||||
mockContentTypeHandlerManager.expectAndReturn("handleResult", new AnyConstraintMatcher() {
|
||||
|
||||
+5
-4
@@ -21,6 +21,7 @@
|
||||
|
||||
package org.apache.struts2.rest.handler;
|
||||
|
||||
import com.opensymphony.xwork2.mock.MockActionInvocation;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -37,7 +38,7 @@ public class JacksonLibHandlerTest extends TestCase {
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
JacksonLibHandler handler = new JacksonLibHandler();
|
||||
handler.fromObject(contact, "success", writer);
|
||||
handler.fromObject(new MockActionInvocation(), contact, "success", writer);
|
||||
String data = writer.toString();
|
||||
assertTrue(data.startsWith("{"));
|
||||
assertTrue(data.contains("\"age\":44"));
|
||||
@@ -50,7 +51,7 @@ public class JacksonLibHandlerTest extends TestCase {
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
JacksonLibHandler handler = new JacksonLibHandler();
|
||||
handler.fromObject(Arrays.asList(contact), "success", writer);
|
||||
handler.fromObject(new MockActionInvocation(), Arrays.asList(contact), "success", writer);
|
||||
|
||||
String data = writer.toString();
|
||||
assertTrue(data.startsWith("[{"));
|
||||
@@ -65,7 +66,7 @@ public class JacksonLibHandlerTest extends TestCase {
|
||||
Contact target = new Contact();
|
||||
StringReader reader = new StringReader("{\"age\":44,\"important\":true,\"name\":\"bob\"}");
|
||||
JacksonLibHandler handler = new JacksonLibHandler();
|
||||
handler.toObject(reader, target);
|
||||
handler.toObject(new MockActionInvocation(), reader, target);
|
||||
assertEquals(contact, target);
|
||||
}
|
||||
|
||||
@@ -78,7 +79,7 @@ public class JacksonLibHandlerTest extends TestCase {
|
||||
List<Contact> target = new ArrayList<Contact>();
|
||||
StringReader reader = new StringReader("[{\"age\":44,\"important\":true,\"name\":\"bob\"},{\"age\":33,\"important\":false,\"name\":\"john\"}]");
|
||||
JacksonLibHandler handler = new JacksonLibHandler();
|
||||
handler.toObject(reader, target);
|
||||
handler.toObject(new MockActionInvocation(), reader, target);
|
||||
assertEquals(source.size(), target.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.opensymphony.xwork2.mock.MockActionInvocation;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class JsonLibHandlerTest extends TestCase {
|
||||
@@ -35,7 +36,7 @@ public class JsonLibHandlerTest extends TestCase {
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonLibHandler handler = new JsonLibHandler();
|
||||
handler.fromObject(contact, "success", writer);
|
||||
handler.fromObject(new MockActionInvocation(), contact, "success", writer);
|
||||
String data = writer.toString();
|
||||
assertTrue(data.startsWith("{"));
|
||||
assertTrue(data.contains("\"age\":44"));
|
||||
@@ -48,7 +49,7 @@ public class JsonLibHandlerTest extends TestCase {
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonLibHandler handler = new JsonLibHandler();
|
||||
handler.fromObject(Arrays.asList(contact), "success", writer);
|
||||
handler.fromObject(new MockActionInvocation(), Arrays.asList(contact), "success", writer);
|
||||
|
||||
String data = writer.toString();
|
||||
assertTrue(data.startsWith("[{"));
|
||||
@@ -63,7 +64,7 @@ public class JsonLibHandlerTest extends TestCase {
|
||||
Contact target = new Contact();
|
||||
StringReader reader = new StringReader("{\"age\":44,\"important\":true,\"name\":\"bob\"}");
|
||||
JsonLibHandler handler = new JsonLibHandler();
|
||||
handler.toObject(reader, target);
|
||||
handler.toObject(new MockActionInvocation(), reader, target);
|
||||
|
||||
assertEquals(contact, target);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-sitegraph-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-sitemesh-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-spring-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-struts1-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-testng-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-tiles-plugin</artifactId>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-tiles3-plugin</artifactId>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts-master</artifactId>
|
||||
<version>9</version>
|
||||
<version>11</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Struts 2</name>
|
||||
<url>http://struts.apache.org/</url>
|
||||
@@ -28,20 +28,20 @@
|
||||
-->
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://git.apache.org/struts.git</connection>
|
||||
<developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/struts.git</developerConnection>
|
||||
<url>http://git.apache.org/struts.git</url>
|
||||
<tag>STRUTS_2_3_33</tag>
|
||||
<connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection>
|
||||
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection>
|
||||
<url>https://github.com/apache/struts/</url>
|
||||
<tag>STRUTS_2_3_37</tag>
|
||||
</scm>
|
||||
|
||||
<issueManagement>
|
||||
<system>JIRA</system>
|
||||
<url>https://issues.apache.org/jira/browse/WW</url>
|
||||
<url>https://issues.apache.org/jira/projects/WW</url>
|
||||
</issueManagement>
|
||||
|
||||
<ciManagement>
|
||||
<system>Jenkins</system>
|
||||
<url>https://builds.apache.org/hudson/view/S-Z/view/Struts</url>
|
||||
<url>https://builds.apache.org/view/S-Z/view/Struts/</url>
|
||||
<notifiers>
|
||||
<notifier>
|
||||
<type>mail</type>
|
||||
@@ -52,13 +52,6 @@
|
||||
</notifiers>
|
||||
</ciManagement>
|
||||
|
||||
<distributionManagement>
|
||||
<site>
|
||||
<id>apache-site</id>
|
||||
<url>scm:svn:https://svn.apache.org/repos/infra/websites/production/struts/content/release/2.3.x/</url>
|
||||
</site>
|
||||
</distributionManagement>
|
||||
|
||||
<modules>
|
||||
<module>bom</module>
|
||||
<module>xwork-core</module>
|
||||
@@ -86,7 +79,7 @@
|
||||
<properties>
|
||||
<currentVersion>${project.version}</currentVersion>
|
||||
<struts2.springPlatformVersion>3.0.5.RELEASE</struts2.springPlatformVersion>
|
||||
<ognl.version>3.0.19</ognl.version>
|
||||
<ognl.version>3.0.21</ognl.version>
|
||||
<asm.version>3.3</asm.version>
|
||||
<asm5.version>5.0.2</asm5.version>
|
||||
<tiles.version>2.2.2</tiles.version>
|
||||
@@ -143,6 +136,11 @@
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>net.nicoulaj.maven.plugins</groupId>
|
||||
<artifactId>checksum-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
@@ -166,8 +164,8 @@
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -181,6 +179,7 @@
|
||||
<excludes>
|
||||
<exclude>**/TestBean.java</exclude>
|
||||
</excludes>
|
||||
<useFile>false</useFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -197,6 +196,24 @@
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>net.nicoulaj.maven.plugins</groupId>
|
||||
<artifactId>checksum-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>artifacts</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<algorithms>
|
||||
<algorithm>SHA-256</algorithm>
|
||||
<algorithm>SHA-512</algorithm>
|
||||
</algorithms>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
@@ -543,7 +560,7 @@
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.22</version>
|
||||
<version>2.3.28</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -764,7 +781,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
@@ -940,7 +957,7 @@
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.8</version>
|
||||
<version>1.4.10</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.3.33</version>
|
||||
<version>2.3.37</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.apache.struts.xwork</groupId>
|
||||
|
||||
@@ -197,17 +197,14 @@ 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)
|
||||
: null;
|
||||
? TextParseUtil.translateVariables(this.methodName, stack)
|
||||
: null;
|
||||
|
||||
if (isInChainHistory(finalNamespace, finalActionName, finalMethodName)) {
|
||||
addToHistory(finalNamespace, finalActionName, finalMethodName);
|
||||
|
||||
-1
@@ -3,7 +3,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;
|
||||
|
||||
+1
-2
@@ -13,13 +13,12 @@
|
||||
* See the License for the 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 com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -66,14 +67,20 @@ public class OgnlUtil {
|
||||
private boolean enableExpressionCache = true;
|
||||
private boolean enableEvalExpression;
|
||||
|
||||
private Set<Class<?>> excludedClasses = new HashSet<Class<?>>();
|
||||
private Set<Pattern> excludedPackageNamePatterns = new HashSet<Pattern>();
|
||||
private Set<String> excludedPackageNames = new HashSet<String>();
|
||||
private Set<Class<?>> excludedClasses;
|
||||
private Set<Pattern> excludedPackageNamePatterns;
|
||||
private Set<String> excludedPackageNames;
|
||||
|
||||
private Container container;
|
||||
private boolean allowStaticMethodAccess;
|
||||
private boolean disallowProxyMemberAccess;
|
||||
|
||||
public OgnlUtil() {
|
||||
excludedClasses = new HashSet<Class<?>>();
|
||||
excludedPackageNamePatterns = new HashSet<Pattern>();
|
||||
excludedPackageNames = new HashSet<String>();
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setXWorkConverter(XWorkConverter conv) {
|
||||
this.defaultConverter = new OgnlTypeConverterWrapper(conv);
|
||||
@@ -100,27 +107,56 @@ public class OgnlUtil {
|
||||
|
||||
@Inject(value = XWorkConstants.OGNL_EXCLUDED_CLASSES, required = false)
|
||||
public void setExcludedClasses(String commaDelimitedClasses) {
|
||||
Set<String> classes = TextParseUtil.commaDelimitedStringToSet(commaDelimitedClasses);
|
||||
for (String className : classes) {
|
||||
Set<Class<?>> excludedClasses = new HashSet<Class<?>>();
|
||||
excludedClasses.addAll(this.excludedClasses);
|
||||
excludedClasses.addAll(parseExcludedClasses(commaDelimitedClasses));
|
||||
this.excludedClasses = Collections.unmodifiableSet(excludedClasses);
|
||||
}
|
||||
|
||||
private Set<Class<?>> parseExcludedClasses(String commaDelimitedClasses) {
|
||||
Set<String> classNames = TextParseUtil.commaDelimitedStringToSet(commaDelimitedClasses);
|
||||
Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||
|
||||
for (String className : classNames) {
|
||||
try {
|
||||
excludedClasses.add(Class.forName(className));
|
||||
classes.add(Class.forName(className));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new ConfigurationException("Cannot load excluded class: " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
@Inject(value = XWorkConstants.OGNL_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false)
|
||||
public void setExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) {
|
||||
Set<Pattern> excludedPackageNamePatterns = new HashSet<Pattern>();
|
||||
excludedPackageNamePatterns.addAll(this.excludedPackageNamePatterns);
|
||||
excludedPackageNamePatterns.addAll(parseExcludedPackageNamePatterns(commaDelimitedPackagePatterns));
|
||||
this.excludedPackageNamePatterns = Collections.unmodifiableSet(excludedPackageNamePatterns);
|
||||
}
|
||||
|
||||
private Set<Pattern> parseExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) {
|
||||
Set<String> packagePatterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackagePatterns);
|
||||
Set<Pattern> packageNamePatterns = new HashSet<Pattern>();
|
||||
|
||||
for (String pattern : packagePatterns) {
|
||||
excludedPackageNamePatterns.add(Pattern.compile(pattern));
|
||||
packageNamePatterns.add(Pattern.compile(pattern));
|
||||
}
|
||||
|
||||
return packageNamePatterns;
|
||||
}
|
||||
|
||||
@Inject(value = XWorkConstants.OGNL_EXCLUDED_PACKAGE_NAMES, required = false)
|
||||
public void setExcludedPackageNames(String commaDelimitedPackageNames) {
|
||||
excludedPackageNames = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackageNames);
|
||||
Set<String> excludedPackageNames = new HashSet<String>();
|
||||
excludedPackageNames.addAll(this.excludedPackageNames);
|
||||
excludedPackageNames.addAll(parseExcludedPackageNames(commaDelimitedPackageNames));
|
||||
this.excludedPackageNames = Collections.unmodifiableSet(excludedPackageNames);
|
||||
}
|
||||
|
||||
private Set<String> parseExcludedPackageNames(String commaDelimitedPackageNames) {
|
||||
return TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackageNames);
|
||||
}
|
||||
|
||||
public Set<Class<?>> getExcludedClasses() {
|
||||
|
||||
@@ -55,19 +55,24 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
|
||||
|
||||
@Override
|
||||
public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
|
||||
if (checkEnumAccess(target, member)) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Allowing access to enum #0", target);
|
||||
}
|
||||
return true;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Checking access for [target: #0, member: #1, property: #2]", target, member, propertyName);
|
||||
}
|
||||
|
||||
Class targetClass = target.getClass();
|
||||
Class memberClass = member.getDeclaringClass();
|
||||
|
||||
if (checkEnumAccess(target, member)) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Allowing access to enum: target class [#0] of target [#1], member [#2]", targetClass, target, member);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Modifier.isStatic(member.getModifiers()) && allowStaticMethodAccess) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Support for accessing static methods [target: #0, member: #1, property: #2] is deprecated!", target, member, propertyName);
|
||||
LOG.debug("Support for accessing static methods [target: #0, targetClass: #1, member: #2, property: #3] is deprecated!",
|
||||
target, targetClass, member, propertyName);
|
||||
}
|
||||
if (!isClassExcluded(member.getDeclaringClass())) {
|
||||
targetClass = member.getDeclaringClass();
|
||||
@@ -76,14 +81,15 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
|
||||
|
||||
if (isPackageExcluded(targetClass.getPackage(), memberClass.getPackage())) {
|
||||
if (LOG.isWarnEnabled()) {
|
||||
LOG.warn("Package of target [#0] or package of member [#1] are excluded!", target, member);
|
||||
LOG.warn("Package [#0] of target class [#1] of target [#2] or package [#3] of member [#4] are excluded!", targetClass.getPackage(),
|
||||
targetClass, target, memberClass.getPackage(), member);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isClassExcluded(targetClass)) {
|
||||
if (LOG.isWarnEnabled()) {
|
||||
LOG.warn("Target class [#0] is excluded!", target);
|
||||
LOG.warn("Target class [#0] of target [#1] is excluded!", targetClass, target);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -96,7 +102,7 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
|
||||
}
|
||||
|
||||
if (disallowProxyMemberAccess && ProxyUtil.isProxyMember(member, target)) {
|
||||
LOG.warn("Access to proxy [#0] is blocked!", member);
|
||||
LOG.warn("Access to proxy is blocked! Target class [#0] of target [#1], member [#2]", targetClass, target, member);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -139,9 +145,9 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
|
||||
if (LOG.isWarnEnabled() && (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()) {
|
||||
@@ -149,9 +155,11 @@ public class SecurityMemberAccess extends DefaultMemberAccess {
|
||||
}
|
||||
}
|
||||
|
||||
targetPackageName = targetPackageName + ".";
|
||||
memberPackageName = memberPackageName + ".";
|
||||
|
||||
for (String packageName: excludedPackageNames) {
|
||||
if (targetPackageName.startsWith(packageName) || targetPackageName.equals(packageName)
|
||||
|| memberPackageName.startsWith(packageName) || memberPackageName.equals(packageName)) {
|
||||
if (targetPackageName.startsWith(packageName) || memberPackageName.startsWith(packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-12
@@ -73,19 +73,18 @@ public class URLValidator extends FieldValidatorSupport {
|
||||
} else if (StringUtils.isNotEmpty(urlRegex)) {
|
||||
return urlRegex;
|
||||
} else {
|
||||
return "^(https?|ftp):\\/\\/" +
|
||||
"(([a-z0-9$_\\.\\+!\\*\\'\\(\\),;\\?&=-]|%[0-9a-f]{2})+" +
|
||||
"(:([a-z0-9$_\\.\\+!\\*\\'\\(\\),;\\?&=-]|%[0-9a-f]{2})+)?" +
|
||||
"@)?(#?" +
|
||||
")((([a-z0-9]\\.|[a-z0-9][a-z0-9-]*[a-z0-9]\\.)*" +
|
||||
return "^(?:https?|ftp):\\/\\/" +
|
||||
"(?:(?:[a-z0-9$_.+!*'(),;?&=\\-]|%[0-9a-f]{2})+" +
|
||||
"(?::(?:[a-z0-9$_.+!*'(),;?&=\\-]|%[0-9a-f]{2})+)?" +
|
||||
"@)?#?" +
|
||||
"(?:(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)*" +
|
||||
"[a-z][a-z0-9-]*[a-z0-9]" +
|
||||
"|((\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])\\.){3}" +
|
||||
"(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" +
|
||||
")(:\\d+)?" +
|
||||
")(((\\/{0,1}([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)*" +
|
||||
"(\\?([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)" +
|
||||
"?)?)?" +
|
||||
"(#([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)?" +
|
||||
"|(?:(?:[1-9]?\\d|1\\d{2}|2[0-4]\\d|25[0-5])\\.){3}" +
|
||||
"(?:[1-9]?\\d|1\\d{2}|2[0-4]\\d|25[0-5])" +
|
||||
")(?::\\d+)?" +
|
||||
")(?:(?:\\/(?:[a-z0-9$_.+!*'(),;:@&=\\-]|%[0-9a-f]{2})*)*" +
|
||||
"(?:\\?(?:[a-z0-9$_.+!*'(),;:@&=\\-\\/:]|%[0-9a-f]{2})*)?)?" +
|
||||
"(?:#(?:[a-z0-9$_.+!*'(),;:@&=\\-]|%[0-9a-f]{2})*)?" +
|
||||
"$";
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
* See the License for the 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;
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Unit test of {@link ognlUtil}.
|
||||
* Unit test of {@link OgnlUtil}.
|
||||
*
|
||||
* @version $Date$ $Id$
|
||||
*/
|
||||
|
||||
+22
-8
@@ -4,7 +4,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;
|
||||
@@ -168,7 +167,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
// then
|
||||
assertFalse("stringField is accessible!", actual);
|
||||
}
|
||||
|
||||
|
||||
public void testPackageNameExclusion() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false);
|
||||
@@ -187,29 +186,29 @@ 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<Pattern> excluded = new HashSet<Pattern>();
|
||||
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
|
||||
sma.setExcludedPackageNamePatterns(excluded);
|
||||
|
||||
|
||||
// when
|
||||
boolean actual = sma.isPackageExcluded(null, null);
|
||||
|
||||
// then
|
||||
assertFalse("default package is excluded!", actual);
|
||||
}
|
||||
|
||||
public void testDefaultPackageExclusion2() throws Exception {
|
||||
|
||||
public void testDefaultPackageExclusion2() {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false);
|
||||
|
||||
Set<Pattern> excluded = new HashSet<Pattern>();
|
||||
excluded.add(Pattern.compile("^$"));
|
||||
sma.setExcludedPackageNamePatterns(excluded);
|
||||
|
||||
|
||||
// when
|
||||
boolean actual = sma.isPackageExcluded(null, null);
|
||||
|
||||
@@ -299,7 +298,7 @@ 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<Class<?>> excluded = new HashSet<Class<?>>();
|
||||
@@ -401,6 +400,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 {
|
||||
|
||||
Reference in New Issue
Block a user