Compare commits

..

52 Commits

Author SHA1 Message Date
Lukasz Lenart 4f8cb5211f [maven-release-plugin] prepare release STRUTS_7_0_0_M8 2024-07-11 09:48:14 +02:00
Lukasz Lenart b16ae04459 Merge pull request #984 from apache/fic/WW-5438-weld
WW-5438 Fixes scope of Weld dependencies
2024-07-11 08:26:12 +02:00
Lukasz Lenart 8c8bf6bc7d WW-5438 Fixes scope of Weld dependencies 2024-07-09 08:05:25 +02:00
Kusal Kithul-Godage 713fd3ba26 Merge pull request #983 from apache/7.0.x/merge-master-2024-07-09
Merge master to 7.0.x, 2024-07-09
2024-07-09 06:21:07 +10:00
Kusal Kithul-Godage d995b1a85e Merge remote-tracking branch 'origin/master' into 7.0.x/merge-master-2024-07-09 2024-07-09 05:45:36 +10:00
Kusal Kithul-Godage d4a0f4fdde Merge pull request #982 from apache/WW-5428-stop-excessive-logging
WW-5428 Stop excessive logging in DevMode
2024-07-09 05:44:33 +10:00
Kusal Kithul-Godage 9fe1a4a031 WW-5428 Stop excessive logging in DevMode 2024-07-09 05:01:02 +10:00
Kusal Kithul-Godage 70b5d7c83e Merge pull request #981 from apache/WW-5411-delete-deprecated-1
WW-5411 Delete deprecated method/classes
2024-07-08 21:29:32 +10:00
Lukasz Lenart 3693ea2eec Merge pull request #978 from apache/dependabot/github_actions/actions/upload-artifact-4.3.4
Bump actions/upload-artifact from 4.3.3 to 4.3.4
2024-07-08 13:19:12 +02:00
Lukasz Lenart 7cb57087d3 Merge pull request #976 from apache/dependabot/maven/org.apache.maven.plugins-maven-failsafe-plugin-3.3.0
Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.2.5 to 3.3.0
2024-07-08 13:18:59 +02:00
Kusal Kithul-Godage b65005c72d Merge pull request #980 from apache/7.0.x/merge-master-2024-07-08
Merge master to 7.0.x, 2024-07-08
2024-07-08 21:18:46 +10:00
Kusal Kithul-Godage a3cc0422f9 WW-5411 Delete more deprecated methods from OgnlUtil 2024-07-08 20:40:02 +10:00
Kusal Kithul-Godage 089f620ea2 WW-5411 Delete deprecated Aware marker interfaces 2024-07-08 20:37:11 +10:00
Kusal Kithul-Godage 61d593620f WW-5411 Delete misc deprecated methods from 6.4.0 2024-07-08 20:37:11 +10:00
Kusal Kithul-Godage 31bdbfc27a WW-5411 Delete deprecated Velocity injection methods 2024-07-08 20:37:11 +10:00
Kusal Kithul-Godage 1b8e7ac824 WW-5411 Delete misc deprecated methods from 6.2.0 2024-07-08 20:37:11 +10:00
Kusal Kithul-Godage e3624835f0 WW-5411 Delete deprecated members from prepare filters 2024-07-08 20:37:11 +10:00
Kusal Kithul-Godage c801c8a741 WW-5411 Delete deprecated methods from OgnlUtil 2024-07-08 20:37:09 +10:00
Kusal Kithul-Godage ead66f2f75 WW-5411 Delete deprecated methods from cache factories and OgnlUtil constructor 2024-07-08 20:33:46 +10:00
Kusal Kithul-Godage 4944f1838f WW-5411 Delete deprecated methods from OgnlValueStack 2024-07-08 20:33:46 +10:00
Kusal Kithul-Godage e2d5cc2bd7 Merge branch 'refs/heads/master' into 7.0.x/merge-master-2024-07-08 2024-07-08 20:21:30 +10:00
Kusal Kithul-Godage 398e104fe0 Merge pull request #979 from apache/WW-5439-fix-dev-mode
WW-5439 Move DevMode security configuration to SecurityMemberAccess
2024-07-08 20:18:40 +10:00
Kusal Kithul-Godage 7f57e895a1 Merge pull request #967 from apache/WW-5428-allowlist-hibernate
WW-5428 Allowlist capability should resolve Hibernate proxies when disableProxyObjects is not set
2024-07-08 20:15:38 +10:00
Kusal Kithul-Godage 81b4943176 WW-5439 Move Dev Mode security configuration 2024-07-08 20:01:53 +10:00
Kusal Kithul-Godage 05680d7827 WW-5428 Amend log warning for missing allowlist entry 2024-07-08 19:57:36 +10:00
Kusal Kithul-Godage 8555dc266e WW-5428 Add log warning for allowlist disabled 2024-07-08 19:52:22 +10:00
Kusal Kithul-Godage c6f394a0e8 WW-5428 Add log warning for Hibernate entities 2024-07-08 19:44:05 +10:00
Kusal Kithul-Godage c965812ffe WW-5428 Add unit test coverage for Hibernate proxy resolution 2024-07-08 16:58:07 +10:00
Kusal Kithul-Godage abf03fdccc WW-5428 Clean up SecurityMemberAccessProxyTest 2024-07-08 16:58:07 +10:00
Kusal Kithul-Godage 2f814186c8 WW-5428 Allowlist capability should resolve Hibernate proxies when disableProxyObjects is not set 2024-07-08 16:58:07 +10:00
dependabot[bot] 7762d7fba2 Bump actions/upload-artifact from 4.3.3 to 4.3.4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.3 to 4.3.4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/65462800fd760344b1a7b4382951275a0abb4808...0b2256b8c012f0828dc542b3febcab082c67f72b)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-08 01:40:34 +00:00
Lukasz Lenart 82b364d521 Merge pull request #977 from stefansielaff/fix-behavior-of-envsvaluesubstitutor
WW-5437 Swap order of sysStrSubstitutor and envStrSubstitutor in substitute method
2024-07-05 06:52:12 +02:00
stefansielaff 98f2e68e0b "Swap order of sysStrSubstitutor and envStrSubstitutor in substitute method" 2024-07-02 13:24:57 +02:00
dependabot[bot] 40ab7a776a Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.2.5 to 3.3.0
Bumps [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire) from 3.2.5 to 3.3.0.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.2.5...surefire-3.3.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-failsafe-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-01 01:20:28 +00:00
Lukasz Lenart 8b22f7170f Merge pull request #966 from apache/dependabot/maven/org.codehaus.mojo-exec-maven-plugin-3.3.0
Bump org.codehaus.mojo:exec-maven-plugin from 3.2.0 to 3.3.0
2024-06-24 07:46:26 +02:00
Lukasz Lenart 688413a359 Merge pull request #965 from apache/dependabot/maven/org.apache.maven.plugins-maven-enforcer-plugin-3.5.0
Bump org.apache.maven.plugins:maven-enforcer-plugin from 3.4.1 to 3.5.0
2024-06-24 07:46:02 +02:00
Lukasz Lenart 53ed5f6dfa Merge pull request #960 from apache/dependabot/maven/org.apache.felix-org.apache.felix.main-7.0.5
Bump org.apache.felix:org.apache.felix.main from 6.0.3 to 7.0.5
2024-06-24 07:45:09 +02:00
Lukasz Lenart 100ef07a44 Merge pull request #958 from apache/dependabot/maven/commons-validator-commons-validator-1.9.0
Bump commons-validator:commons-validator from 1.8.0 to 1.9.0
2024-06-24 07:42:04 +02:00
Lukasz Lenart 4267bf0647 Merge pull request #971 from apache/feature/WW-5431-deprecated
WW-5431 Marks unused constants as deprecated
2024-06-24 07:40:13 +02:00
Lukasz Lenart 6cebeaca94 Merge pull request #970 from apache/feature/WW-5430-freemarker-jakarta
WW-5430 Uses Freemarker native support for JakartaEE instead of manually transforming the artifacts
2024-06-24 07:39:45 +02:00
Kusal Kithul-Godage 898a8d9ef9 Merge pull request #969 from apache/WW-5429-param-anno-log
WW-5429 Log parameter annotation issues at ERROR level when in DevMode
2024-06-21 19:47:23 +10:00
Lukasz Lenart 75ebbf4367 WW-5431 Marks unused constants as deprecated
To be removed in Struts 7
2024-06-21 08:24:54 +02:00
Lukasz Lenart a7145d695e WW-5430 Uses Freemarker native support for JakartaEE instead of manually transforming the artifacts 2024-06-21 08:13:07 +02:00
Lukasz Lenart a8954508c6 Merge pull request #968 from apache/fix/WW-5310-fragment
WW-5310 Fixes broken support for Fragments in <s:url/> tag
2024-06-21 07:28:17 +02:00
Kusal Kithul-Godage ba46c18f07 WW-5429 Make DebugUtils final and remove @author JavaDoc tag 2024-06-21 11:04:10 +10:00
Kusal Kithul-Godage b96cf2c072 WW-5429 Log parameter annotation issues at ERROR level when in DevMode 2024-06-18 19:36:51 +10:00
Lukasz Lenart 13916c8b84 WW-5310 Fixes broken support for Fragments in <s:url/> tag 2024-06-18 09:39:17 +02:00
dependabot[bot] a99162a1a4 Bump org.codehaus.mojo:exec-maven-plugin from 3.2.0 to 3.3.0
Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/3.2.0...3.3.0)

---
updated-dependencies:
- dependency-name: org.codehaus.mojo:exec-maven-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 01:28:53 +00:00
dependabot[bot] b07268d5bd Bump org.apache.maven.plugins:maven-enforcer-plugin from 3.4.1 to 3.5.0
Bumps [org.apache.maven.plugins:maven-enforcer-plugin](https://github.com/apache/maven-enforcer) from 3.4.1 to 3.5.0.
- [Release notes](https://github.com/apache/maven-enforcer/releases)
- [Commits](https://github.com/apache/maven-enforcer/compare/enforcer-3.4.1...enforcer-3.5.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-enforcer-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-17 01:28:48 +00:00
Lukasz Lenart 28a68676ec [maven-release-plugin] prepare for next development iteration 2024-06-12 07:45:22 +02:00
dependabot[bot] 54bf309f88 Bump org.apache.felix:org.apache.felix.main from 6.0.3 to 7.0.5
Bumps org.apache.felix:org.apache.felix.main from 6.0.3 to 7.0.5.

---
updated-dependencies:
- dependency-name: org.apache.felix:org.apache.felix.main
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 01:57:32 +00:00
dependabot[bot] 63fcf0f14f Bump commons-validator:commons-validator from 1.8.0 to 1.9.0
Bumps commons-validator:commons-validator from 1.8.0 to 1.9.0.

---
updated-dependencies:
- dependency-name: commons-validator:commons-validator
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 01:57:26 +00:00
86 changed files with 657 additions and 1273 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ jobs:
publish_results: true
- name: "Upload artifact"
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # 4.3.3
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # 4.3.4
with:
name: SARIF file
path: results.sarif
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
+2 -2
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
<name>Struts 2 Rest Showcase Webapp</name>
<description>Struts 2 Rest Showcase Example</description>
+2 -8
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-showcase</artifactId>
@@ -166,11 +166,6 @@
<configuration>
<outputDirectory>${project.build.directory}/extraclasspath</outputDirectory>
<artifactItems>
<artifactItem>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-freemarker-jakarta</artifactId>
<destFileName>struts2-freemarker-jakarta.jar</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-sitemesh2-jakarta</artifactId>
@@ -197,7 +192,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.2.5</version>
<version>3.3.0</version>
<configuration>
<includes>
<include>it.org.apache.struts2.showcase.*Test</include>
@@ -241,7 +236,6 @@
<webAppSourceDirectory>${basedir}/src/main/webapp/</webAppSourceDirectory>
<webApp>
<extraClasspath>
${project.build.directory}/extraclasspath/struts2-freemarker-jakarta.jar,
${project.build.directory}/extraclasspath/struts2-sitemesh2-jakarta.jar,
${project.build.directory}/extraclasspath/struts2-velocity-tools-view-jakarta.jar,
${project.build.directory}/extraclasspath/struts2-velocity-tools-jsp-jakarta
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-assembly</artifactId>
+4 -4
View File
@@ -25,11 +25,11 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-bom</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
<packaging>pom</packaging>
<name>Struts 2 Bill of Materials</name>
@@ -44,7 +44,7 @@
</licenses>
<properties>
<struts-version.version>7.0.0-M7</struts-version.version>
<struts-version.version>7.0.0-M8</struts-version.version>
<maven.site.skip>true</maven.site.skip>
<maven.site.deploy.skip>true</maven.site.deploy.skip>
</properties>
@@ -165,7 +165,7 @@
</dependencyManagement>
<scm>
<tag>STRUTS_7_0_0_M7</tag>
<tag>STRUTS_7_0_0_M8</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>
+3 -3
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-core</artifactId>
<packaging>jar</packaging>
@@ -136,8 +136,8 @@
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-freemarker-jakarta</artifactId>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
@@ -46,7 +46,7 @@ public class EnvsValueSubstitutor implements ValueSubstitutor {
public String substitute(String value) {
LOG.debug("Substituting value {} with proper System variable or environment variable", value);
String substituted = sysStrSubstitutor.replace(value);
return envStrSubstitutor.replace(substituted);
String substituted = envStrSubstitutor.replace(value);
return sysStrSubstitutor.replace(substituted);
}
}
@@ -82,14 +82,6 @@ public abstract class XmlConfigurationProvider extends XmlDocConfigurationProvid
this.configFileName = filename;
}
/**
* @deprecated since 6.2.0, use {@link #XmlConfigurationProvider(String)}
*/
@Deprecated
public XmlConfigurationProvider(String filename, @Deprecated boolean notUsed) {
this(filename);
}
@Override
public void init(Configuration configuration) {
super.init(configuration);
@@ -465,7 +465,7 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid
Location location = DomHelper.getLocationObject(actionElement);
if (!className.isEmpty()) {
verifyAction(className, name, location);
verifyAction(className, location);
}
Map<String, ResultConfig> results;
@@ -496,7 +496,7 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid
String methodName = trimToNull(actionElement.getAttribute("method"));
List<InterceptorMapping> interceptorList = buildInterceptorList(actionElement, packageContext);
List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(actionElement, packageContext);
List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(actionElement);
Set<String> allowedMethods = buildAllowedMethods(actionElement, packageContext);
return new ActionConfig.Builder(packageContext.getName(), actionName, className)
@@ -511,15 +511,6 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid
.build();
}
/**
* @deprecated since 6.2.0, use {@link #verifyAction(String, Location)}
*/
@Deprecated
protected boolean verifyAction(String className, String name, Location loc) {
verifyAction(className, loc);
return true;
}
protected void verifyAction(String className, Location loc) {
if (className.contains("{")) {
LOG.debug("Action class [{}] contains a wildcard replacement value, so it can't be verified", className);
@@ -785,14 +776,6 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid
return sb.toString();
}
/**
* @deprecated since 6.2.0, use {@link #buildExceptionMappings(Element)}
*/
@Deprecated
protected List<ExceptionMappingConfig> buildExceptionMappings(Element element, PackageConfig.Builder packageContext) {
return buildExceptionMappings(element);
}
/**
* Build a list of exception mapping objects from below a given XML element.
*
@@ -930,7 +913,7 @@ public abstract class XmlDocConfigurationProvider implements ConfigurationProvid
if (globalExceptionMappingList.getLength() > 0) {
Element globalExceptionMappingElement = (Element) globalExceptionMappingList.item(0);
List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(globalExceptionMappingElement, packageContext);
List<ExceptionMappingConfig> exceptionMappings = buildExceptionMappings(globalExceptionMappingElement);
packageContext.addGlobalExceptionMappingConfigs(exceptionMappings);
}
}
@@ -25,8 +25,6 @@ import java.util.Map;
/**
* ValidationAware classes can accept Action (class level) or field level error messages. Action level messages are kept
* in a Collection. Field level error messages are kept in a Map from String field name to a List of field error msgs.
*
* @author plightbo
*/
public interface ValidationAware {
@@ -119,7 +117,9 @@ public interface ValidationAware {
*
* @return <code>(hasActionErrors() || hasFieldErrors())</code>
*/
boolean hasErrors();
default boolean hasErrors() {
return hasActionErrors() || hasFieldErrors();
}
/**
* Check whether there are any field errors associated with this action.
@@ -30,13 +30,6 @@ import org.apache.struts2.StrutsConstants;
public class DefaultOgnlBeanInfoCacheFactory<Key, Value> extends DefaultOgnlCacheFactory<Key, Value>
implements BeanInfoCacheFactory<Key, Value> {
/**
* @deprecated since 6.4.0, use {@link #DefaultOgnlBeanInfoCacheFactory(String, String)}
*/
@Deprecated
public DefaultOgnlBeanInfoCacheFactory() {
}
@Inject
public DefaultOgnlBeanInfoCacheFactory(@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE) String cacheMaxSize,
@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_TYPE) String defaultCacheType) {
@@ -15,8 +15,6 @@
*/
package com.opensymphony.xwork2.ognl;
import org.apache.commons.lang3.BooleanUtils;
/**
* <p>Default OGNL Cache factory implementation.</p>
*
@@ -30,18 +28,10 @@ public class DefaultOgnlCacheFactory<Key, Value> implements OgnlCacheFactory<Key
private static final int DEFAULT_INIT_CAPACITY = 16;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private CacheType defaultCacheType;
private int cacheMaxSize;
private final CacheType defaultCacheType;
private final int cacheMaxSize;
private final int initialCapacity;
/**
* @deprecated since 6.4.0, use {@link #DefaultOgnlCacheFactory(int, CacheType)}
*/
@Deprecated
public DefaultOgnlCacheFactory() {
this(10000, CacheType.BASIC);
}
public DefaultOgnlCacheFactory(int cacheMaxSize, CacheType defaultCacheType) {
this(cacheMaxSize, defaultCacheType, DEFAULT_INIT_CAPACITY);
}
@@ -62,16 +52,11 @@ public class DefaultOgnlCacheFactory<Key, Value> implements OgnlCacheFactory<Key
int initialCapacity,
float loadFactor,
CacheType cacheType) {
switch (cacheType) {
case BASIC:
return new OgnlDefaultCache<>(evictionLimit, initialCapacity, loadFactor);
case LRU:
return new OgnlLRUCache<>(evictionLimit, initialCapacity, loadFactor);
case WTLFU:
return new OgnlCaffeineCache<>(evictionLimit, initialCapacity);
default:
throw new IllegalArgumentException("Unknown cache type: " + cacheType);
}
return switch (cacheType) {
case BASIC -> new OgnlDefaultCache<>(evictionLimit, initialCapacity, loadFactor);
case LRU -> new OgnlLRUCache<>(evictionLimit, initialCapacity, loadFactor);
case WTLFU -> new OgnlCaffeineCache<>(evictionLimit, initialCapacity);
};
}
@Override
@@ -79,28 +64,8 @@ public class DefaultOgnlCacheFactory<Key, Value> implements OgnlCacheFactory<Key
return cacheMaxSize;
}
/**
* @deprecated since 6.4.0
*/
@Deprecated
protected void setCacheMaxSize(String maxSize) {
cacheMaxSize = Integer.parseInt(maxSize);
}
@Override
public CacheType getDefaultCacheType() {
return defaultCacheType;
}
/**
* No effect when {@code useLRUMode} is {@code false}
*
* @deprecated since 6.4.0
*/
@Deprecated
protected void setUseLRUCache(String useLRUMode) {
if (BooleanUtils.toBoolean(useLRUMode)) {
defaultCacheType = CacheType.LRU;
}
}
}
@@ -30,13 +30,6 @@ import org.apache.struts2.StrutsConstants;
public class DefaultOgnlExpressionCacheFactory<Key, Value> extends DefaultOgnlCacheFactory<Key, Value>
implements ExpressionCacheFactory<Key, Value> {
/**
* @deprecated since 6.4.0, use {@link #DefaultOgnlExpressionCacheFactory(String, String)}
*/
@Deprecated
public DefaultOgnlExpressionCacheFactory() {
}
@Inject
public DefaultOgnlExpressionCacheFactory(@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE) String cacheMaxSize,
@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_TYPE) String defaultCacheType) {
@@ -33,7 +33,7 @@ public class ErrorMessageBuilder {
}
public ErrorMessageBuilder errorSettingExpressionWithValue(String expr, Object value) {
appenExpression(expr);
appendExpression(expr);
if (value instanceof Object[]) {
appendValueAsArray((Object[]) value, message);
} else {
@@ -42,7 +42,7 @@ public class ErrorMessageBuilder {
return this;
}
private void appenExpression(String expr) {
private void appendExpression(String expr) {
message.append("Error setting expression '");
message.append(expr);
message.append("' with value ");
@@ -25,22 +25,6 @@ package com.opensymphony.xwork2.ognl;
public interface OgnlCacheFactory<Key, Value> {
OgnlCache<Key, Value> buildOgnlCache();
/**
* Note that if {@code lruCache} is {@code false}, the cache type could still be LRU if the default cache type is
* configured as such.
* @deprecated since 6.4.0, use {@link #buildOgnlCache(int, int, float, CacheType)}
*/
@Deprecated
default OgnlCache<Key, Value> buildOgnlCache(int evictionLimit,
int initialCapacity,
float loadFactor,
boolean lruCache) {
return buildOgnlCache(evictionLimit,
initialCapacity,
loadFactor,
lruCache ? CacheType.LRU : getDefaultCacheType());
}
/**
* @param evictionLimit maximum capacity of the cache where applicable for cache type chosen
* @param initialCapacity initial capacity of the cache where applicable for cache type chosen
@@ -52,14 +36,6 @@ public interface OgnlCacheFactory<Key, Value> {
int getCacheMaxSize();
/**
* @deprecated since 6.4.0
*/
@Deprecated
default boolean getUseLRUCache() {
return CacheType.LRU.equals(getDefaultCacheType());
}
CacheType getDefaultCacheType();
enum CacheType {
@@ -36,7 +36,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.ognl.OgnlGuard;
import org.apache.struts2.ognl.StrutsOgnlGuard;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
@@ -46,14 +45,7 @@ import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import static com.opensymphony.xwork2.util.ConfigParseUtil.toClassesSet;
import static com.opensymphony.xwork2.util.ConfigParseUtil.toNewPatternsSet;
import static com.opensymphony.xwork2.util.ConfigParseUtil.toPackageNamesSet;
import static java.util.Collections.emptySet;
import static java.util.Objects.requireNonNull;
import static org.apache.struts2.ognl.OgnlGuard.EXPR_BLOCKED;
@@ -68,9 +60,6 @@ public class OgnlUtil {
private static final Logger LOG = LogManager.getLogger(OgnlUtil.class);
// Flag used to reduce flooding logs with WARNs about using DevMode excluded packages
private final AtomicBoolean warnReported = new AtomicBoolean(false);
private final OgnlCache<String, Object> expressionCache;
private final OgnlCache<Class<?>, BeanInfo> beanInfoCache;
private TypeConverter defaultConverter;
@@ -80,25 +69,8 @@ public class OgnlUtil {
private boolean enableExpressionCache = true;
private boolean enableEvalExpression;
private String devModeExcludedClasses = "";
private String devModeExcludedPackageNamePatterns = "";
private String devModeExcludedPackageNames = "";
private String devModeExcludedPackageExemptClasses = "";
private Container container;
/**
* Construct a new OgnlUtil instance for use with the framework
*
* @deprecated since 6.0.0. Use {@link #OgnlUtil(ExpressionCacheFactory, BeanInfoCacheFactory, OgnlGuard) instead.
*/
@Deprecated
public OgnlUtil() {
this(new DefaultOgnlExpressionCacheFactory<>(),
new DefaultOgnlBeanInfoCacheFactory<>(),
new StrutsOgnlGuard());
}
/**
* Construct a new OgnlUtil instance for use with the framework, with optional cache factories for OGNL Expression
* and BeanInfo caches.
@@ -156,119 +128,11 @@ public class OgnlUtil {
}
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected void setExcludedClasses(String commaDelimitedClasses) {
// Must be set directly on SecurityMemberAccess
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required = false)
protected void setDevModeExcludedClasses(String commaDelimitedClasses) {
this.devModeExcludedClasses = commaDelimitedClasses;
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected void setExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) {
// Must be set directly on SecurityMemberAccess
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false)
protected void setDevModeExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) {
this.devModeExcludedPackageNamePatterns = commaDelimitedPackagePatterns;
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected void setExcludedPackageNames(String commaDelimitedPackageNames) {
// Must be set directly on SecurityMemberAccess
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, required = false)
protected void setDevModeExcludedPackageNames(String commaDelimitedPackageNames) {
this.devModeExcludedPackageNames = commaDelimitedPackageNames;
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
public void setExcludedPackageExemptClasses(String commaDelimitedClasses) {
// Must be set directly on SecurityMemberAccess
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required = false)
public void setDevModeExcludedPackageExemptClasses(String commaDelimitedClasses) {
this.devModeExcludedPackageExemptClasses = commaDelimitedClasses;
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
public Set<String> getExcludedClasses() {
return toClassesSet(container.getInstance(String.class, StrutsConstants.STRUTS_EXCLUDED_CLASSES));
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
public Set<Pattern> getExcludedPackageNamePatterns() {
return toNewPatternsSet(emptySet(), container.getInstance(String.class, StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAME_PATTERNS));
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
public Set<String> getExcludedPackageNames() {
return toPackageNamesSet(container.getInstance(String.class, StrutsConstants.STRUTS_EXCLUDED_PACKAGE_NAMES));
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
public Set<String> getExcludedPackageExemptClasses() {
return toClassesSet(container.getInstance(String.class, StrutsConstants.STRUTS_EXCLUDED_PACKAGE_EXEMPT_CLASSES));
}
@Inject
protected void setContainer(Container container) {
this.container = container;
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected void setAllowStaticFieldAccess(String allowStaticFieldAccess) {
// Must be set directly on SecurityMemberAccess
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected void setDisallowProxyMemberAccess(String disallowProxyMemberAccess) {
// Must be set directly on SecurityMemberAccess
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected void setDisallowDefaultPackageAccess(String disallowDefaultPackageAccess) {
// Must be set directly on SecurityMemberAccess
}
/**
* @param maxLength Injects the Struts OGNL expression maximum length.
*/
@@ -288,22 +152,6 @@ public class OgnlUtil {
}
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
public boolean isDisallowProxyMemberAccess() {
return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_DISALLOW_PROXY_MEMBER_ACCESS));
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
public boolean isDisallowDefaultPackageAccess() {
return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_DISALLOW_DEFAULT_PACKAGE_ACCESS));
}
/**
* Convenience mechanism to clear the OGNL Runtime Cache via OgnlUtil. May be utilized
* by applications that generate many unique OGNL expressions over time.
@@ -856,6 +704,11 @@ public class OgnlUtil {
return createDefaultContext(root, null);
}
/**
* Note that the allowlist capability is not enforced by the {@link OgnlContext} returned by this method. Currently,
* this context is only leveraged by some public methods on {@link OgnlUtil} which are called by
* {@link OgnlReflectionProvider}.
*/
protected Map<String, Object> createDefaultContext(Object root, ClassResolver resolver) {
if (resolver == null) {
resolver = container.getInstance(RootAccessor.class);
@@ -867,17 +720,6 @@ public class OgnlUtil {
SecurityMemberAccess memberAccess = container.getInstance(SecurityMemberAccess.class);
memberAccess.useEnforceAllowlistEnabled(Boolean.FALSE.toString());
if (devMode) {
if (!warnReported.get()) {
warnReported.set(true);
LOG.warn("Working in devMode, using devMode excluded classes and packages!");
}
memberAccess.useExcludedClasses(devModeExcludedClasses);
memberAccess.useExcludedPackageNamePatterns(devModeExcludedPackageNamePatterns);
memberAccess.useExcludedPackageNames(devModeExcludedPackageNames);
memberAccess.useExcludedPackageExemptClasses(devModeExcludedPackageExemptClasses);
}
return Ognl.createDefaultContext(root, memberAccess, resolver, defaultConverter);
}
@@ -23,7 +23,6 @@ import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.ognl.accessor.RootAccessor;
import com.opensymphony.xwork2.util.ClearableValueStack;
import com.opensymphony.xwork2.util.CompoundRoot;
@@ -109,34 +108,6 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
this(vs, xworkConverter, accessor, null, securityMemberAccess);
}
/**
* @deprecated since 6.4.0, use {@link #OgnlValueStack(ValueStack, XWorkConverter, RootAccessor, TextProvider, SecurityMemberAccess)} instead.
*/
@Deprecated
protected OgnlValueStack(ValueStack vs,
XWorkConverter xworkConverter,
CompoundRootAccessor accessor,
TextProvider prov,
boolean allowStaticFieldAccess) {
this(vs, xworkConverter, accessor, prov, new SecurityMemberAccess(allowStaticFieldAccess));
}
/**
* @deprecated since 6.4.0, use {@link #OgnlValueStack(XWorkConverter, RootAccessor, TextProvider, SecurityMemberAccess)} instead.
*/
@Deprecated
protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticFieldAccess) {
this(xworkConverter, accessor, prov, new SecurityMemberAccess(allowStaticFieldAccess));
}
/**
* @deprecated since 6.4.0, use {@link #OgnlValueStack(ValueStack, XWorkConverter, RootAccessor, SecurityMemberAccess)} instead.
*/
@Deprecated
protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticFieldAccess) {
this(vs, xworkConverter, accessor, new SecurityMemberAccess(allowStaticFieldAccess));
}
@Inject
protected void setOgnlUtil(OgnlUtil ognlUtil) {
this.ognlUtil = ognlUtil;
@@ -155,14 +126,6 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
((OgnlContext) context).setKeepLastEvaluation(false);
}
/**
* @deprecated since 6.4.0, use {@link #setRoot(XWorkConverter, RootAccessor, CompoundRoot, SecurityMemberAccess)} instead.
*/
@Deprecated
protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, boolean allowStaticFieldAccess) {
setRoot(xworkConverter, accessor, compoundRoot, new SecurityMemberAccess(allowStaticFieldAccess));
}
@Inject(StrutsConstants.STRUTS_DEVMODE)
protected void setDevMode(String mode) {
this.devMode = BooleanUtils.toBoolean(mode);
@@ -535,12 +498,4 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
public void useExcludeProperties(Set<Pattern> excludeProperties) {
securityMemberAccess.useExcludeProperties(excludeProperties);
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected void setXWorkConverter(final XWorkConverter converter) {
// no-op
}
}
@@ -30,7 +30,6 @@ import com.opensymphony.xwork2.util.ValueStackFactory;
import ognl.MethodAccessor;
import ognl.OgnlRuntime;
import ognl.PropertyAccessor;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
@@ -159,12 +158,4 @@ public class OgnlValueStackFactory implements ValueStackFactory {
LOG.debug("Registered custom OGNL PropertyAccessor [{}] for class [{}]", propertyAccessor.getClass().getName(), cls.getName());
}
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated
protected boolean containerAllowsStaticFieldAccess() {
return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS));
}
}
@@ -51,6 +51,8 @@ import static java.text.MessageFormat.format;
import static java.util.Collections.emptySet;
import static java.util.Collections.singletonList;
import static java.util.Collections.unmodifiableSet;
import static org.apache.struts2.StrutsConstants.STRUTS_ALLOWLIST_CLASSES;
import static org.apache.struts2.StrutsConstants.STRUTS_ALLOWLIST_PACKAGE_NAMES;
/**
* Allows access decisions to be made on the basis of whether a member is static or not.
@@ -77,16 +79,28 @@ public class SecurityMemberAccess implements MemberAccess {
private final ProviderAllowlist providerAllowlist;
private final ThreadAllowlist threadAllowlist;
private boolean allowStaticFieldAccess = true;
private Set<Pattern> excludeProperties = emptySet();
private Set<Pattern> acceptProperties = emptySet();
private Set<String> excludedClasses = unmodifiableSet(new HashSet<>(singletonList(Object.class.getName())));
private Set<Pattern> excludedPackageNamePatterns = emptySet();
private Set<String> excludedPackageNames = emptySet();
private Set<String> excludedPackageExemptClasses = emptySet();
private volatile boolean isDevModeInit;
private boolean isDevMode;
private Set<String> devModeExcludedClasses = unmodifiableSet(new HashSet<>(singletonList(Object.class.getName())));
private Set<Pattern> devModeExcludedPackageNamePatterns = emptySet();
private Set<String> devModeExcludedPackageNames = emptySet();
private Set<String> devModeExcludedPackageExemptClasses = emptySet();
private boolean enforceAllowlistEnabled = false;
private Set<Class<?>> allowlistClasses = emptySet();
private Set<String> allowlistPackageNames = emptySet();
private boolean disallowProxyObjectAccess = false;
private boolean disallowProxyMemberAccess = false;
private boolean disallowDefaultPackageAccess = false;
@@ -209,12 +223,27 @@ public class SecurityMemberAccess implements MemberAccess {
* @return {@code true} if member access is allowed
*/
protected boolean checkAllowlist(Object target, Member member) {
Class<?> memberClass = member.getDeclaringClass();
if (!enforceAllowlistEnabled) {
return true;
}
if (!disallowProxyObjectAccess && target != null && ProxyUtil.isProxy(target)) {
// If `disallowProxyObjectAccess` is not set, allow resolving Hibernate entities to their underlying
// classes/members. This allows the allowlist capability to continue working and offer some level of
// protection in applications where the developer has accepted the risk of allowing OGNL access to Hibernate
// entities. This is preferred to having to disable the allowlist capability entirely.
Object newTarget = ProxyUtil.getHibernateProxyTarget(target);
if (newTarget != target) {
logAllowlistHibernateEntity(target, newTarget);
target = newTarget;
member = ProxyUtil.resolveTargetMember(member, newTarget);
}
}
Class<?> memberClass = member.getDeclaringClass();
if (!isClassAllowlisted(memberClass)) {
LOG.warn(format("Declaring class [{0}] of member type [{1}] is not allowlisted!", memberClass, member));
LOG.warn("Declaring class [{}] of member type [{}] is not allowlisted! Add to '{}' or '{}' configuration.",
memberClass, member, STRUTS_ALLOWLIST_CLASSES, STRUTS_ALLOWLIST_PACKAGE_NAMES);
return false;
}
if (target == null || target.getClass() == memberClass) {
@@ -222,12 +251,27 @@ public class SecurityMemberAccess implements MemberAccess {
}
Class<?> targetClass = target.getClass();
if (!isClassAllowlisted(targetClass)) {
LOG.warn(format("Target class [{0}] of target [{1}] is not allowlisted!", targetClass, target));
LOG.warn("Target class [{}] of target [{}] is not allowlisted! Add to '{}' or '{}' configuration.",
targetClass, target, STRUTS_ALLOWLIST_CLASSES, STRUTS_ALLOWLIST_PACKAGE_NAMES);
return false;
}
return true;
}
private void logAllowlistHibernateEntity(Object original, Object resolved) {
if (!isDevMode && !LOG.isDebugEnabled()) {
return;
}
String msg = "Hibernate entity [{}] resolved to [{}] for purpose of OGNL allowlisting." +
" We don't recommend executing OGNL expressions against Hibernate entities, you may disallow this behaviour using the configuration `{}=true`.";
Object[] args = {original, resolved, StrutsConstants.STRUTS_DISALLOW_PROXY_OBJECT_ACCESS};
if (isDevMode) {
LOG.warn(msg, args);
} else {
LOG.debug(msg, args);
}
}
protected boolean isClassAllowlisted(Class<?> clazz) {
return allowlistClasses.contains(clazz)
|| ALLOWLIST_REQUIRED_CLASSES.contains(clazz)
@@ -241,6 +285,7 @@ public class SecurityMemberAccess implements MemberAccess {
* @return {@code true} if member access is allowed
*/
protected boolean checkExclusionList(Object target, Member member) {
useDevModeConfiguration();
Class<?> memberClass = member.getDeclaringClass();
if (isClassExcluded(memberClass)) {
LOG.warn("Declaring class of member type [{}] is excluded!", memberClass);
@@ -436,12 +481,12 @@ public class SecurityMemberAccess implements MemberAccess {
this.enforceAllowlistEnabled = BooleanUtils.toBoolean(enforceAllowlistEnabled);
}
@Inject(value = StrutsConstants.STRUTS_ALLOWLIST_CLASSES, required = false)
@Inject(value = STRUTS_ALLOWLIST_CLASSES, required = false)
public void useAllowlistClasses(String commaDelimitedClasses) {
this.allowlistClasses = toClassObjectsSet(commaDelimitedClasses);
}
@Inject(value = StrutsConstants.STRUTS_ALLOWLIST_PACKAGE_NAMES, required = false)
@Inject(value = STRUTS_ALLOWLIST_PACKAGE_NAMES, required = false)
public void useAllowlistPackageNames(String commaDelimitedPackageNames) {
this.allowlistPackageNames = toPackageNamesSet(commaDelimitedPackageNames);
}
@@ -460,4 +505,41 @@ public class SecurityMemberAccess implements MemberAccess {
public void useDisallowDefaultPackageAccess(String disallowDefaultPackageAccess) {
this.disallowDefaultPackageAccess = BooleanUtils.toBoolean(disallowDefaultPackageAccess);
}
@Inject(StrutsConstants.STRUTS_DEVMODE)
protected void useDevMode(String devMode) {
this.isDevMode = BooleanUtils.toBoolean(devMode);
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required = false)
public void useDevModeExcludedClasses(String commaDelimitedClasses) {
this.devModeExcludedClasses = toNewClassesSet(devModeExcludedClasses, commaDelimitedClasses);
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false)
public void useDevModeExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) {
this.devModeExcludedPackageNamePatterns = toNewPatternsSet(devModeExcludedPackageNamePatterns, commaDelimitedPackagePatterns);
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, required = false)
public void useDevModeExcludedPackageNames(String commaDelimitedPackageNames) {
this.devModeExcludedPackageNames = toNewPackageNamesSet(devModeExcludedPackageNames, commaDelimitedPackageNames);
}
@Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required = false)
public void useDevModeExcludedPackageExemptClasses(String commaDelimitedClasses) {
this.devModeExcludedPackageExemptClasses = toClassesSet(commaDelimitedClasses);
}
private void useDevModeConfiguration() {
if (!isDevMode || isDevModeInit) {
return;
}
isDevModeInit = true;
LOG.warn("Working in devMode, using devMode excluded classes and packages!");
excludedClasses = devModeExcludedClasses;
excludedPackageNamePatterns = devModeExcludedPackageNamePatterns;
excludedPackageNames = devModeExcludedPackageNames;
excludedPackageExemptClasses = devModeExcludedPackageExemptClasses;
}
}
@@ -16,17 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.struts2.interceptor;
package com.opensymphony.xwork2.util;
import java.util.Map;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.logging.log4j.Logger;
@Deprecated
public interface ApplicationAware extends org.apache.struts2.action.ApplicationAware {
/**
* @since 6.5.0
*/
public final class DebugUtils {
void setApplication(Map<String, Object> application);
@Override
default void withApplication(Map<String, Object> application) {
setApplication(application);
public static void notifyDeveloperOfError(Logger log, Object action, String message) {
if (action instanceof TextProvider) {
TextProvider tp = (TextProvider) action;
message = tp.getText("devmode.notification", "Developer Notification:\n{0}", new String[]{message});
}
log.error(message);
if (action instanceof ValidationAware) {
ValidationAware validationAware = (ValidationAware) action;
validationAware.addActionError(message);
}
}
}
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.ognl.OgnlCacheFactory;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;
import java.lang.reflect.Constructor;
@@ -33,6 +34,8 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import static java.lang.reflect.Modifier.isPublic;
/**
* <code>ProxyUtil</code>
* <p>
@@ -255,4 +258,34 @@ public class ProxyUtil {
return false;
}
/**
* @return the target instance of the given object if it is a Hibernate proxy object, otherwise the given object
*/
public static Object getHibernateProxyTarget(Object object) {
try {
return Hibernate.unproxy(object);
} catch (NoClassDefFoundError ignored) {
return object;
}
}
/**
* @return matching member on target object if one exists, otherwise the same member
*/
public static Member resolveTargetMember(Member proxyMember, Object target) {
int mod = proxyMember.getModifiers();
if (proxyMember instanceof Method) {
if (isPublic(mod)) {
return MethodUtils.getMatchingAccessibleMethod(target.getClass(), proxyMember.getName(), ((Method) proxyMember).getParameterTypes());
} else {
return MethodUtils.getMatchingMethod(target.getClass(), proxyMember.getName(), ((Method) proxyMember).getParameterTypes());
}
} else if (proxyMember instanceof Field) {
return FieldUtils.getField(target.getClass(), proxyMember.getName(), isPublic(mod));
} else if (proxyMember instanceof Constructor && isPublic(mod)) {
return ConstructorUtils.getMatchingAccessibleConstructor(target.getClass(), ((Constructor<?>) proxyMember).getParameterTypes());
}
return proxyMember;
}
}
@@ -310,13 +310,6 @@ public final class StrutsConstants {
*/
public static final String STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE = "struts.ognl.beanInfoCacheMaxSize";
/**
* @since 6.0.0
* @deprecated since 6.4.0, use {@link StrutsConstants#STRUTS_OGNL_BEANINFO_CACHE_TYPE} instead.
*/
@Deprecated
public static final String STRUTS_OGNL_BEANINFO_CACHE_LRU_MODE = "struts.ognl.beanInfoCacheLRUMode";
/**
* Logs properties that are not found (very verbose)
* @since 6.0.0
@@ -372,13 +365,6 @@ public final class StrutsConstants {
*/
public static final String STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE = "struts.ognl.expressionCacheMaxSize";
/**
* @since 6.0.0
* @deprecated since 6.4.0, use {@link StrutsConstants#STRUTS_OGNL_EXPRESSION_CACHE_TYPE} instead.
*/
@Deprecated
public static final String STRUTS_OGNL_EXPRESSION_CACHE_LRU_MODE = "struts.ognl.expressionCacheLRUMode";
/**
* Enables evaluation of OGNL expressions
* @since 6.0.0
@@ -103,9 +103,9 @@ public class ServletUrlRenderer implements UrlRenderer {
}
result = urlHelper.buildUrl(_value, urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
}
String anchor = urlComponent.getAnchor();
if (StringUtils.isNotEmpty(anchor)) {
result += '#' + urlComponent.findString(anchor);
if (StringUtils.isNotEmpty(urlComponent.getAnchor())) {
String anchor = urlComponent.findString(urlComponent.getAnchor());
result += '#' + anchor;
}
if (urlComponent.isPutInContext()) {
@@ -292,7 +292,7 @@ public class ServletUrlRenderer implements UrlRenderer {
private void includeGetParameters(UrlProvider urlComponent) {
String query = extractQueryString(urlComponent);
QueryStringParser.Result result = queryStringParser.parse(query);
mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), result.getQueryParams());
result = mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), result.getQueryParams());
if (!result.getQueryFragment().isEmpty()) {
urlComponent.setAnchor(result.getQueryFragment());
}
@@ -331,10 +331,11 @@ public class ServletUrlRenderer implements UrlRenderer {
* @param value the value attribute (URL to be generated by this component)
* @param parameters component parameters
* @param contextParameters request parameters
* @return {@link QueryStringParser.Result} of value's ?query-string or empty()
*/
protected void mergeRequestParameters(String value, Map<String, Object> parameters, Map<String, ?> contextParameters) {
protected QueryStringParser.Result mergeRequestParameters(String value, Map<String, Object> parameters, Map<String, ?> contextParameters) {
Map<String, Object> mergedParams = new LinkedHashMap<>(contextParameters);
QueryStringParser.Result result = queryStringParser.empty();
// Merge contextParameters (from current request) with parameters specified in value attribute
// eg. value="someAction.action?id=someId&venue=someVenue"
@@ -343,7 +344,8 @@ public class ServletUrlRenderer implements UrlRenderer {
if (StringUtils.contains(value, "?")) {
String queryString = value.substring(value.indexOf('?') + 1);
mergedParams = new LinkedHashMap<>(queryStringParser.parse(queryString).getQueryParams());
result = queryStringParser.parse(queryString);
mergedParams = new LinkedHashMap<>(result.getQueryParams());
for (Map.Entry<String, ?> entry : contextParameters.entrySet()) {
if (!mergedParams.containsKey(entry.getKey())) {
mergedParams.put(entry.getKey(), entry.getValue());
@@ -362,6 +364,8 @@ public class ServletUrlRenderer implements UrlRenderer {
parameters.put(entry.getKey(), entry.getValue());
}
}
return result;
}
}
@@ -25,10 +25,10 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Context;
import com.opensymphony.xwork2.inject.Factory;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import jakarta.servlet.ServletContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import jakarta.servlet.ServletContext;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -105,14 +105,6 @@ public class StrutsXmlConfigurationProvider extends XmlConfigurationProvider {
}
}
/**
* @deprecated since 6.2.0, use {@link #StrutsXmlConfigurationProvider(String, ServletContext)}
*/
@Deprecated
public StrutsXmlConfigurationProvider(String filename, @Deprecated boolean errorIfMissing, ServletContext ctx) {
this(filename, ctx);
}
/* (non-Javadoc)
* @see com.opensymphony.xwork2.config.providers.XmlConfigurationProvider#register(com.opensymphony.xwork2.inject.ContainerBuilder, java.util.Properties)
*/
@@ -48,6 +48,10 @@ import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.util.location.Location;
import com.opensymphony.xwork2.util.location.LocationUtils;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
@@ -72,10 +76,6 @@ import org.apache.struts2.ognl.ThreadAllowlist;
import org.apache.struts2.util.ObjectFactoryDestroyable;
import org.apache.struts2.util.fs.JBossFileManager;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
@@ -331,14 +331,6 @@ public class Dispatcher {
multipartSaveDir = val;
}
/**
* @deprecated since 6.4.0, no replacement.
*/
@Deprecated(since = "6.4.0", forRemoval = true)
public void setMultipartHandler(String val) {
// no-op
}
@Inject(value = StrutsConstants.STRUTS_MULTIPART_ENABLED, required = false)
public void setMultipartSupportEnabled(String multipartSupportEnabled) {
this.multipartSupportEnabled = Boolean.parseBoolean(multipartSupportEnabled);
@@ -551,14 +543,6 @@ public class Dispatcher {
return new StrutsXmlConfigurationProvider(filename, ctx);
}
/**
* @deprecated since 6.2.0, use {@link #createStrutsXmlConfigurationProvider(String, ServletContext)}
*/
@Deprecated
protected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) {
return createStrutsXmlConfigurationProvider(filename, ctx);
}
private void init_JavaConfigurations() {
String configClasses = initParams.get("javaConfigClasses");
if (configClasses != null) {
@@ -22,9 +22,7 @@ import com.opensymphony.xwork2.ActionContext;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Contains initialization operations
@@ -90,18 +88,4 @@ public class InitOperations {
public void cleanup() {
ActionContext.clear();
}
/**
* Extract a list of patterns to exclude from request filtering
*
* @param dispatcher The dispatcher to check for exclude pattern configuration
* @return a List of Patterns for request to exclude if apply, or <tt>null</tt>
* @see org.apache.struts2.StrutsConstants#STRUTS_ACTION_EXCLUDE_PATTERN
* @deprecated since 6.4.0, use {@link Dispatcher#getActionExcludedPatterns()} instead.
*/
@Deprecated
public List<Pattern> buildExcludedPatternsList(Dispatcher dispatcher) {
return dispatcher.getActionExcludedPatterns();
}
}
@@ -20,6 +20,9 @@ package org.apache.struts2.dispatcher;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.RequestUtils;
@@ -27,13 +30,8 @@ import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsException;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
/**
* Contains preparation operations for a request before execution
@@ -230,18 +228,6 @@ public class PrepareOperations {
return dispatcher.getActionExcludedPatterns().stream().anyMatch(pattern -> pattern.matcher(uri).matches());
}
/**
* @deprecated since 6.4.0, use {@link #isUrlExcluded(HttpServletRequest)} instead.
*/
@Deprecated
public boolean isUrlExcluded(HttpServletRequest request, List<Pattern> excludedPatterns) {
if (excludedPatterns == null) {
return false;
}
String uri = RequestUtils.getUri(request);
return excludedPatterns.stream().anyMatch(pattern -> pattern.matcher(uri).matches());
}
/**
* Set an override of the static devMode value. Do not set this via a
* request parameter or any other unprotected method. Using a signed
@@ -18,6 +18,14 @@
*/
package org.apache.struts2.dispatcher.filter;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.RequestUtils;
@@ -28,17 +36,7 @@ import org.apache.struts2.dispatcher.InitOperations;
import org.apache.struts2.dispatcher.PrepareOperations;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;
/**
* Handles both the preparation and execution phases of the Struts dispatching process. This filter is better to use
@@ -51,13 +49,6 @@ public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
protected PrepareOperations prepare;
protected ExecuteOperations execute;
/**
* @deprecated since 6.4.0, use {@link Dispatcher#getActionExcludedPatterns} or
* {@link PrepareOperations#isUrlExcluded(HttpServletRequest)} instead.
*/
@Deprecated
protected List<Pattern> excludedPatterns;
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = createInitOperations();
Dispatcher dispatcher = null;
@@ -69,8 +60,6 @@ public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
prepare = createPrepareOperations(dispatcher);
execute = createExecuteOperations(dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
@@ -18,11 +18,6 @@
*/
package org.apache.struts2.dispatcher.filter;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.InitOperations;
import org.apache.struts2.dispatcher.PrepareOperations;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
@@ -31,9 +26,12 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.InitOperations;
import org.apache.struts2.dispatcher.PrepareOperations;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;
/**
* Prepares the request for execution by a later {@link org.apache.struts2.dispatcher.filter.StrutsExecuteFilter} filter instance.
@@ -44,13 +42,6 @@ public class StrutsPrepareFilter implements StrutsStatics, Filter {
protected PrepareOperations prepare;
/**
* @deprecated since 6.4.0, use {@link Dispatcher#getActionExcludedPatterns} or
* {@link PrepareOperations#isUrlExcluded(HttpServletRequest)} instead.
*/
@Deprecated
protected List<Pattern> excludedPatterns;
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = createInitOperations();
Dispatcher dispatcher = null;
@@ -60,8 +51,6 @@ public class StrutsPrepareFilter implements StrutsStatics, Filter {
prepare = createPrepareOperations(dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
postInit(dispatcher, filterConfig);
} finally {
if (dispatcher != null) {
@@ -55,7 +55,7 @@ import java.util.Map;
* <p>
* The best way to add behavior to this interceptor is to utilize the {@link ParameterNameAware} interface in your
* actions. However, if you wish to apply a global rule that isn't implemented in your action, then you could extend
* this interceptor and override the {@link #acceptableName(String)} method.
* this interceptor and override the {@link #isAcceptableName(String)} method.
* </p>
*
* <!-- END SNIPPET: extending -->
@@ -26,11 +26,12 @@ import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import jakarta.servlet.http.Cookie;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.action.CookiesAware;
import jakarta.servlet.http.Cookie;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -357,7 +358,7 @@ public class CookieInterceptor extends AbstractInterceptor {
protected void injectIntoCookiesAwareAction(Object action, Map<String, String> cookiesMap) {
if (action instanceof CookiesAware) {
LOG.debug("Action [{}] implements CookiesAware, injecting cookies map [{}]", action, cookiesMap);
((CookiesAware)action).setCookiesMap(cookiesMap);
((CookiesAware)action).withCookies(cookiesMap);
}
if (action instanceof org.apache.struts2.action.CookiesAware) {
LOG.debug("Action [{}] implements CookiesAware, injecting cookies map [{}]", action, cookiesMap);
@@ -1,40 +0,0 @@
/*
* 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.interceptor;
import java.util.Map;
/**
* Actions implementing the CookiesAware interface will receive
* a Map of filtered cookies via the setCookiesMap method.
*
* Please note that the {@link CookieInterceptor} needs to be
* activated to receive a cookies map.
*
* @deprecated please use {@link org.apache.struts2.action.CookiesAware} instead
*/
@Deprecated
public interface CookiesAware {
/**
* Sets a map of filtered cookies.
* @param cookies the cookies
* @deprecated please use {@link org.apache.struts2.action.CookiesAware#withCookies(Map)} instead
*/
void setCookiesMap(Map<String, String> cookies);
}
@@ -1,32 +0,0 @@
/*
* 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.interceptor;
import org.apache.struts2.dispatcher.HttpParameters;
@Deprecated
public interface HttpParametersAware extends org.apache.struts2.action.ParametersAware {
void setParameters(HttpParameters parameters);
@Override
default void withParameters(HttpParameters parameters) {
setParameters(parameters);
}
}
@@ -1,36 +0,0 @@
/*
* 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.interceptor;
import org.apache.struts2.dispatcher.HttpParameters;
import java.util.Map;
import static java.util.stream.Collectors.toMap;
@Deprecated
public interface ParameterAware extends org.apache.struts2.action.ParametersAware {
void setParameters(Map<String, String[]> map);
@Override
default void withParameters(HttpParameters parameters) {
setParameters(parameters.entrySet().stream().collect(toMap(Map.Entry::getKey, e -> e.getValue().getMultipleValues())));
}
}
@@ -1,30 +0,0 @@
/*
* 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.interceptor;
@Deprecated
public interface PrincipalAware extends org.apache.struts2.action.PrincipalAware {
void setPrincipalProxy(PrincipalProxy principalProxy);
@Override
default void withPrincipalProxy(PrincipalProxy principalProxy) {
setPrincipalProxy(principalProxy);
}
}
@@ -1,41 +0,0 @@
/*
* 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.interceptor;
import org.apache.struts2.dispatcher.RequestMap;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;
@Deprecated
public interface RequestAware extends ServletRequestAware {
@Override
default void setServletRequest(HttpServletRequest httpServletRequest) {
// default no-op
}
@Override
default void withServletRequest(HttpServletRequest request) {
ServletRequestAware.super.withServletRequest(request);
setRequest(new RequestMap(request));
}
void setRequest(Map<String, Object> request);
}
@@ -18,10 +18,12 @@
*/
package org.apache.struts2.interceptor;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.action.ApplicationAware;
import org.apache.struts2.action.ParametersAware;
@@ -32,15 +34,11 @@ import org.apache.struts2.action.ServletResponseAware;
import org.apache.struts2.action.SessionAware;
import org.apache.struts2.interceptor.servlet.ServletPrincipalProxy;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
* <!-- START SNIPPET: description -->
* <p>
* An interceptor which sets action properties based on the interfaces an action implements. For example, if the action
* implements {@link ParameterAware} then the action context's parameter map will be set on it.
* implements {@link ParametersAware} then the action context's parameter map will be set on it.
* </p>
*
* <p>This interceptor is designed to set all properties an action needs if it's aware of servlet parameters, the
@@ -1,32 +0,0 @@
/*
* 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.interceptor;
import jakarta.servlet.http.HttpServletRequest;
@Deprecated
public interface ServletRequestAware extends org.apache.struts2.action.ServletRequestAware {
void setServletRequest(HttpServletRequest httpServletRequest);
@Override
default void withServletRequest(HttpServletRequest request) {
setServletRequest(request);
}
}
@@ -1,32 +0,0 @@
/*
* 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.interceptor;
import jakarta.servlet.http.HttpServletResponse;
@Deprecated
public interface ServletResponseAware extends org.apache.struts2.action.ServletResponseAware {
void setServletResponse(HttpServletResponse httpServletResponse);
@Override
default void withServletResponse(HttpServletResponse response) {
setServletResponse(response);
}
}
@@ -1,32 +0,0 @@
/*
* 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.interceptor;
import java.util.Map;
@Deprecated
public interface SessionAware extends org.apache.struts2.action.SessionAware {
void setSession(Map<String, Object> session);
@Override
default void withSession(Map<String, Object> session) {
setSession(session);
}
}
@@ -20,10 +20,8 @@ package org.apache.struts2.interceptor.parameter;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
@@ -56,7 +54,6 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
@@ -67,6 +64,8 @@ import java.util.regex.Pattern;
import static com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker.NESTING_CHARS;
import static com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker.NESTING_CHARS_STR;
import static com.opensymphony.xwork2.util.DebugUtils.notifyDeveloperOfError;
import static java.lang.String.format;
import static java.util.Collections.unmodifiableSet;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.lang3.StringUtils.indexOfAny;
@@ -196,7 +195,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
Map<String, Object> contextMap = actionContext.getContextMap();
batchApplyReflectionContextState(contextMap, true);
try {
setParameters(action, actionContext.getValueStack(), parameters);
applyParameters(action, actionContext.getValueStack(), parameters);
} finally {
batchApplyReflectionContextState(contextMap, false);
}
@@ -227,14 +226,6 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
protected void addParametersToContext(ActionContext ac, Map<String, ?> newParams) {
}
/**
* @deprecated since 6.4.0, use {@link #applyParameters}
*/
@Deprecated
protected void setParameters(final Object action, ValueStack stack, HttpParameters parameters) {
applyParameters(action, stack, parameters);
}
protected void applyParameters(final Object action, ValueStack stack, HttpParameters parameters) {
Map<String, Parameter> acceptableParameters = toAcceptableParameters(parameters, action);
@@ -317,19 +308,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
}
protected void notifyDeveloperParameterException(Object action, String property, String message) {
String logMsg = "Unexpected Exception caught setting '" + property + "' on '" + action.getClass() + ": " + message;
if (action instanceof TextProvider) {
TextProvider tp = (TextProvider) action;
logMsg = tp.getText("devmode.notification", "Developer Notification:\n{0}", new String[]{logMsg});
}
LOG.error(logMsg);
if (action instanceof ValidationAware) {
ValidationAware validationAware = (ValidationAware) action;
Collection<String> messages = validationAware.getActionMessages();
messages.add(message);
validationAware.setActionMessages(messages);
}
String logMsg = format("Unexpected Exception caught setting '%s' on '%s: %s", property, action.getClass(), message);
notifyDeveloperOfError(LOG, action, logMsg);
}
/**
@@ -340,7 +320,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
* @return true if parameter is accepted
*/
protected boolean isAcceptableParameter(String name, Object action) {
return acceptableName(name) && isAcceptableParameterNameAware(name, action) && isParameterAnnotatedAndAllowlist(name, action);
return isAcceptableName(name) && isAcceptableParameterNameAware(name, action) && isParameterAnnotatedAndAllowlist(name, action);
}
protected boolean isAcceptableParameterNameAware(String name, Object action) {
@@ -388,23 +368,37 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return hasValidAnnotatedField(action, rootProperty, paramDepth);
}
if (hasValidAnnotatedPropertyDescriptor(propDescOpt.get(), paramDepth)) {
if (hasValidAnnotatedPropertyDescriptor(action, propDescOpt.get(), paramDepth)) {
return true;
}
return hasValidAnnotatedField(action, rootProperty, paramDepth);
}
/**
* @deprecated since 6.5.0, use {@link #hasValidAnnotatedPropertyDescriptor(Object, PropertyDescriptor, long)}
* instead.
*/
@Deprecated
protected boolean hasValidAnnotatedPropertyDescriptor(PropertyDescriptor propDesc, long paramDepth) {
return hasValidAnnotatedPropertyDescriptor(null, propDesc, paramDepth);
}
protected boolean hasValidAnnotatedPropertyDescriptor(Object action, PropertyDescriptor propDesc, long paramDepth) {
Method relevantMethod = paramDepth == 0 ? propDesc.getWriteMethod() : propDesc.getReadMethod();
if (relevantMethod == null) {
return false;
}
if (getPermittedInjectionDepth(relevantMethod) < paramDepth) {
LOG.debug(
"Parameter injection for method [{}] on action [{}] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.",
String logMessage = format(
"Parameter injection for method [%s] on action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.",
relevantMethod.getName(),
relevantMethod.getDeclaringClass().getName());
if (devMode) {
notifyDeveloperOfError(LOG, action, logMessage);
} else {
LOG.debug(logMessage);
}
return false;
}
if (paramDepth >= 1) {
@@ -455,10 +449,15 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return false;
}
if (getPermittedInjectionDepth(field) < paramDepth) {
LOG.debug(
"Parameter injection for field [{}] on action [{}] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.",
String logMessage = format(
"Parameter injection for field [%s] on action [%s] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.",
fieldName,
action.getClass().getName());
if (devMode) {
notifyDeveloperOfError(LOG, action, logMessage);
} else {
LOG.debug(logMessage);
}
return false;
}
if (paramDepth >= 1) {
@@ -510,7 +509,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
* @return true if parameter is accepted
*/
protected boolean isAcceptableParameterValue(Parameter param, Object action) {
return isAcceptableParameterValueAware(param, action) && acceptableValue(param.getName(), param.getValue());
return isAcceptableParameterValueAware(param, action) && isAcceptableValue(param.getName(), param.getValue());
}
protected boolean isAcceptableParameterValueAware(Parameter param, Object action) {
@@ -533,17 +532,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return "NONE";
}
return parameters.entrySet().stream()
.map(entry -> String.format("%s => %s ", entry.getKey(), entry.getValue().getValue()))
.map(entry -> format("%s => %s ", entry.getKey(), entry.getValue().getValue()))
.collect(joining());
}
/**
* @deprecated since 6.4.0, use {@link #isAcceptableName}
*/
protected boolean acceptableName(String name) {
return isAcceptableName(name);
}
/**
* Validates the name passed is:
* * Within the max length of a parameter name
@@ -572,13 +564,6 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return DMI_IGNORED_PATTERN.matcher(name).matches();
}
/**
* @deprecated since 6.4.0, use {@link #isAcceptableValue}
*/
protected boolean acceptableValue(String name, String value) {
return isAcceptableValue(name, value);
}
/**
* Validates:
* * Value is null/blank
@@ -28,14 +28,14 @@ import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.ext.jakarta.servlet.WebappTemplateLoader;
import freemarker.core.HTMLOutputFormat;
import freemarker.core.TemplateClassResolver;
import freemarker.ext.jsp.TaglibFactory;
import freemarker.ext.servlet.HttpRequestHashModel;
import freemarker.ext.servlet.HttpRequestParametersHashModel;
import freemarker.ext.servlet.HttpSessionHashModel;
import freemarker.ext.servlet.ServletContextHashModel;
import freemarker.ext.jakarta.jsp.TaglibFactory;
import freemarker.ext.jakarta.servlet.HttpRequestHashModel;
import freemarker.ext.jakarta.servlet.HttpRequestParametersHashModel;
import freemarker.ext.jakarta.servlet.HttpSessionHashModel;
import freemarker.ext.jakarta.servlet.ServletContextHashModel;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateException;
@@ -118,9 +118,6 @@ public class FreemarkerManager {
public static final String INITPARAM_DEBUG = "Debug";
public static final String KEY_REQUEST = "Request";
public static final String KEY_INCLUDE = "include_page";
public static final String KEY_REQUEST_PRIVATE = "__FreeMarkerServlet.Request__";
public static final String KEY_REQUEST_PARAMETERS = "RequestParameters";
public static final String KEY_SESSION = "Session";
public static final String KEY_APPLICATION = "Application";
public static final String KEY_APPLICATION_PRIVATE = "__FreeMarkerServlet.Application__";
@@ -138,10 +135,29 @@ public class FreemarkerManager {
// for Struts
public static final String KEY_REQUEST_PARAMETERS_STRUTS = "Parameters";
public static final String KEY_HASHMODEL_PRIVATE = "__FreeMarkerManager.Request__";
public static final String EXPIRATION_DATE;
/**
* @deprecated since Struts 6.5.0, do not use as it will be removed in Struts 7.0.0
*/
@Deprecated
public static final String KEY_INCLUDE = "include_page";
/**
* @deprecated since Struts 6.5.0, do not use as it will be removed in Struts 7.0.0
*/
@Deprecated
public static final String KEY_REQUEST_PRIVATE = "__FreeMarkerServlet.Request__";
/**
* @deprecated since Struts 6.5.0, do not use as it will be removed in Struts 7.0.0
*/
@Deprecated
public static final String KEY_REQUEST_PARAMETERS = "RequestParameters";
/**
* @deprecated since Struts 6.5.0, do not use as it will be removed in Struts 7.0.0
*/
@Deprecated
public static final String KEY_HASHMODEL_PRIVATE = "__FreeMarkerManager.Request__";
/**
* Adds individual settings.
*
@@ -26,14 +26,10 @@ import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.mock.MockActionProxy;
import com.opensymphony.xwork2.mock.MockInterceptor;
import com.opensymphony.xwork2.mock.MockResult;
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import org.apache.struts2.config.StrutsXmlConfigurationProvider;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.ognl.StrutsOgnlGuard;
import java.util.ArrayList;
import java.util.HashMap;
@@ -42,6 +38,8 @@ import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import static com.opensymphony.xwork2.ognl.OgnlUtilTest.createOgnlUtil;
/**
* A partial test of DefaultActionInvocation.
@@ -531,14 +529,6 @@ public class DefaultActionInvocationTest extends XWorkTestCase {
loadConfigurationProviders(configurationProvider);
}
private OgnlUtil createOgnlUtil() {
return new OgnlUtil(
new DefaultOgnlExpressionCacheFactory<>(),
new DefaultOgnlBeanInfoCacheFactory<>(),
new StrutsOgnlGuard()
);
}
private static class SimpleActionEventListener implements ActionEventListener {
private final String name;
@@ -63,6 +63,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import static com.opensymphony.xwork2.ognl.OgnlCacheFactory.CacheType.BASIC;
import static com.opensymphony.xwork2.ognl.OgnlCacheFactory.CacheType.LRU;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertThrows;
@@ -80,6 +82,11 @@ public class OgnlUtilTest extends XWorkTestCase {
ognlUtil = container.getInstance(OgnlUtil.class);
}
private void resetOgnlUtil(Map<String, ?> properties) {
loadButSet(properties);
ognlUtil = container.getInstance(OgnlUtil.class);
}
public void testCanSetADependentObject() {
String dogName = "fido";
@@ -1152,8 +1159,8 @@ public class OgnlUtilTest extends XWorkTestCase {
Exception expected = null;
try {
ognlUtil.setExcludedClasses(Object.class.getName());
ognlUtil.setValue("class.classLoader.defaultAssertionStatus", ognlUtil.createDefaultContext(foo), foo, true);
// Object.class is excluded by default
ognlUtil.setValue("class.classLoader", ognlUtil.createDefaultContext(foo), foo, true);
fail();
} catch (OgnlException e) {
expected = e;
@@ -1166,9 +1173,11 @@ public class OgnlUtilTest extends XWorkTestCase {
public void testAllowCallingMethodsOnObjectClassInDevModeTrue() {
Exception expected = null;
try {
ognlUtil.setExcludedClasses(Foo.class.getName());
ognlUtil.setDevModeExcludedClasses("");
ognlUtil.setDevMode(Boolean.TRUE.toString());
Map<String, String> properties = new HashMap<>();
properties.put(StrutsConstants.STRUTS_EXCLUDED_CLASSES, Foo.class.getName());
properties.put(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, "");
properties.put(StrutsConstants.STRUTS_DEVMODE, Boolean.TRUE.toString());
resetOgnlUtil(properties);
Foo foo = new Foo();
String result = (String) ognlUtil.getValue("toString", ognlUtil.createDefaultContext(foo), foo, String.class);
@@ -1180,14 +1189,18 @@ public class OgnlUtilTest extends XWorkTestCase {
}
public void testExclusionListDevModeOnOff() throws Exception {
ognlUtil.setDevModeExcludedClasses(Foo.class.getName());
Foo foo = new Foo();
ognlUtil.setDevMode(Boolean.TRUE.toString());
Map<String, String> properties = new HashMap<>();
properties.put(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, Foo.class.getName());
properties.put(StrutsConstants.STRUTS_DEVMODE, Boolean.TRUE.toString());
resetOgnlUtil(properties);
OgnlException e = assertThrows(OgnlException.class, () -> ognlUtil.getValue("toString", ognlUtil.createDefaultContext(foo), foo, String.class));
assertThat(e).hasMessageContaining("com.opensymphony.xwork2.util.Foo.toString");
ognlUtil.setDevMode(Boolean.FALSE.toString());
properties.put(StrutsConstants.STRUTS_DEVMODE, Boolean.FALSE.toString());
resetOgnlUtil(properties);
assertEquals("Foo", (String) ognlUtil.getValue("toString", ognlUtil.createDefaultContext(foo), foo, String.class));
}
@@ -1196,7 +1209,7 @@ public class OgnlUtilTest extends XWorkTestCase {
Exception expected = null;
try {
ognlUtil.setExcludedClasses(Object.class.getName());
// Object.class is excluded by default
ognlUtil.setValue("Class.ClassLoader.DefaultAssertionStatus", ognlUtil.createDefaultContext(foo), foo, true);
fail();
} catch (OgnlException e) {
@@ -1212,7 +1225,7 @@ public class OgnlUtilTest extends XWorkTestCase {
Exception expected = null;
try {
ognlUtil.setExcludedClasses(Object.class.getName());
// Object.class is excluded by default
ognlUtil.setValue("class['classLoader']['defaultAssertionStatus']", ognlUtil.createDefaultContext(foo), foo, true);
fail();
} catch (OgnlException e) {
@@ -1243,7 +1256,7 @@ public class OgnlUtilTest extends XWorkTestCase {
Exception expected = null;
try {
ognlUtil.setExcludedClasses(Object.class.getName());
// Object.class is excluded by default
ognlUtil.setValue("class[\"classLoader\"]['defaultAssertionStatus']", ognlUtil.createDefaultContext(foo), foo, true);
fail();
} catch (OgnlException e) {
@@ -1284,12 +1297,11 @@ public class OgnlUtilTest extends XWorkTestCase {
assertEquals(expected.getMessage(), "Inappropriate OGNL expression: toString()");
}
public void testAvoidCallingSomeClasses() {
public void testStaticMethodBlocked() {
Foo foo = new Foo();
Exception expected = null;
try {
ognlUtil.setExcludedClasses(Runtime.class.getName());
ognlUtil.setValue("@java.lang.Runtime@getRuntime().exec('mate')", ognlUtil.createDefaultContext(foo), foo, true);
fail();
} catch (OgnlException e) {
@@ -1333,13 +1345,13 @@ public class OgnlUtilTest extends XWorkTestCase {
public void testDefaultOgnlUtilAlternateConstructorArguments() {
// Code coverage test for the OgnlUtil alternate constructor method, and verify expected behaviour.
try {
OgnlUtil basicOgnlUtil = new OgnlUtil(new DefaultOgnlExpressionCacheFactory<>(), null, null);
new OgnlUtil(createDefaultOgnlExpressionCacheFactory(), null, null);
fail("null beanInfoCacheFactory should result in exception");
} catch (NullPointerException iaex) {
// expected result
}
try {
OgnlUtil basicOgnlUtil = new OgnlUtil(null, new DefaultOgnlBeanInfoCacheFactory<>(), null);
new OgnlUtil(null, createDefaultOgnlBeanInfoCacheFactory(), null);
fail("null expressionCacheFactory should result in exception");
} catch (NullPointerException iaex) {
// expected result
@@ -1604,23 +1616,24 @@ public class OgnlUtilTest extends XWorkTestCase {
*/
public void testOgnlDefaultCacheFactoryCoverage() {
OgnlCache<String, Object> ognlCache;
DefaultOgnlCacheFactory defaultOgnlCacheFactory = new DefaultOgnlCacheFactory<String, Object>();
// Normal cache
defaultOgnlCacheFactory.setCacheMaxSize("12");
defaultOgnlCacheFactory.setUseLRUCache("false");
DefaultOgnlCacheFactory<String, Object> defaultOgnlCacheFactory = new DefaultOgnlCacheFactory<>(12, BASIC);
ognlCache = defaultOgnlCacheFactory.buildOgnlCache();
assertNotNull("No param build method result null ?", ognlCache);
assertEquals("Eviction limit for cache mismatches limit for factory ?", 12, ognlCache.getEvictionLimit());
ognlCache = defaultOgnlCacheFactory.buildOgnlCache(6, 6, 0.75f, false);
ognlCache = defaultOgnlCacheFactory.buildOgnlCache(6, 6, 0.75f, BASIC);
assertNotNull("No param build method result null ?", ognlCache);
assertEquals("Eviction limit for cache mismatches limit for factory ?", 6, ognlCache.getEvictionLimit());
// LRU cache
defaultOgnlCacheFactory.setCacheMaxSize("30");
defaultOgnlCacheFactory.setUseLRUCache("true");
defaultOgnlCacheFactory = new DefaultOgnlCacheFactory<>(30, LRU);
ognlCache = defaultOgnlCacheFactory.buildOgnlCache();
assertNotNull("No param build method result null ?", ognlCache);
assertEquals("Eviction limit for cache mismatches limit for factory ?", 30, ognlCache.getEvictionLimit());
ognlCache = defaultOgnlCacheFactory.buildOgnlCache(15, 15, 0.75f, true);
ognlCache = defaultOgnlCacheFactory.buildOgnlCache(15, 15, 0.75f, LRU);
assertNotNull("No param build method result null ?", ognlCache);
assertEquals("Eviction limit for cache mismatches limit for factory ?", 15, ognlCache.getEvictionLimit());
}
@@ -1643,12 +1656,8 @@ public class OgnlUtilTest extends XWorkTestCase {
*/
private OgnlUtil generateOgnlUtilInstanceWithDefaultLRUCacheFactories() {
final OgnlUtil result;
final DefaultOgnlExpressionCacheFactory<String, Object> expressionFactory = new DefaultOgnlExpressionCacheFactory<>();
final DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo> beanInfoFactory = new DefaultOgnlBeanInfoCacheFactory<>();
expressionFactory.setUseLRUCache("true");
expressionFactory.setCacheMaxSize("25");
beanInfoFactory.setUseLRUCache("true");
beanInfoFactory.setCacheMaxSize("25");
final DefaultOgnlExpressionCacheFactory<String, Object> expressionFactory = new DefaultOgnlExpressionCacheFactory<>(String.valueOf(25), LRU.toString());
final DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo> beanInfoFactory = new DefaultOgnlBeanInfoCacheFactory<>(String.valueOf(25), LRU.toString());
result = new OgnlUtil(expressionFactory, beanInfoFactory, new StrutsOgnlGuard());
return result;
}
@@ -1796,4 +1805,19 @@ public class OgnlUtilTest extends XWorkTestCase {
}
}
public static OgnlUtil createOgnlUtil() {
return new OgnlUtil(
createDefaultOgnlExpressionCacheFactory(),
createDefaultOgnlBeanInfoCacheFactory(),
new StrutsOgnlGuard()
);
}
public static <K, V> DefaultOgnlExpressionCacheFactory<K, V> createDefaultOgnlExpressionCacheFactory() {
return new DefaultOgnlExpressionCacheFactory<>(String.valueOf(10_000), BASIC.toString());
}
public static <K, V> DefaultOgnlBeanInfoCacheFactory<K, V> createDefaultOgnlBeanInfoCacheFactory() {
return new DefaultOgnlBeanInfoCacheFactory<>(String.valueOf(10_000), BASIC.toString());
}
}
@@ -1061,7 +1061,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
OgnlValueStack stack2 = new OgnlValueStack(vs,
container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(RootAccessor.class), true);
(CompoundRootAccessor) container.getInstance(RootAccessor.class), new SecurityMemberAccess(true));
container.inject(stack2);
assertEquals(vs.getRoot(), stack2.getRoot());
@@ -26,12 +26,16 @@ import ognl.MemberAccess;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.struts2.ognl.ProviderAllowlist;
import org.apache.struts2.ognl.ThreadAllowlist;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
@@ -853,9 +857,11 @@ public class SecurityMemberAccessTest {
assertTrue("package java.lang. is accessible!", actual);
}
/**
* Test that the allowlist is enforced correctly for classes.
*/
@Test
public void classInclusion() throws Exception {
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
TestBean2 bean = new TestBean2();
@@ -868,6 +874,9 @@ public class SecurityMemberAccessTest {
assertTrue(sma.checkAllowlist(bean, method));
}
/**
* Test that the allowlist is enforced correctly for packages.
*/
@Test
public void packageInclusion() throws Exception {
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
@@ -882,6 +891,9 @@ public class SecurityMemberAccessTest {
assertTrue(sma.checkAllowlist(bean, method));
}
/**
* Test that the allowlist doesn't allow inherited methods unless the declaring class is also allowlisted.
*/
@Test
public void classInclusion_subclass() throws Exception {
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
@@ -893,6 +905,9 @@ public class SecurityMemberAccessTest {
assertFalse(sma.checkAllowlist(bean, method));
}
/**
* Test that the allowlist allows inherited methods when both the target and declaring class are allowlisted.
*/
@Test
public void classInclusion_subclass_both() throws Exception {
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
@@ -904,6 +919,10 @@ public class SecurityMemberAccessTest {
assertTrue(sma.checkAllowlist(bean, method));
}
/**
* Test that the allowlist doesn't allow inherited methods unless the package of the declaring class is also
* allowlisted.
*/
@Test
public void packageInclusion_subclass() throws Exception {
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
@@ -915,6 +934,37 @@ public class SecurityMemberAccessTest {
assertFalse(sma.checkAllowlist(bean, method));
}
/**
* When the allowlist is enabled and proxy object access is disallowed, Hibernate proxies should not be allowed.
*/
@Test
public void classInclusion_hibernateProxy_disallowProxyObjectAccess() throws Exception {
FooBarInterface proxyObject = mockHibernateProxy(new FooBar(), FooBarInterface.class);
Method proxyMethod = proxyObject.getClass().getMethod("fooLogic");
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
sma.useDisallowProxyObjectAccess(Boolean.TRUE.toString());
sma.useAllowlistClasses(FooBar.class.getName());
assertFalse(sma.checkAllowlist(proxyObject, proxyMethod));
}
/**
* When the allowlist is enabled and proxy object access is allowed, Hibernate proxies should be allowlisted based
* on their underlying target object. Class allowlisting should work as expected.
*/
@Test
public void classInclusion_hibernateProxy_allowProxyObjectAccess() throws Exception {
FooBarInterface proxyObject = mockHibernateProxy(new FooBar(), FooBarInterface.class);
Method proxyMethod = proxyObject.getClass().getMethod("fooLogic");
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
sma.useDisallowProxyObjectAccess(Boolean.FALSE.toString());
sma.useAllowlistClasses(FooBar.class.getName());
assertTrue(sma.checkAllowlist(proxyObject, proxyMethod));
}
@Test
public void packageInclusion_subclass_both() throws Exception {
sma.useEnforceAllowlistEnabled(Boolean.TRUE.toString());
@@ -931,6 +981,15 @@ public class SecurityMemberAccessTest {
private static String formGetterName(String propertyName) {
return "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
}
@SuppressWarnings("unchecked")
private static <T> T mockHibernateProxy(T originalObject, Class<T> proxyInterface) {
return (T) Proxy.newProxyInstance(
proxyInterface.getClassLoader(),
new Class<?>[]{proxyInterface, HibernateProxy.class},
new DummyHibernateProxyHandler(originalObject)
);
}
}
class FooBar implements FooBarInterface {
@@ -1042,10 +1101,28 @@ class StaticTester {
}
protected static Field getFieldByName(String fieldName) throws NoSuchFieldException {
if (fieldName != null && fieldName.length() > 0) {
if (fieldName != null && !fieldName.isEmpty()) {
return StaticTester.class.getDeclaredField(fieldName);
} else {
throw new NoSuchFieldException("field: " + fieldName + " does not exist");
}
}
}
class DummyHibernateProxyHandler implements InvocationHandler {
private final Object instance;
public DummyHibernateProxyHandler(Object instance) {
this.instance = instance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (HibernateProxy.class.getMethod("getHibernateLazyInitializer").equals(method)) {
LazyInitializer initializer = mock(LazyInitializer.class);
when(initializer.getImplementation()).thenReturn(instance);
return initializer;
}
return method.invoke(instance, args);
}
}
@@ -25,11 +25,12 @@ import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
import jakarta.servlet.http.Cookie;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsInternalTestCase;
import org.apache.struts2.action.CookiesAware;
import org.springframework.mock.web.MockHttpServletRequest;
import jakarta.servlet.http.Cookie;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -451,49 +452,6 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertFalse(excludedName.get(reqCookieName));
}
public void testActionCookieAwareWithStrutsInternalsAccess() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
String sessionCookieName = "session.userId";
String sessionCookieValue = "session.userId=1";
String appCookieName = "application.userId";
String appCookieValue = "application.userId=1";
String reqCookieName = "request.userId";
String reqCookieValue = "request.userId=1";
request.setCookies(
new Cookie(sessionCookieName, "1"),
new Cookie("1", sessionCookieValue),
new Cookie(appCookieName, "1"),
new Cookie("1", appCookieValue),
new Cookie(reqCookieName, "1"),
new Cookie("1", reqCookieValue)
);
ServletActionContext.setRequest(request);
final Map<String, Boolean> excludedName = new HashMap<>();
CookieInterceptor interceptor = new CookieInterceptor() {
@Override
protected boolean isAcceptableName(String name) {
boolean accepted = super.isAcceptableName(name);
excludedName.put(name, accepted);
return accepted;
}
};
interceptor.setExcludedPatternsChecker(new DefaultExcludedPatternsChecker());
interceptor.setAcceptedPatternsChecker(new DefaultAcceptedPatternsChecker());
interceptor.setCookiesName("*");
MockActionInvocation invocation = new MockActionInvocation();
invocation.setAction(new MockActionWithActionCookieAware());
interceptor.intercept(invocation);
assertFalse(excludedName.get(sessionCookieName));
assertFalse(excludedName.get(appCookieName));
assertFalse(excludedName.get(reqCookieName));
}
public static class MockActionWithCookieAware extends ActionSupport implements CookiesAware {
private static final long serialVersionUID = -6202290616812813386L;
@@ -503,46 +461,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
private String cookie2;
private String cookie3;
public void setCookiesMap(Map<String, String> cookies) {
this.cookies = cookies;
}
public Map getCookiesMap() {
return this.cookies;
}
public String getCookie1() {
return cookie1;
}
public void setCookie1(String cookie1) {
this.cookie1 = cookie1;
}
public String getCookie2() {
return cookie2;
}
public void setCookie2(String cookie2) {
this.cookie2 = cookie2;
}
public String getCookie3() {
return cookie3;
}
public void setCookie3(String cookie3) {
this.cookie3 = cookie3;
}
}
public static class MockActionWithActionCookieAware extends ActionSupport implements org.apache.struts2.action.CookiesAware {
private Map cookies = Collections.EMPTY_MAP;
private String cookie1;
private String cookie2;
private String cookie3;
@Override
public void withCookies(Map<String, String> cookies) {
this.cookies = cookies;
}
@@ -36,6 +36,7 @@ import com.opensymphony.xwork2.interceptor.ValidationAware;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.ognl.OgnlValueStack;
import com.opensymphony.xwork2.ognl.OgnlValueStackFactory;
import com.opensymphony.xwork2.ognl.SecurityMemberAccess;
import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.ognl.accessor.RootAccessor;
import com.opensymphony.xwork2.util.ValueStack;
@@ -90,7 +91,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
put("test%test", "test%test");
}
};
pi.setParameters(a, stack, HttpParameters.create(parameters).build());
pi.applyParameters(a, stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
@@ -113,18 +114,20 @@ public class ParametersInterceptorTest extends XWorkTestCase {
// when
ValidateAction action = new ValidateAction();
pi.setParameters(action, vs, HttpParameters.create(params).build());
pi.applyParameters(action, vs, HttpParameters.create(params).build());
// then
assertEquals(3, action.getActionMessages().size());
assertEquals(3, action.getActionErrors().size());
String msg1 = action.getActionMessage(0);
String msg2 = action.getActionMessage(1);
String msg3 = action.getActionMessage(2);
List<String> actionErrors = new ArrayList<>(action.getActionErrors());
assertEquals("Error setting expression 'expression' with value '#f=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#f.setAccessible(true),#f.set(#_memberAccess,true),#req=@org.apache.struts2.ServletActionContext@getRequest(),#resp=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#resp.println(#req.getRealPath('/')),#resp.close()'", msg1);
assertEquals("Error setting expression 'name' with value '(#context[\"xwork.MethodAccessor.denyMethodExecution\"]= new java.lang.Boolean(false), #_memberAccess[\"allowStaticMethodAccess\"]= new java.lang.Boolean(true), @java.lang.Runtime@getRuntime().exec('mkdir /tmp/PWNAGE'))(meh)'", msg2);
assertEquals("Error setting expression 'top['name'](0)' with value 'true'", msg3);
String msg1 = actionErrors.get(0);
String msg2 = actionErrors.get(1);
String msg3 = actionErrors.get(2);
assertEquals("Unexpected Exception caught setting 'expression' on 'class org.apache.struts2.interceptor.parameter.ValidateAction: Error setting expression 'expression' with value '#f=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#f.setAccessible(true),#f.set(#_memberAccess,true),#req=@org.apache.struts2.ServletActionContext@getRequest(),#resp=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#resp.println(#req.getRealPath('/')),#resp.close()'", msg1);
assertEquals("Unexpected Exception caught setting 'name' on 'class org.apache.struts2.interceptor.parameter.ValidateAction: Error setting expression 'name' with value '(#context[\"xwork.MethodAccessor.denyMethodExecution\"]= new java.lang.Boolean(false), #_memberAccess[\"allowStaticMethodAccess\"]= new java.lang.Boolean(true), @java.lang.Runtime@getRuntime().exec('mkdir /tmp/PWNAGE'))(meh)'", msg2);
assertEquals("Unexpected Exception caught setting 'top['name'](0)' on 'class org.apache.struts2.interceptor.parameter.ValidateAction: Error setting expression 'top['name'](0)' with value 'true'", msg3);
assertNull(action.getName());
}
@@ -158,7 +161,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
// when
ValidateAction action = new ValidateAction();
pi.setParameters(action, vs, HttpParameters.create(params).build());
pi.applyParameters(action, vs, HttpParameters.create(params).build());
// then
assertEquals(0, action.getActionMessages().size());
@@ -198,18 +201,19 @@ public class ParametersInterceptorTest extends XWorkTestCase {
// when
ValidateAction action = new ValidateAction();
pi.setParameters(action, vs, HttpParameters.create(params).build());
pi.applyParameters(action, vs, HttpParameters.create(params).build());
// then
assertEquals(3, action.getActionMessages().size());
assertEquals(3, action.getActionErrors().size());
String msg1 = action.getActionMessage(0);
String msg2 = action.getActionMessage(1);
String msg3 = action.getActionMessage(2);
List<String> actionErrors = new ArrayList<>(action.getActionErrors());
String msg1 = actionErrors.get(0);
String msg2 = actionErrors.get(1);
String msg3 = actionErrors.get(2);
assertEquals("Error setting expression 'class.classLoader.defaultAssertionStatus' with value 'true'", msg1);
assertEquals("Error setting expression 'class.classLoader.jarPath' with value 'bad'", msg2);
assertEquals("Error setting expression 'model.class.classLoader.jarPath' with value 'very bad'", msg3);
assertEquals("Unexpected Exception caught setting 'class.classLoader.defaultAssertionStatus' on 'class org.apache.struts2.interceptor.parameter.ValidateAction: Error setting expression 'class.classLoader.defaultAssertionStatus' with value 'true'", msg1);
assertEquals("Unexpected Exception caught setting 'class.classLoader.jarPath' on 'class org.apache.struts2.interceptor.parameter.ValidateAction: Error setting expression 'class.classLoader.jarPath' with value 'bad'", msg2);
assertEquals("Unexpected Exception caught setting 'model.class.classLoader.jarPath' on 'class org.apache.struts2.interceptor.parameter.ValidateAction: Error setting expression 'model.class.classLoader.jarPath' with value 'very bad'", msg3);
assertFalse(excluded.get(pollution1));
assertFalse(excluded.get(pollution2));
@@ -317,7 +321,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
// when
ValidateAction action = new ValidateAction();
pi.setParameters(action, vs, HttpParameters.create(params).build());
pi.applyParameters(action, vs, HttpParameters.create(params).build());
// then
assertEquals(0, action.getActionMessages().size());
@@ -432,7 +436,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
parameters.put("huuhaa", "");
Action action = new SimpleAction();
parametersInterceptor.setParameters(action, stack, HttpParameters.create(parameters).build());
parametersInterceptor.applyParameters(action, stack, HttpParameters.create(parameters).build());
assertEquals(1, actual.size());
}
@@ -582,8 +586,8 @@ public class ParametersInterceptorTest extends XWorkTestCase {
container.inject(config.getInterceptors().get(0).getInterceptor());
ActionProxy proxy = actionProxyFactory.createActionProxy("", MockConfigurationProvider.PARAM_INTERCEPTOR_ACTION_NAME, null, extraContext.getContextMap());
proxy.execute();
final String actionMessage = "" + ((SimpleAction) proxy.getAction()).getActionMessages().toArray()[0];
assertTrue(actionMessage.contains("Error setting expression 'not_a_property' with value 'There is no action property named like this'"));
final String actionError = "" + ((SimpleAction) proxy.getAction()).getActionErrors().toArray()[0];
assertTrue(actionError.contains("Error setting expression 'not_a_property' with value 'There is no action property named like this'"));
}
public void testNonexistentParametersAreIgnoredInProductionMode() throws Exception {
@@ -626,7 +630,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
parameters.put("user.name", "Superman");
Action action = new SimpleAction();
pi.setParameters(action, stack, HttpParameters.create(parameters).build());
pi.applyParameters(action, stack, HttpParameters.create(parameters).build());
assertEquals("ordered should be false by default", false, pi.isOrdered());
assertEquals(2, actual.size());
@@ -653,7 +657,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
parameters.put("user.name", "Superman");
Action action = new SimpleAction();
pi.setParameters(action, stack, HttpParameters.create(parameters).build());
pi.applyParameters(action, stack, HttpParameters.create(parameters).build());
assertEquals(true, pi.isOrdered());
assertEquals(3, actual.size());
@@ -693,7 +697,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
put("fooKey", "fooValue");
}
};
pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
pi.applyParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
@@ -724,7 +728,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
};
// when
interceptor.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
interceptor.applyParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
// then
assertEquals(expected, actual);
@@ -751,7 +755,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
};
// when
interceptor.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
interceptor.applyParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
// then
assertEquals(expected, actual);
@@ -803,7 +807,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
put("fooKey2", "");
}
};
pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
pi.applyParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
@@ -840,7 +844,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
put("fooKey2", "");
}
};
pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
pi.applyParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
@@ -879,7 +883,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
put("fooKey2", "");
}
};
pi.setParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
pi.applyParameters(new NoParametersAction(), stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
@@ -923,7 +927,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
put("fooKey3", "");
}
};
pi.setParameters(a, stack, HttpParameters.create(parameters).build());
pi.applyParameters(a, stack, HttpParameters.create(parameters).build());
assertEquals(expected, actual);
}
@@ -961,7 +965,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
ValueStack stack = new OgnlValueStack(
container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(RootAccessor.class),
container.getInstance(TextProvider.class, "system"), true) {
container.getInstance(TextProvider.class, "system"), new SecurityMemberAccess(true)) {
@Override
public void setValue(String expr, Object value) {
actual.put(expr, value);
@@ -1014,59 +1018,65 @@ public class ParametersInterceptorTest extends XWorkTestCase {
class ValidateAction implements ValidationAware {
private final List<String> messages = new LinkedList<>();
private final List<String> errors = new LinkedList<>();
private String name;
@Override
public void setActionErrors(Collection<String> errorMessages) {
}
@Override
public Collection<String> getActionErrors() {
return null;
return errors;
}
@Override
public void setActionMessages(Collection<String> messages) {
}
@Override
public Collection<String> getActionMessages() {
return messages;
}
@Override
public void setFieldErrors(Map<String, List<String>> errorMap) {
}
@Override
public Map<String, List<String>> getFieldErrors() {
return null;
}
@Override
public void addActionError(String anErrorMessage) {
errors.add(anErrorMessage);
}
@Override
public void addActionMessage(String aMessage) {
messages.add(aMessage);
}
@Override
public void addFieldError(String fieldName, String errorMessage) {
}
@Override
public boolean hasActionErrors() {
return false;
return !errors.isEmpty();
}
@Override
public boolean hasActionMessages() {
return !messages.isEmpty();
}
public boolean hasErrors() {
return false;
}
@Override
public boolean hasFieldErrors() {
return false;
}
public String getActionMessage(int index) {
return messages.get(index);
}
public String getName() {
return name;
}
@@ -112,6 +112,14 @@ public class StrutsQueryStringParserTest {
assertEquals("test", queryParameters.getQueryFragment());
}
@Test
public void shouldHandleOnlyFragment() {
QueryStringParser.Result queryParameters = parser.parse("#test");
assertTrue(queryParameters.getQueryParams().isEmpty());
assertEquals("test", queryParameters.getQueryFragment());
}
@Before
public void setUp() throws Exception {
this.parser = new StrutsQueryStringParser(new StrutsUrlDecoder());
@@ -2068,6 +2068,42 @@ public class URLTagTest extends AbstractUITagTest {
strutsBodyTagsAreReflectionEqual(tag, freshTag));
}
public void testQueryParamsAndFragment() throws Exception {
request.setRequestURI("/public/about");
tag.setAction("company");
tag.setValue("/books?hl=en&lr=Y&redir_esc=y#v=twopage&q&f=false");
tag.setEscapeAmp("false");
tag.doStartTag();
tag.doEndTag();
assertEquals("/books?hl=en&lr=Y&redir_esc=y#v=twopage&q&f=false", writer.toString());
}
public void testDoubleEqualSigns() throws Exception {
request.setRequestURI("/public/about");
tag.setAction("company");
tag.setValue("/PublicationsDetail.aspx?ID=GjTu91suYQI=&t=1");
tag.setEscapeAmp("false");
tag.doStartTag();
tag.doEndTag();
assertEquals("/PublicationsDetail.aspx?ID=GjTu91suYQI%3D&t=1", writer.toString());
}
public void testOnlyFragment() throws Exception {
request.setRequestURI("/public/about");
tag.setAction("company");
tag.setValue("/books#v=twopage&q&f=false");
tag.setEscapeAmp("false");
tag.doStartTag();
tag.doEndTag();
assertEquals("/books#v=twopage&q&f=false", writer.toString());
}
@Override
protected void setUp() throws Exception {
super.setUp();
-4
View File
@@ -1,4 +0,0 @@
# Struts 2 Freemarker Jakarta
This uses the eclipse transformer maven plugin to make the Freemarker dependency Jakarta EE 9+ compatible.
-69
View File
@@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jakarta</artifactId>
<version>7.0.0-M7</version>
</parent>
<artifactId>struts2-freemarker-jakarta</artifactId>
<packaging>jar</packaging>
<name>Struts 2 Jakarta EE Compatible Freemarker</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.site.skip>true</maven.site.skip>
<maven.site.deploy.skip>true</maven.site.deploy.skip>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.transformer</groupId>
<artifactId>transformer-maven-plugin</artifactId>
<version>0.5.0</version>
<extensions>true</extensions>
<configuration>
<rules>
<jakartaDefaults>true</jakartaDefaults>
</rules>
</configuration>
<executions>
<execution>
<id>eclipse-transformer-freemarker-jar</id>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<artifact>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</artifact>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
+1 -2
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-jakarta</artifactId>
<packaging>pom</packaging>
@@ -37,7 +37,6 @@
</properties>
<modules>
<module>freemarker-jakarta</module>
<module>sitemesh2-jakarta</module>
<module>velocity-tools-view-jakarta</module>
<module>velocity-tools-jsp-jakarta</module>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jakarta</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-sitemesh2-jakarta</artifactId>
<packaging>jar</packaging>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jakarta</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-velocity-tools-jsp-jakarta</artifactId>
<packaging>jar</packaging>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jakarta</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-velocity-tools-view-jakarta</artifactId>
<packaging>jar</packaging>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-async-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+3 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-cdi-plugin</artifactId>
@@ -43,11 +43,13 @@
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core-impl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-config-browser-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-convention-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-jasperreports-plugin</artifactId>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-javatemplates-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-jfreechart-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-json-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-junit-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-plugins</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-rest-plugin</artifactId>
@@ -28,20 +28,24 @@ import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.mock.MockActionProxy;
import com.opensymphony.xwork2.mock.MockInterceptor;
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.util.XWorkTestCaseHelper;
import jakarta.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.ognl.StrutsOgnlGuard;
import org.apache.struts2.result.HttpHeaderResult;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.opensymphony.xwork2.ognl.OgnlCacheFactory.CacheType.BASIC;
import static jakarta.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
public class RestActionInvocationTest extends TestCase {
@@ -53,7 +57,7 @@ public class RestActionInvocationTest extends TestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
restActionInvocation = new RestActionInvocationTester();
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
@@ -61,7 +65,7 @@ public class RestActionInvocationTest extends TestCase {
ServletActionContext.setResponse(response);
}
/**
* Test the correct action results: null, String, HttpHeaders, Result
* @throws Exception
@@ -71,12 +75,12 @@ public class RestActionInvocationTest extends TestCase {
Object methodResult = "index";
ActionConfig actionConfig = restActionInvocation.getProxy().getConfig();
assertEquals("index", restActionInvocation.saveResult(actionConfig, methodResult));
setUp();
methodResult = new DefaultHttpHeaders("show");
assertEquals("show", restActionInvocation.saveResult(actionConfig, methodResult));
assertEquals(methodResult, restActionInvocation.httpHeaders);
setUp();
methodResult = new HttpHeaderResult(HttpServletResponse.SC_ACCEPTED);
assertEquals(null, restActionInvocation.saveResult(actionConfig, methodResult));
@@ -89,18 +93,18 @@ public class RestActionInvocationTest extends TestCase {
// ko
assertFalse(true);
} catch (ConfigurationException c) {
// ok, object not allowed
}
}
/**
* Test the target selection: exception, error messages, model and null
* @throws Exception
*/
public void testSelectTarget() throws Exception {
// Exception
Exception e = new Exception();
restActionInvocation.getStack().set("exception", e);
@@ -118,7 +122,7 @@ public class RestActionInvocationTest extends TestCase {
errors.put("actionErrors", list);
restActionInvocation.selectTarget();
assertEquals(errors, restActionInvocation.target);
// Model with get and no content in post, put, delete
setUp();
RestAction restAction = (RestAction)restActionInvocation.getAction();
@@ -168,18 +172,18 @@ public class RestActionInvocationTest extends TestCase {
};
model.add("Item");
restAction.model = model;
restActionInvocation.processResult();
assertEquals(SC_NOT_MODIFIED, response.getStatus());
}
/**
* Test the default error result.
* @throws Exception
*/
public void testDefaultErrorResult() throws Exception {
// Exception
Exception e = new Exception();
restActionInvocation.getStack().set("exception", e);
@@ -189,24 +193,24 @@ public class RestActionInvocationTest extends TestCase {
List<String> model = new ArrayList<String>();
model.add("Item");
restAction.model = model;
restActionInvocation.setDefaultErrorResultName("default-error");
ResultConfig resultConfig = new ResultConfig.Builder("default-error",
ResultConfig resultConfig = new ResultConfig.Builder("default-error",
"org.apache.struts2.result.HttpHeaderResult")
.addParam("status", "123").build();
ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest",
ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest",
"RestAction", "org.apache.rest.RestAction")
.addResultConfig(resultConfig)
.build();
((MockActionProxy)restActionInvocation.getProxy()).setConfig(actionConfig);
restActionInvocation.processResult();
assertEquals(123, response.getStatus());
}
public void testNoResult() throws Exception {
RestAction restAction = (RestAction)restActionInvocation.getAction();
List<String> model = new ArrayList<String>();
model.add("Item");
@@ -219,35 +223,39 @@ public class RestActionInvocationTest extends TestCase {
// ko
assertFalse(true);
} catch (ConfigurationException c) {
// ok, no result
}
}
/**
* Test the global execution
* @throws Exception
*/
public void testInvoke() throws Exception {
// Default index method return 'success'
((MockActionProxy)restActionInvocation.getProxy()).setMethod("index");
// Define result 'success'
ResultConfig resultConfig = new ResultConfig.Builder("success",
ResultConfig resultConfig = new ResultConfig.Builder("success",
"org.apache.struts2.result.HttpHeaderResult")
.addParam("status", "123").build();
ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest",
ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest",
"RestAction", "org.apache.rest.RestAction")
.addResultConfig(resultConfig)
.build();
((MockActionProxy)restActionInvocation.getProxy()).setConfig(actionConfig);
request.setMethod("GET");
restActionInvocation.setOgnlUtil(new OgnlUtil());
restActionInvocation.setOgnlUtil(new OgnlUtil(
new DefaultOgnlExpressionCacheFactory<>(String.valueOf(10_000), BASIC.toString()),
new DefaultOgnlBeanInfoCacheFactory<>(String.valueOf(10_000), BASIC.toString()),
new StrutsOgnlGuard()
));
restActionInvocation.invoke();
assertEquals(123, response.getStatus());
@@ -264,7 +272,7 @@ public class RestActionInvocationTest extends TestCase {
interceptorMappings.add(new InterceptorMapping("interceptor", mockInterceptor));
interceptors = interceptorMappings.iterator();
MockActionProxy actionProxy = new MockActionProxy();
ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest",
ActionConfig actionConfig = new ActionConfig.Builder("org.apache.rest",
"RestAction", "org.apache.rest.RestAction").build();
actionProxy.setConfig(actionConfig);
proxy = actionProxy;
@@ -280,18 +288,18 @@ public class RestActionInvocationTest extends TestCase {
container = ActionContext.getContext().getContainer();
stack = ActionContext.getContext().getValueStack();
objectFactory = container.getInstance(ObjectFactory.class);
}
}
class RestAction extends RestActionSupport implements ModelDriven<List<String>> {
List<String> model;
public List<String> getModel() {
return model;
}
}
}
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-sitemesh-plugin</artifactId>
@@ -22,6 +22,7 @@ import com.opensymphony.module.sitemesh.HTMLPage;
import com.opensymphony.module.sitemesh.RequestConstants;
import com.opensymphony.xwork2.ActionContext;
import freemarker.core.InvalidReferenceException;
import freemarker.ext.jakarta.servlet.FreemarkerServlet;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.SimpleHash;
@@ -54,10 +55,9 @@ import java.util.Locale;
* Freemarker Manager in Struts instead of creating it's
* own manager</p>
*/
public class FreemarkerDecoratorServlet extends freemarker.ext.servlet.FreemarkerServlet {
public class FreemarkerDecoratorServlet extends FreemarkerServlet {
private static final Logger LOG = LogManager.getLogger(FreemarkerDecoratorServlet.class);
public static final long serialVersionUID = -2440216393145762479L;
protected FreemarkerManager freemarkerManager;
protected String templatePath;
@@ -273,7 +273,7 @@ public class FreemarkerDecoratorServlet extends freemarker.ext.servlet.Freemarke
* @param response the actual HTTP response
* @param template the template that will get executed
* @return true to process the template, false to suppress template processing.
* @see freemarker.ext.servlet.FreemarkerServlet#preTemplateProcess(jakarta.servlet.http.HttpServletRequest, jakarta.servlet.http.HttpServletResponse, freemarker.template.Template, freemarker.template.TemplateModel)
* @see FreemarkerServlet#preTemplateProcess(jakarta.servlet.http.HttpServletRequest, jakarta.servlet.http.HttpServletResponse, freemarker.template.Template, freemarker.template.TemplateModel)
*/
protected boolean preTemplateProcess(HttpServletRequest request, HttpServletResponse response, Template template, TemplateModel templateModel) throws ServletException, IOException {
boolean result = super.preTemplateProcess(request, response, template, templateModel);
@@ -23,16 +23,15 @@ import com.opensymphony.sitemesh.Content;
import com.opensymphony.sitemesh.compatability.Content2HTMLPage;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.inject.Inject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.views.velocity.VelocityManager;
import org.apache.struts2.views.velocity.VelocityManagerInterface;
import org.apache.velocity.context.Context;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.views.velocity.VelocityManagerInterface;
import org.apache.velocity.context.Context;
import java.io.IOException;
import java.io.PrintWriter;
@@ -49,14 +48,6 @@ public class OldDecorator2NewStrutsVelocityDecorator extends OldDecorator2NewStr
velocityManager = mgr;
}
/**
* @deprecated since 6.4.0
*/
@Deprecated
public static void setVelocityManager(VelocityManager mgr) {
setVelocityManager((VelocityManagerInterface) mgr);
}
public OldDecorator2NewStrutsVelocityDecorator(com.opensymphony.module.sitemesh.Decorator oldDecorator) {
this.oldDecorator = oldDecorator;
}
@@ -24,29 +24,19 @@ import com.opensymphony.sitemesh.DecoratorSelector;
import com.opensymphony.sitemesh.webapp.SiteMeshFilter;
import com.opensymphony.sitemesh.webapp.SiteMeshWebAppContext;
import com.opensymphony.xwork2.inject.Inject;
import org.apache.struts2.views.velocity.VelocityManager;
import jakarta.servlet.FilterConfig;
import org.apache.struts2.views.velocity.VelocityManagerInterface;
import jakarta.servlet.*;
/**
* Core Filter for integrating SiteMesh into a Java web application.
*/
public class VelocityPageFilter extends SiteMeshFilter {
@Inject(required=false)
@Inject(required = false)
public static void setVelocityManager(VelocityManagerInterface mgr) {
OldDecorator2NewStrutsVelocityDecorator.setVelocityManager(mgr);
}
/**
* @deprecated since 6.4.0
*/
@Deprecated
public static void setVelocityManager(VelocityManager mgr) {
setVelocityManager((VelocityManagerInterface) mgr);
}
private FilterConfig filterConfig;
public void init(FilterConfig filterConfig) {
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-spring-plugin</artifactId>
@@ -19,76 +19,72 @@
package com.opensymphony.xwork2.ognl;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.XWorkTestCase;
import com.opensymphony.xwork2.XWorkJUnit4TestCase;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import org.apache.struts2.config.StrutsXmlConfigurationProvider;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Member;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class SecurityMemberAccessProxyTest extends XWorkTestCase {
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class SecurityMemberAccessProxyTest extends XWorkJUnit4TestCase {
private static final String PROXY_MEMBER_METHOD = "isExposeProxy";
private static final String TEST_SUB_BEAN_CLASS_METHOD = "getIssueId";
private Map<String, Object> context;
private ActionProxy proxy;
private Map<String, Member> members;
private final SecurityMemberAccess sma = new SecurityMemberAccess(true);
private final String PROXY_MEMBER_METHOD = "isExposeProxy";
private final String TEST_SUB_BEAN_CLASS_METHOD = "setIssueId";
private final SecurityMemberAccess sma = new SecurityMemberAccess(null, null);
private Member proxyObjectProxyMember;
private Member proxyObjectNonProxyMember;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
context = new HashMap<>();
// Set up XWork
XmlConfigurationProvider provider = new StrutsXmlConfigurationProvider("com/opensymphony/xwork2/spring/actionContext-xwork.xml");
container.inject(provider);
loadConfigurationProviders(provider);
// Setup proxy object
setupProxy();
}
public void testProxyAccessIsBlocked() throws Exception {
members.values().forEach(member -> {
// When disallowProxyObjectAccess is set to true, and disallowProxyMemberAccess is set to false, the proxy access is blocked
sma.useDisallowProxyObjectAccess(Boolean.TRUE.toString());
sma.useDisallowProxyMemberAccess(Boolean.FALSE.toString());
assertFalse(sma.isAccessible(context, proxy.getAction(), member, ""));
// When disallowProxyObjectAccess is set to true, and disallowProxyMemberAccess is set to true, the proxy access is blocked
sma.useDisallowProxyObjectAccess(Boolean.TRUE.toString());
sma.useDisallowProxyMemberAccess(Boolean.TRUE.toString());
assertFalse(sma.isAccessible(context, proxy.getAction(), member, ""));
});
// When disallowProxyObjectAccess is set to false, and disallowProxyMemberAccess is set to true, the proxy member access is blocked
sma.useDisallowProxyObjectAccess(Boolean.FALSE.toString());
sma.useDisallowProxyMemberAccess(Boolean.TRUE.toString());
assertFalse(sma.isAccessible(context, proxy.getAction(), members.get(PROXY_MEMBER_METHOD), ""));
}
public void testProxyAccessIsAccessible() throws Exception {
members.values().forEach(member -> {
// When disallowProxyObjectAccess is set to false, and disallowProxyMemberAccess is set to false, the proxy access is allowed
sma.useDisallowProxyObjectAccess(Boolean.FALSE.toString());
sma.useDisallowProxyMemberAccess(Boolean.FALSE.toString());
assertTrue(sma.isAccessible(context, proxy.getAction(), member, ""));
});
// When disallowProxyObjectAccess is set to false, and disallowProxyMemberAccess is set to true, the original class member access is allowed
sma.useDisallowProxyObjectAccess(Boolean.FALSE.toString());
sma.useDisallowProxyMemberAccess(Boolean.TRUE.toString());
assertTrue(sma.isAccessible(context, proxy.getAction(), members.get(TEST_SUB_BEAN_CLASS_METHOD), ""));
}
private void setupProxy() throws NoSuchMethodException {
context = new HashMap<>();
proxy = actionProxyFactory.createActionProxy(null, "chaintoAOPedTestSubBeanAction", null, context);
proxyObjectProxyMember = proxy.getAction().getClass().getMethod(PROXY_MEMBER_METHOD);
proxyObjectNonProxyMember = proxy.getAction().getClass().getMethod(TEST_SUB_BEAN_CLASS_METHOD);
}
members = new HashMap<>();
// method is proxy member
members.put(PROXY_MEMBER_METHOD, proxy.getAction().getClass().getMethod(PROXY_MEMBER_METHOD));
// method is not proxy member but from POJO class
members.put(TEST_SUB_BEAN_CLASS_METHOD, proxy.getAction().getClass().getMethod(TEST_SUB_BEAN_CLASS_METHOD, String.class));
/**
* When {@code disallowProxyObjectAccess} is {@code true}, proxy access is blocked irrespective of
* {@code disallowProxyMemberAccess} value and irrespective of whether the member itself originates from the proxy.
*/
@Test
public void disallowProxyObjectAccess() {
sma.useDisallowProxyObjectAccess(Boolean.TRUE.toString());
Arrays.asList(proxyObjectProxyMember, proxyObjectNonProxyMember).forEach(member ->
Arrays.asList(Boolean.TRUE, Boolean.FALSE).forEach(disallowProxyMemberAccess -> {
sma.useDisallowProxyMemberAccess(disallowProxyMemberAccess.toString());
assertFalse(sma.isAccessible(context, proxy.getAction(), member, ""));
})
);
}
@Test
public void disallowProxyMemberAccess() {
sma.useDisallowProxyObjectAccess(Boolean.FALSE.toString());
sma.useDisallowProxyMemberAccess(Boolean.TRUE.toString());
assertFalse(sma.isAccessible(context, proxy.getAction(), proxyObjectProxyMember, ""));
assertTrue(sma.isAccessible(context, proxy.getAction(), proxyObjectNonProxyMember, ""));
}
@Test
public void allowAllProxyAccess() {
sma.useDisallowProxyObjectAccess(Boolean.FALSE.toString());
sma.useDisallowProxyMemberAccess(Boolean.FALSE.toString());
assertTrue(sma.isAccessible(context, proxy.getAction(), proxyObjectProxyMember, ""));
assertTrue(sma.isAccessible(context, proxy.getAction(), proxyObjectNonProxyMember, ""));
}
}
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-testng-plugin</artifactId>
+2 -2
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-tiles-plugin</artifactId>
@@ -40,7 +40,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.2.0</version>
<version>3.3.0</version>
<executions>
<execution>
<phase>compile</phase>
@@ -20,7 +20,7 @@
package org.apache.tiles.request.freemarker;
import freemarker.core.Environment;
import freemarker.ext.servlet.HttpRequestHashModel;
import freemarker.ext.jakarta.servlet.HttpRequestHashModel;
import org.apache.tiles.request.AbstractViewRequest;
import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.DispatchRequest;
@@ -19,9 +19,9 @@
package org.apache.tiles.request.freemarker;
import freemarker.core.Environment;
import freemarker.ext.servlet.FreemarkerServlet;
import freemarker.ext.servlet.HttpRequestHashModel;
import freemarker.ext.servlet.ServletContextHashModel;
import freemarker.ext.jakarta.servlet.FreemarkerServlet;
import freemarker.ext.jakarta.servlet.HttpRequestHashModel;
import freemarker.ext.jakarta.servlet.ServletContextHashModel;
import freemarker.template.TemplateModelException;
import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.servlet.ServletUtil;
@@ -21,7 +21,7 @@ package org.apache.tiles.request.freemarker.servlet;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.ext.jakarta.servlet.WebappTemplateLoader;
import jakarta.servlet.ServletContext;
import java.io.IOException;
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-velocity-plugin</artifactId>
@@ -22,24 +22,23 @@ import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.result.StrutsResultSupport;
import org.apache.struts2.views.JspSupportServlet;
import org.apache.struts2.views.velocity.VelocityManager;
import org.apache.struts2.views.velocity.VelocityManagerInterface;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.jsp.JspFactory;
import jakarta.servlet.jsp.PageContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.result.StrutsResultSupport;
import org.apache.struts2.views.JspSupportServlet;
import org.apache.struts2.views.velocity.VelocityManagerInterface;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import java.io.OutputStreamWriter;
import java.io.Writer;
@@ -109,14 +108,6 @@ public class VelocityResult extends StrutsResultSupport {
this.velocityManager = mgr;
}
/**
* @deprecated since 6.4.0
*/
@Deprecated
public void setVelocityManager(VelocityManager mgr) {
setVelocityManager((VelocityManagerInterface) mgr);
}
/**
* Creates a Velocity context from the action, loads a Velocity template and executes the
* template. Output is written to the servlet output stream.
@@ -248,16 +239,4 @@ public class VelocityResult extends StrutsResultSupport {
String location) {
return velocityManager.createContext(stack, request, response);
}
/**
* @deprecated since 6.4.0
*/
@Deprecated
protected Context createContext(VelocityManager velocityManager,
ValueStack stack,
HttpServletRequest request,
HttpServletResponse response,
String location) {
return createContext((VelocityManagerInterface) velocityManager, stack, request, response, location);
}
}
@@ -19,20 +19,19 @@
package org.apache.struts2.views.velocity.template;
import com.opensymphony.xwork2.inject.Inject;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.components.template.BaseTemplateEngine;
import org.apache.struts2.components.template.Template;
import org.apache.struts2.components.template.TemplateRenderingContext;
import org.apache.struts2.views.velocity.VelocityManager;
import org.apache.struts2.views.velocity.VelocityManagerInterface;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.Writer;
import java.util.List;
import java.util.Map;
@@ -50,14 +49,6 @@ public class VelocityTemplateEngine extends BaseTemplateEngine {
this.velocityManager = mgr;
}
/**
* @deprecated since 6.4.0
*/
@Deprecated
public void setVelocityManager(VelocityManager mgr) {
setVelocityManager((VelocityManagerInterface) mgr);
}
public void renderTemplate(TemplateRenderingContext templateContext) throws Exception {
// get the various items required from the stack
Map actionContext = templateContext.getStack().getContext();
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
</parent>
<artifactId>struts2-xslt-plugin</artifactId>
+6 -17
View File
@@ -29,7 +29,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>struts2-parent</artifactId>
<version>7.0.0-M7</version>
<version>7.0.0-M8</version>
<packaging>pom</packaging>
<name>Struts 2</name>
<url>https://struts.apache.org/</url>
@@ -51,7 +51,7 @@
<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_7_0_0_M7</tag>
<tag>STRUTS_7_0_0_M8</tag>
</scm>
<issueManagement>
@@ -104,7 +104,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.outputTimestamp>2024-06-12T05:40:09Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2024-07-11T07:43:18Z</project.build.outputTimestamp>
<maven.compiler.release>17</maven.compiler.release>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
@@ -352,7 +352,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
<version>3.5.0</version>
<executions>
<execution>
<id>enforce</id>
@@ -506,19 +506,8 @@
<groupId>org.apache.struts</groupId>
<artifactId>struts-annotations</artifactId>
<version>1.0.8</version>
<exclusions>
<exclusion>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-freemarker-jakarta</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
@@ -641,7 +630,7 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.main</artifactId>
<version>6.0.3</version>
<version>7.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
@@ -854,7 +843,7 @@
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.8.0</version>
<version>1.9.0</version>
</dependency>
<!-- Mocks for unit testing (by Spring) -->